diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-24 21:12:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-24 21:12:15 -0400 |
commit | 9cf1848278a41f8d5f69b26bca546cfd2d5677d8 (patch) | |
tree | 2628cd3e8e3ca1acfe81e636b082c285d97640d9 /drivers | |
parent | 00cec111ac477ba71c99043358f17e9bb4d335fe (diff) | |
parent | 03e04f048d2774aabd126fbad84729d4ba9dc40a (diff) |
Merge branch 'akpm' (incoming from Andrew Morton)
Merge fixes from Andrew Morton:
"A bunch of fixes and one simple fbdev driver which missed the merge
window because people will still talking about it (to no great
effect)."
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (30 commits)
aio: fix kioctx not being freed after cancellation at exit time
mm/pagewalk.c: walk_page_range should avoid VM_PFNMAP areas
drivers/rtc/rtc-max8998.c: check for pdata presence before dereferencing
ocfs2: goto out_unlock if ocfs2_get_clusters_nocache() failed in ocfs2_fiemap()
random: fix accounting race condition with lockless irq entropy_count update
drivers/char/random.c: fix priming of last_data
mm/memory_hotplug.c: fix printk format warnings
nilfs2: fix issue of nilfs_set_page_dirty() for page at EOF boundary
drivers/block/brd.c: fix brd_lookup_page() race
fbdev: FB_GOLDFISH should depend on HAS_DMA
drivers/rtc/rtc-pl031.c: pass correct pointer to free_irq()
auditfilter.c: fix kernel-doc warnings
aio: fix io_getevents documentation
revert "selftest: add simple test for soft-dirty bit"
drivers/leds/leds-ot200.c: fix error caused by shifted mask
mm/THP: use pmd_populate() to update the pmd with pgtable_t pointer
linux/kernel.h: fix kernel-doc warning
mm compaction: fix of improper cache flush in migration code
rapidio/tsi721: fix bug in MSI interrupt handling
hfs: avoid crash in hfs_bnode_create
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/brd.c | 4 | ||||
-rw-r--r-- | drivers/block/xsysace.c | 3 | ||||
-rw-r--r-- | drivers/char/random.c | 54 | ||||
-rw-r--r-- | drivers/leds/leds-ot200.c | 14 | ||||
-rw-r--r-- | drivers/rapidio/Kconfig | 20 | ||||
-rw-r--r-- | drivers/rapidio/Makefile | 3 | ||||
-rw-r--r-- | drivers/rapidio/devices/tsi721.c | 12 | ||||
-rw-r--r-- | drivers/rapidio/rio-driver.c | 8 | ||||
-rw-r--r-- | drivers/rapidio/rio-scan.c | 190 | ||||
-rw-r--r-- | drivers/rapidio/rio-sysfs.c | 45 | ||||
-rw-r--r-- | drivers/rapidio/rio.c | 246 | ||||
-rw-r--r-- | drivers/rapidio/rio.h | 13 | ||||
-rw-r--r-- | drivers/rtc/rtc-max8998.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-pl031.c | 2 | ||||
-rw-r--r-- | drivers/video/Kconfig | 19 | ||||
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/simplefb.c | 234 |
17 files changed, 692 insertions, 178 deletions
diff --git a/drivers/block/brd.c b/drivers/block/brd.c index f1a29f8e9d33..9bf4371755f2 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c | |||
@@ -117,13 +117,13 @@ static struct page *brd_insert_page(struct brd_device *brd, sector_t sector) | |||
117 | 117 | ||
118 | spin_lock(&brd->brd_lock); | 118 | spin_lock(&brd->brd_lock); |
119 | idx = sector >> PAGE_SECTORS_SHIFT; | 119 | idx = sector >> PAGE_SECTORS_SHIFT; |
120 | page->index = idx; | ||
120 | if (radix_tree_insert(&brd->brd_pages, idx, page)) { | 121 | if (radix_tree_insert(&brd->brd_pages, idx, page)) { |
121 | __free_page(page); | 122 | __free_page(page); |
122 | page = radix_tree_lookup(&brd->brd_pages, idx); | 123 | page = radix_tree_lookup(&brd->brd_pages, idx); |
123 | BUG_ON(!page); | 124 | BUG_ON(!page); |
124 | BUG_ON(page->index != idx); | 125 | BUG_ON(page->index != idx); |
125 | } else | 126 | } |
126 | page->index = idx; | ||
127 | spin_unlock(&brd->brd_lock); | 127 | spin_unlock(&brd->brd_lock); |
128 | 128 | ||
129 | radix_tree_preload_end(); | 129 | radix_tree_preload_end(); |
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index f8ef15f37c5e..3fd130fdfbc1 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c | |||
@@ -1160,8 +1160,7 @@ static int ace_probe(struct platform_device *dev) | |||
1160 | dev_dbg(&dev->dev, "ace_probe(%p)\n", dev); | 1160 | dev_dbg(&dev->dev, "ace_probe(%p)\n", dev); |
1161 | 1161 | ||
1162 | /* device id and bus width */ | 1162 | /* device id and bus width */ |
1163 | of_property_read_u32(dev->dev.of_node, "port-number", &id); | 1163 | if (of_property_read_u32(dev->dev.of_node, "port-number", &id)) |
1164 | if (id < 0) | ||
1165 | id = 0; | 1164 | id = 0; |
1166 | if (of_find_property(dev->dev.of_node, "8-bit", NULL)) | 1165 | if (of_find_property(dev->dev.of_node, "8-bit", NULL)) |
1167 | bus_width = ACE_BUS_WIDTH_8; | 1166 | bus_width = ACE_BUS_WIDTH_8; |
diff --git a/drivers/char/random.c b/drivers/char/random.c index cd9a6211dcad..35487e8ded59 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -865,16 +865,24 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
865 | if (r->entropy_count / 8 < min + reserved) { | 865 | if (r->entropy_count / 8 < min + reserved) { |
866 | nbytes = 0; | 866 | nbytes = 0; |
867 | } else { | 867 | } else { |
868 | int entropy_count, orig; | ||
869 | retry: | ||
870 | entropy_count = orig = ACCESS_ONCE(r->entropy_count); | ||
868 | /* If limited, never pull more than available */ | 871 | /* If limited, never pull more than available */ |
869 | if (r->limit && nbytes + reserved >= r->entropy_count / 8) | 872 | if (r->limit && nbytes + reserved >= entropy_count / 8) |
870 | nbytes = r->entropy_count/8 - reserved; | 873 | nbytes = entropy_count/8 - reserved; |
871 | 874 | ||
872 | if (r->entropy_count / 8 >= nbytes + reserved) | 875 | if (entropy_count / 8 >= nbytes + reserved) { |
873 | r->entropy_count -= nbytes*8; | 876 | entropy_count -= nbytes*8; |
874 | else | 877 | if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) |
875 | r->entropy_count = reserved; | 878 | goto retry; |
879 | } else { | ||
880 | entropy_count = reserved; | ||
881 | if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) | ||
882 | goto retry; | ||
883 | } | ||
876 | 884 | ||
877 | if (r->entropy_count < random_write_wakeup_thresh) | 885 | if (entropy_count < random_write_wakeup_thresh) |
878 | wakeup_write = 1; | 886 | wakeup_write = 1; |
879 | } | 887 | } |
880 | 888 | ||
@@ -957,10 +965,23 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
957 | { | 965 | { |
958 | ssize_t ret = 0, i; | 966 | ssize_t ret = 0, i; |
959 | __u8 tmp[EXTRACT_SIZE]; | 967 | __u8 tmp[EXTRACT_SIZE]; |
968 | unsigned long flags; | ||
960 | 969 | ||
961 | /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ | 970 | /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ |
962 | if (fips_enabled && !r->last_data_init) | 971 | if (fips_enabled) { |
963 | nbytes += EXTRACT_SIZE; | 972 | spin_lock_irqsave(&r->lock, flags); |
973 | if (!r->last_data_init) { | ||
974 | r->last_data_init = true; | ||
975 | spin_unlock_irqrestore(&r->lock, flags); | ||
976 | trace_extract_entropy(r->name, EXTRACT_SIZE, | ||
977 | r->entropy_count, _RET_IP_); | ||
978 | xfer_secondary_pool(r, EXTRACT_SIZE); | ||
979 | extract_buf(r, tmp); | ||
980 | spin_lock_irqsave(&r->lock, flags); | ||
981 | memcpy(r->last_data, tmp, EXTRACT_SIZE); | ||
982 | } | ||
983 | spin_unlock_irqrestore(&r->lock, flags); | ||
984 | } | ||
964 | 985 | ||
965 | trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); | 986 | trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); |
966 | xfer_secondary_pool(r, nbytes); | 987 | xfer_secondary_pool(r, nbytes); |
@@ -970,19 +991,6 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
970 | extract_buf(r, tmp); | 991 | extract_buf(r, tmp); |
971 | 992 | ||
972 | if (fips_enabled) { | 993 | if (fips_enabled) { |
973 | unsigned long flags; | ||
974 | |||
975 | |||
976 | /* prime last_data value if need be, per fips 140-2 */ | ||
977 | if (!r->last_data_init) { | ||
978 | spin_lock_irqsave(&r->lock, flags); | ||
979 | memcpy(r->last_data, tmp, EXTRACT_SIZE); | ||
980 | r->last_data_init = true; | ||
981 | nbytes -= EXTRACT_SIZE; | ||
982 | spin_unlock_irqrestore(&r->lock, flags); | ||
983 | extract_buf(r, tmp); | ||
984 | } | ||
985 | |||
986 | spin_lock_irqsave(&r->lock, flags); | 994 | spin_lock_irqsave(&r->lock, flags); |
987 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) | 995 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) |
988 | panic("Hardware RNG duplicated output!\n"); | 996 | panic("Hardware RNG duplicated output!\n"); |
diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c index ee14662ed5ce..98cae529373f 100644 --- a/drivers/leds/leds-ot200.c +++ b/drivers/leds/leds-ot200.c | |||
@@ -47,37 +47,37 @@ static struct ot200_led leds[] = { | |||
47 | { | 47 | { |
48 | .name = "led_1", | 48 | .name = "led_1", |
49 | .port = 0x49, | 49 | .port = 0x49, |
50 | .mask = BIT(7), | 50 | .mask = BIT(6), |
51 | }, | 51 | }, |
52 | { | 52 | { |
53 | .name = "led_2", | 53 | .name = "led_2", |
54 | .port = 0x49, | 54 | .port = 0x49, |
55 | .mask = BIT(6), | 55 | .mask = BIT(5), |
56 | }, | 56 | }, |
57 | { | 57 | { |
58 | .name = "led_3", | 58 | .name = "led_3", |
59 | .port = 0x49, | 59 | .port = 0x49, |
60 | .mask = BIT(5), | 60 | .mask = BIT(4), |
61 | }, | 61 | }, |
62 | { | 62 | { |
63 | .name = "led_4", | 63 | .name = "led_4", |
64 | .port = 0x49, | 64 | .port = 0x49, |
65 | .mask = BIT(4), | 65 | .mask = BIT(3), |
66 | }, | 66 | }, |
67 | { | 67 | { |
68 | .name = "led_5", | 68 | .name = "led_5", |
69 | .port = 0x49, | 69 | .port = 0x49, |
70 | .mask = BIT(3), | 70 | .mask = BIT(2), |
71 | }, | 71 | }, |
72 | { | 72 | { |
73 | .name = "led_6", | 73 | .name = "led_6", |
74 | .port = 0x49, | 74 | .port = 0x49, |
75 | .mask = BIT(2), | 75 | .mask = BIT(1), |
76 | }, | 76 | }, |
77 | { | 77 | { |
78 | .name = "led_7", | 78 | .name = "led_7", |
79 | .port = 0x49, | 79 | .port = 0x49, |
80 | .mask = BIT(1), | 80 | .mask = BIT(0), |
81 | } | 81 | } |
82 | }; | 82 | }; |
83 | 83 | ||
diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig index 6194d35ebb97..5ab056494bbe 100644 --- a/drivers/rapidio/Kconfig +++ b/drivers/rapidio/Kconfig | |||
@@ -47,4 +47,24 @@ config RAPIDIO_DEBUG | |||
47 | 47 | ||
48 | If you are unsure about this, say N here. | 48 | If you are unsure about this, say N here. |
49 | 49 | ||
50 | choice | ||
51 | prompt "Enumeration method" | ||
52 | depends on RAPIDIO | ||
53 | default RAPIDIO_ENUM_BASIC | ||
54 | help | ||
55 | There are different enumeration and discovery mechanisms offered | ||
56 | for RapidIO subsystem. You may select single built-in method or | ||
57 | or any number of methods to be built as modules. | ||
58 | Selecting a built-in method disables use of loadable methods. | ||
59 | |||
60 | If unsure, select Basic built-in. | ||
61 | |||
62 | config RAPIDIO_ENUM_BASIC | ||
63 | tristate "Basic" | ||
64 | help | ||
65 | This option includes basic RapidIO fabric enumeration and discovery | ||
66 | mechanism similar to one described in RapidIO specification Annex 1. | ||
67 | |||
68 | endchoice | ||
69 | |||
50 | source "drivers/rapidio/switches/Kconfig" | 70 | source "drivers/rapidio/switches/Kconfig" |
diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile index ec3fb8121004..3036702ffe8b 100644 --- a/drivers/rapidio/Makefile +++ b/drivers/rapidio/Makefile | |||
@@ -1,7 +1,8 @@ | |||
1 | # | 1 | # |
2 | # Makefile for RapidIO interconnect services | 2 | # Makefile for RapidIO interconnect services |
3 | # | 3 | # |
4 | obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o | 4 | obj-y += rio.o rio-access.o rio-driver.o rio-sysfs.o |
5 | obj-$(CONFIG_RAPIDIO_ENUM_BASIC) += rio-scan.o | ||
5 | 6 | ||
6 | obj-$(CONFIG_RAPIDIO) += switches/ | 7 | obj-$(CONFIG_RAPIDIO) += switches/ |
7 | obj-$(CONFIG_RAPIDIO) += devices/ | 8 | obj-$(CONFIG_RAPIDIO) += devices/ |
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 6faba406b6e9..a8b2c23a7ef4 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c | |||
@@ -471,6 +471,10 @@ static irqreturn_t tsi721_irqhandler(int irq, void *ptr) | |||
471 | u32 intval; | 471 | u32 intval; |
472 | u32 ch_inte; | 472 | u32 ch_inte; |
473 | 473 | ||
474 | /* For MSI mode disable all device-level interrupts */ | ||
475 | if (priv->flags & TSI721_USING_MSI) | ||
476 | iowrite32(0, priv->regs + TSI721_DEV_INTE); | ||
477 | |||
474 | dev_int = ioread32(priv->regs + TSI721_DEV_INT); | 478 | dev_int = ioread32(priv->regs + TSI721_DEV_INT); |
475 | if (!dev_int) | 479 | if (!dev_int) |
476 | return IRQ_NONE; | 480 | return IRQ_NONE; |
@@ -560,6 +564,14 @@ static irqreturn_t tsi721_irqhandler(int irq, void *ptr) | |||
560 | } | 564 | } |
561 | } | 565 | } |
562 | #endif | 566 | #endif |
567 | |||
568 | /* For MSI mode re-enable device-level interrupts */ | ||
569 | if (priv->flags & TSI721_USING_MSI) { | ||
570 | dev_int = TSI721_DEV_INT_SR2PC_CH | TSI721_DEV_INT_SRIO | | ||
571 | TSI721_DEV_INT_SMSG_CH | TSI721_DEV_INT_BDMA_CH; | ||
572 | iowrite32(dev_int, priv->regs + TSI721_DEV_INTE); | ||
573 | } | ||
574 | |||
563 | return IRQ_HANDLED; | 575 | return IRQ_HANDLED; |
564 | } | 576 | } |
565 | 577 | ||
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index 0f4a53bdaa3c..a0c875563d76 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c | |||
@@ -164,6 +164,13 @@ void rio_unregister_driver(struct rio_driver *rdrv) | |||
164 | driver_unregister(&rdrv->driver); | 164 | driver_unregister(&rdrv->driver); |
165 | } | 165 | } |
166 | 166 | ||
167 | void rio_attach_device(struct rio_dev *rdev) | ||
168 | { | ||
169 | rdev->dev.bus = &rio_bus_type; | ||
170 | rdev->dev.parent = &rio_bus; | ||
171 | } | ||
172 | EXPORT_SYMBOL_GPL(rio_attach_device); | ||
173 | |||
167 | /** | 174 | /** |
168 | * rio_match_bus - Tell if a RIO device structure has a matching RIO driver device id structure | 175 | * rio_match_bus - Tell if a RIO device structure has a matching RIO driver device id structure |
169 | * @dev: the standard device structure to match against | 176 | * @dev: the standard device structure to match against |
@@ -200,6 +207,7 @@ struct bus_type rio_bus_type = { | |||
200 | .name = "rapidio", | 207 | .name = "rapidio", |
201 | .match = rio_match_bus, | 208 | .match = rio_match_bus, |
202 | .dev_attrs = rio_dev_attrs, | 209 | .dev_attrs = rio_dev_attrs, |
210 | .bus_attrs = rio_bus_attrs, | ||
203 | .probe = rio_device_probe, | 211 | .probe = rio_device_probe, |
204 | .remove = rio_device_remove, | 212 | .remove = rio_device_remove, |
205 | }; | 213 | }; |
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index a965acd3c0e4..4c15dbf81087 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c | |||
@@ -37,12 +37,8 @@ | |||
37 | 37 | ||
38 | #include "rio.h" | 38 | #include "rio.h" |
39 | 39 | ||
40 | LIST_HEAD(rio_devices); | ||
41 | |||
42 | static void rio_init_em(struct rio_dev *rdev); | 40 | static void rio_init_em(struct rio_dev *rdev); |
43 | 41 | ||
44 | DEFINE_SPINLOCK(rio_global_list_lock); | ||
45 | |||
46 | static int next_destid = 0; | 42 | static int next_destid = 0; |
47 | static int next_comptag = 1; | 43 | static int next_comptag = 1; |
48 | 44 | ||
@@ -327,127 +323,6 @@ static int rio_is_switch(struct rio_dev *rdev) | |||
327 | } | 323 | } |
328 | 324 | ||
329 | /** | 325 | /** |
330 | * rio_switch_init - Sets switch operations for a particular vendor switch | ||
331 | * @rdev: RIO device | ||
332 | * @do_enum: Enumeration/Discovery mode flag | ||
333 | * | ||
334 | * Searches the RIO switch ops table for known switch types. If the vid | ||
335 | * and did match a switch table entry, then call switch initialization | ||
336 | * routine to setup switch-specific routines. | ||
337 | */ | ||
338 | static void rio_switch_init(struct rio_dev *rdev, int do_enum) | ||
339 | { | ||
340 | struct rio_switch_ops *cur = __start_rio_switch_ops; | ||
341 | struct rio_switch_ops *end = __end_rio_switch_ops; | ||
342 | |||
343 | while (cur < end) { | ||
344 | if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) { | ||
345 | pr_debug("RIO: calling init routine for %s\n", | ||
346 | rio_name(rdev)); | ||
347 | cur->init_hook(rdev, do_enum); | ||
348 | break; | ||
349 | } | ||
350 | cur++; | ||
351 | } | ||
352 | |||
353 | if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) { | ||
354 | pr_debug("RIO: adding STD routing ops for %s\n", | ||
355 | rio_name(rdev)); | ||
356 | rdev->rswitch->add_entry = rio_std_route_add_entry; | ||
357 | rdev->rswitch->get_entry = rio_std_route_get_entry; | ||
358 | rdev->rswitch->clr_table = rio_std_route_clr_table; | ||
359 | } | ||
360 | |||
361 | if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry) | ||
362 | printk(KERN_ERR "RIO: missing routing ops for %s\n", | ||
363 | rio_name(rdev)); | ||
364 | } | ||
365 | |||
366 | /** | ||
367 | * rio_add_device- Adds a RIO device to the device model | ||
368 | * @rdev: RIO device | ||
369 | * | ||
370 | * Adds the RIO device to the global device list and adds the RIO | ||
371 | * device to the RIO device list. Creates the generic sysfs nodes | ||
372 | * for an RIO device. | ||
373 | */ | ||
374 | static int rio_add_device(struct rio_dev *rdev) | ||
375 | { | ||
376 | int err; | ||
377 | |||
378 | err = device_add(&rdev->dev); | ||
379 | if (err) | ||
380 | return err; | ||
381 | |||
382 | spin_lock(&rio_global_list_lock); | ||
383 | list_add_tail(&rdev->global_list, &rio_devices); | ||
384 | spin_unlock(&rio_global_list_lock); | ||
385 | |||
386 | rio_create_sysfs_dev_files(rdev); | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | /** | ||
392 | * rio_enable_rx_tx_port - enable input receiver and output transmitter of | ||
393 | * given port | ||
394 | * @port: Master port associated with the RIO network | ||
395 | * @local: local=1 select local port otherwise a far device is reached | ||
396 | * @destid: Destination ID of the device to check host bit | ||
397 | * @hopcount: Number of hops to reach the target | ||
398 | * @port_num: Port (-number on switch) to enable on a far end device | ||
399 | * | ||
400 | * Returns 0 or 1 from on General Control Command and Status Register | ||
401 | * (EXT_PTR+0x3C) | ||
402 | */ | ||
403 | inline int rio_enable_rx_tx_port(struct rio_mport *port, | ||
404 | int local, u16 destid, | ||
405 | u8 hopcount, u8 port_num) { | ||
406 | #ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS | ||
407 | u32 regval; | ||
408 | u32 ext_ftr_ptr; | ||
409 | |||
410 | /* | ||
411 | * enable rx input tx output port | ||
412 | */ | ||
413 | pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = " | ||
414 | "%d, port_num = %d)\n", local, destid, hopcount, port_num); | ||
415 | |||
416 | ext_ftr_ptr = rio_mport_get_physefb(port, local, destid, hopcount); | ||
417 | |||
418 | if (local) { | ||
419 | rio_local_read_config_32(port, ext_ftr_ptr + | ||
420 | RIO_PORT_N_CTL_CSR(0), | ||
421 | ®val); | ||
422 | } else { | ||
423 | if (rio_mport_read_config_32(port, destid, hopcount, | ||
424 | ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), ®val) < 0) | ||
425 | return -EIO; | ||
426 | } | ||
427 | |||
428 | if (regval & RIO_PORT_N_CTL_P_TYP_SER) { | ||
429 | /* serial */ | ||
430 | regval = regval | RIO_PORT_N_CTL_EN_RX_SER | ||
431 | | RIO_PORT_N_CTL_EN_TX_SER; | ||
432 | } else { | ||
433 | /* parallel */ | ||
434 | regval = regval | RIO_PORT_N_CTL_EN_RX_PAR | ||
435 | | RIO_PORT_N_CTL_EN_TX_PAR; | ||
436 | } | ||
437 | |||
438 | if (local) { | ||
439 | rio_local_write_config_32(port, ext_ftr_ptr + | ||
440 | RIO_PORT_N_CTL_CSR(0), regval); | ||
441 | } else { | ||
442 | if (rio_mport_write_config_32(port, destid, hopcount, | ||
443 | ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), regval) < 0) | ||
444 | return -EIO; | ||
445 | } | ||
446 | #endif | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | /** | ||
451 | * rio_setup_device- Allocates and sets up a RIO device | 326 | * rio_setup_device- Allocates and sets up a RIO device |
452 | * @net: RIO network | 327 | * @net: RIO network |
453 | * @port: Master port to send transactions | 328 | * @port: Master port to send transactions |
@@ -587,8 +462,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, | |||
587 | rdev->destid); | 462 | rdev->destid); |
588 | } | 463 | } |
589 | 464 | ||
590 | rdev->dev.bus = &rio_bus_type; | 465 | rio_attach_device(rdev); |
591 | rdev->dev.parent = &rio_bus; | ||
592 | 466 | ||
593 | device_initialize(&rdev->dev); | 467 | device_initialize(&rdev->dev); |
594 | rdev->dev.release = rio_release_dev; | 468 | rdev->dev.release = rio_release_dev; |
@@ -1260,19 +1134,30 @@ static void rio_pw_enable(struct rio_mport *port, int enable) | |||
1260 | /** | 1134 | /** |
1261 | * rio_enum_mport- Start enumeration through a master port | 1135 | * rio_enum_mport- Start enumeration through a master port |
1262 | * @mport: Master port to send transactions | 1136 | * @mport: Master port to send transactions |
1137 | * @flags: Enumeration control flags | ||
1263 | * | 1138 | * |
1264 | * Starts the enumeration process. If somebody has enumerated our | 1139 | * Starts the enumeration process. If somebody has enumerated our |
1265 | * master port device, then give up. If not and we have an active | 1140 | * master port device, then give up. If not and we have an active |
1266 | * link, then start recursive peer enumeration. Returns %0 if | 1141 | * link, then start recursive peer enumeration. Returns %0 if |
1267 | * enumeration succeeds or %-EBUSY if enumeration fails. | 1142 | * enumeration succeeds or %-EBUSY if enumeration fails. |
1268 | */ | 1143 | */ |
1269 | int rio_enum_mport(struct rio_mport *mport) | 1144 | int rio_enum_mport(struct rio_mport *mport, u32 flags) |
1270 | { | 1145 | { |
1271 | struct rio_net *net = NULL; | 1146 | struct rio_net *net = NULL; |
1272 | int rc = 0; | 1147 | int rc = 0; |
1273 | 1148 | ||
1274 | printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id, | 1149 | printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id, |
1275 | mport->name); | 1150 | mport->name); |
1151 | |||
1152 | /* | ||
1153 | * To avoid multiple start requests (repeat enumeration is not supported | ||
1154 | * by this method) check if enumeration/discovery was performed for this | ||
1155 | * mport: if mport was added into the list of mports for a net exit | ||
1156 | * with error. | ||
1157 | */ | ||
1158 | if (mport->nnode.next || mport->nnode.prev) | ||
1159 | return -EBUSY; | ||
1160 | |||
1276 | /* If somebody else enumerated our master port device, bail. */ | 1161 | /* If somebody else enumerated our master port device, bail. */ |
1277 | if (rio_enum_host(mport) < 0) { | 1162 | if (rio_enum_host(mport) < 0) { |
1278 | printk(KERN_INFO | 1163 | printk(KERN_INFO |
@@ -1362,14 +1247,16 @@ static void rio_build_route_tables(struct rio_net *net) | |||
1362 | /** | 1247 | /** |
1363 | * rio_disc_mport- Start discovery through a master port | 1248 | * rio_disc_mport- Start discovery through a master port |
1364 | * @mport: Master port to send transactions | 1249 | * @mport: Master port to send transactions |
1250 | * @flags: discovery control flags | ||
1365 | * | 1251 | * |
1366 | * Starts the discovery process. If we have an active link, | 1252 | * Starts the discovery process. If we have an active link, |
1367 | * then wait for the signal that enumeration is complete. | 1253 | * then wait for the signal that enumeration is complete (if wait |
1254 | * is allowed). | ||
1368 | * When enumeration completion is signaled, start recursive | 1255 | * When enumeration completion is signaled, start recursive |
1369 | * peer discovery. Returns %0 if discovery succeeds or %-EBUSY | 1256 | * peer discovery. Returns %0 if discovery succeeds or %-EBUSY |
1370 | * on failure. | 1257 | * on failure. |
1371 | */ | 1258 | */ |
1372 | int rio_disc_mport(struct rio_mport *mport) | 1259 | int rio_disc_mport(struct rio_mport *mport, u32 flags) |
1373 | { | 1260 | { |
1374 | struct rio_net *net = NULL; | 1261 | struct rio_net *net = NULL; |
1375 | unsigned long to_end; | 1262 | unsigned long to_end; |
@@ -1379,6 +1266,11 @@ int rio_disc_mport(struct rio_mport *mport) | |||
1379 | 1266 | ||
1380 | /* If master port has an active link, allocate net and discover peers */ | 1267 | /* If master port has an active link, allocate net and discover peers */ |
1381 | if (rio_mport_is_active(mport)) { | 1268 | if (rio_mport_is_active(mport)) { |
1269 | if (rio_enum_complete(mport)) | ||
1270 | goto enum_done; | ||
1271 | else if (flags & RIO_SCAN_ENUM_NO_WAIT) | ||
1272 | return -EAGAIN; | ||
1273 | |||
1382 | pr_debug("RIO: wait for enumeration to complete...\n"); | 1274 | pr_debug("RIO: wait for enumeration to complete...\n"); |
1383 | 1275 | ||
1384 | to_end = jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; | 1276 | to_end = jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; |
@@ -1421,3 +1313,41 @@ enum_done: | |||
1421 | bail: | 1313 | bail: |
1422 | return -EBUSY; | 1314 | return -EBUSY; |
1423 | } | 1315 | } |
1316 | |||
1317 | static struct rio_scan rio_scan_ops = { | ||
1318 | .enumerate = rio_enum_mport, | ||
1319 | .discover = rio_disc_mport, | ||
1320 | }; | ||
1321 | |||
1322 | static bool scan; | ||
1323 | module_param(scan, bool, 0); | ||
1324 | MODULE_PARM_DESC(scan, "Start RapidIO network enumeration/discovery " | ||
1325 | "(default = 0)"); | ||
1326 | |||
1327 | /** | ||
1328 | * rio_basic_attach: | ||
1329 | * | ||
1330 | * When this enumeration/discovery method is loaded as a module this function | ||
1331 | * registers its specific enumeration and discover routines for all available | ||
1332 | * RapidIO mport devices. The "scan" command line parameter controls ability of | ||
1333 | * the module to start RapidIO enumeration/discovery automatically. | ||
1334 | * | ||
1335 | * Returns 0 for success or -EIO if unable to register itself. | ||
1336 | * | ||
1337 | * This enumeration/discovery method cannot be unloaded and therefore does not | ||
1338 | * provide a matching cleanup_module routine. | ||
1339 | */ | ||
1340 | |||
1341 | static int __init rio_basic_attach(void) | ||
1342 | { | ||
1343 | if (rio_register_scan(RIO_MPORT_ANY, &rio_scan_ops)) | ||
1344 | return -EIO; | ||
1345 | if (scan) | ||
1346 | rio_init_mports(); | ||
1347 | return 0; | ||
1348 | } | ||
1349 | |||
1350 | late_initcall(rio_basic_attach); | ||
1351 | |||
1352 | MODULE_DESCRIPTION("Basic RapidIO enumeration/discovery"); | ||
1353 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 4dbe360989be..66d4acd5e18f 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c | |||
@@ -285,3 +285,48 @@ void rio_remove_sysfs_dev_files(struct rio_dev *rdev) | |||
285 | rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE); | 285 | rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE); |
286 | } | 286 | } |
287 | } | 287 | } |
288 | |||
289 | static ssize_t bus_scan_store(struct bus_type *bus, const char *buf, | ||
290 | size_t count) | ||
291 | { | ||
292 | long val; | ||
293 | struct rio_mport *port = NULL; | ||
294 | int rc; | ||
295 | |||
296 | if (kstrtol(buf, 0, &val) < 0) | ||
297 | return -EINVAL; | ||
298 | |||
299 | if (val == RIO_MPORT_ANY) { | ||
300 | rc = rio_init_mports(); | ||
301 | goto exit; | ||
302 | } | ||
303 | |||
304 | if (val < 0 || val >= RIO_MAX_MPORTS) | ||
305 | return -EINVAL; | ||
306 | |||
307 | port = rio_find_mport((int)val); | ||
308 | |||
309 | if (!port) { | ||
310 | pr_debug("RIO: %s: mport_%d not available\n", | ||
311 | __func__, (int)val); | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | if (!port->nscan) | ||
316 | return -EINVAL; | ||
317 | |||
318 | if (port->host_deviceid >= 0) | ||
319 | rc = port->nscan->enumerate(port, 0); | ||
320 | else | ||
321 | rc = port->nscan->discover(port, RIO_SCAN_ENUM_NO_WAIT); | ||
322 | exit: | ||
323 | if (!rc) | ||
324 | rc = count; | ||
325 | |||
326 | return rc; | ||
327 | } | ||
328 | |||
329 | struct bus_attribute rio_bus_attrs[] = { | ||
330 | __ATTR(scan, (S_IWUSR|S_IWGRP), NULL, bus_scan_store), | ||
331 | __ATTR_NULL | ||
332 | }; | ||
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index d553b5d13722..cb1c08996fbb 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c | |||
@@ -31,7 +31,11 @@ | |||
31 | 31 | ||
32 | #include "rio.h" | 32 | #include "rio.h" |
33 | 33 | ||
34 | static LIST_HEAD(rio_devices); | ||
35 | static DEFINE_SPINLOCK(rio_global_list_lock); | ||
36 | |||
34 | static LIST_HEAD(rio_mports); | 37 | static LIST_HEAD(rio_mports); |
38 | static DEFINE_MUTEX(rio_mport_list_lock); | ||
35 | static unsigned char next_portid; | 39 | static unsigned char next_portid; |
36 | static DEFINE_SPINLOCK(rio_mmap_lock); | 40 | static DEFINE_SPINLOCK(rio_mmap_lock); |
37 | 41 | ||
@@ -53,6 +57,32 @@ u16 rio_local_get_device_id(struct rio_mport *port) | |||
53 | } | 57 | } |
54 | 58 | ||
55 | /** | 59 | /** |
60 | * rio_add_device- Adds a RIO device to the device model | ||
61 | * @rdev: RIO device | ||
62 | * | ||
63 | * Adds the RIO device to the global device list and adds the RIO | ||
64 | * device to the RIO device list. Creates the generic sysfs nodes | ||
65 | * for an RIO device. | ||
66 | */ | ||
67 | int rio_add_device(struct rio_dev *rdev) | ||
68 | { | ||
69 | int err; | ||
70 | |||
71 | err = device_add(&rdev->dev); | ||
72 | if (err) | ||
73 | return err; | ||
74 | |||
75 | spin_lock(&rio_global_list_lock); | ||
76 | list_add_tail(&rdev->global_list, &rio_devices); | ||
77 | spin_unlock(&rio_global_list_lock); | ||
78 | |||
79 | rio_create_sysfs_dev_files(rdev); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(rio_add_device); | ||
84 | |||
85 | /** | ||
56 | * rio_request_inb_mbox - request inbound mailbox service | 86 | * rio_request_inb_mbox - request inbound mailbox service |
57 | * @mport: RIO master port from which to allocate the mailbox resource | 87 | * @mport: RIO master port from which to allocate the mailbox resource |
58 | * @dev_id: Device specific pointer to pass on event | 88 | * @dev_id: Device specific pointer to pass on event |
@@ -489,6 +519,7 @@ rio_mport_get_physefb(struct rio_mport *port, int local, | |||
489 | 519 | ||
490 | return ext_ftr_ptr; | 520 | return ext_ftr_ptr; |
491 | } | 521 | } |
522 | EXPORT_SYMBOL_GPL(rio_mport_get_physefb); | ||
492 | 523 | ||
493 | /** | 524 | /** |
494 | * rio_get_comptag - Begin or continue searching for a RIO device by component tag | 525 | * rio_get_comptag - Begin or continue searching for a RIO device by component tag |
@@ -521,6 +552,7 @@ exit: | |||
521 | spin_unlock(&rio_global_list_lock); | 552 | spin_unlock(&rio_global_list_lock); |
522 | return rdev; | 553 | return rdev; |
523 | } | 554 | } |
555 | EXPORT_SYMBOL_GPL(rio_get_comptag); | ||
524 | 556 | ||
525 | /** | 557 | /** |
526 | * rio_set_port_lockout - Sets/clears LOCKOUT bit (RIO EM 1.3) for a switch port. | 558 | * rio_set_port_lockout - Sets/clears LOCKOUT bit (RIO EM 1.3) for a switch port. |
@@ -545,6 +577,107 @@ int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock) | |||
545 | regval); | 577 | regval); |
546 | return 0; | 578 | return 0; |
547 | } | 579 | } |
580 | EXPORT_SYMBOL_GPL(rio_set_port_lockout); | ||
581 | |||
582 | /** | ||
583 | * rio_switch_init - Sets switch operations for a particular vendor switch | ||
584 | * @rdev: RIO device | ||
585 | * @do_enum: Enumeration/Discovery mode flag | ||
586 | * | ||
587 | * Searches the RIO switch ops table for known switch types. If the vid | ||
588 | * and did match a switch table entry, then call switch initialization | ||
589 | * routine to setup switch-specific routines. | ||
590 | */ | ||
591 | void rio_switch_init(struct rio_dev *rdev, int do_enum) | ||
592 | { | ||
593 | struct rio_switch_ops *cur = __start_rio_switch_ops; | ||
594 | struct rio_switch_ops *end = __end_rio_switch_ops; | ||
595 | |||
596 | while (cur < end) { | ||
597 | if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) { | ||
598 | pr_debug("RIO: calling init routine for %s\n", | ||
599 | rio_name(rdev)); | ||
600 | cur->init_hook(rdev, do_enum); | ||
601 | break; | ||
602 | } | ||
603 | cur++; | ||
604 | } | ||
605 | |||
606 | if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) { | ||
607 | pr_debug("RIO: adding STD routing ops for %s\n", | ||
608 | rio_name(rdev)); | ||
609 | rdev->rswitch->add_entry = rio_std_route_add_entry; | ||
610 | rdev->rswitch->get_entry = rio_std_route_get_entry; | ||
611 | rdev->rswitch->clr_table = rio_std_route_clr_table; | ||
612 | } | ||
613 | |||
614 | if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry) | ||
615 | printk(KERN_ERR "RIO: missing routing ops for %s\n", | ||
616 | rio_name(rdev)); | ||
617 | } | ||
618 | EXPORT_SYMBOL_GPL(rio_switch_init); | ||
619 | |||
620 | /** | ||
621 | * rio_enable_rx_tx_port - enable input receiver and output transmitter of | ||
622 | * given port | ||
623 | * @port: Master port associated with the RIO network | ||
624 | * @local: local=1 select local port otherwise a far device is reached | ||
625 | * @destid: Destination ID of the device to check host bit | ||
626 | * @hopcount: Number of hops to reach the target | ||
627 | * @port_num: Port (-number on switch) to enable on a far end device | ||
628 | * | ||
629 | * Returns 0 or 1 from on General Control Command and Status Register | ||
630 | * (EXT_PTR+0x3C) | ||
631 | */ | ||
632 | int rio_enable_rx_tx_port(struct rio_mport *port, | ||
633 | int local, u16 destid, | ||
634 | u8 hopcount, u8 port_num) | ||
635 | { | ||
636 | #ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS | ||
637 | u32 regval; | ||
638 | u32 ext_ftr_ptr; | ||
639 | |||
640 | /* | ||
641 | * enable rx input tx output port | ||
642 | */ | ||
643 | pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = " | ||
644 | "%d, port_num = %d)\n", local, destid, hopcount, port_num); | ||
645 | |||
646 | ext_ftr_ptr = rio_mport_get_physefb(port, local, destid, hopcount); | ||
647 | |||
648 | if (local) { | ||
649 | rio_local_read_config_32(port, ext_ftr_ptr + | ||
650 | RIO_PORT_N_CTL_CSR(0), | ||
651 | ®val); | ||
652 | } else { | ||
653 | if (rio_mport_read_config_32(port, destid, hopcount, | ||
654 | ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), ®val) < 0) | ||
655 | return -EIO; | ||
656 | } | ||
657 | |||
658 | if (regval & RIO_PORT_N_CTL_P_TYP_SER) { | ||
659 | /* serial */ | ||
660 | regval = regval | RIO_PORT_N_CTL_EN_RX_SER | ||
661 | | RIO_PORT_N_CTL_EN_TX_SER; | ||
662 | } else { | ||
663 | /* parallel */ | ||
664 | regval = regval | RIO_PORT_N_CTL_EN_RX_PAR | ||
665 | | RIO_PORT_N_CTL_EN_TX_PAR; | ||
666 | } | ||
667 | |||
668 | if (local) { | ||
669 | rio_local_write_config_32(port, ext_ftr_ptr + | ||
670 | RIO_PORT_N_CTL_CSR(0), regval); | ||
671 | } else { | ||
672 | if (rio_mport_write_config_32(port, destid, hopcount, | ||
673 | ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), regval) < 0) | ||
674 | return -EIO; | ||
675 | } | ||
676 | #endif | ||
677 | return 0; | ||
678 | } | ||
679 | EXPORT_SYMBOL_GPL(rio_enable_rx_tx_port); | ||
680 | |||
548 | 681 | ||
549 | /** | 682 | /** |
550 | * rio_chk_dev_route - Validate route to the specified device. | 683 | * rio_chk_dev_route - Validate route to the specified device. |
@@ -610,6 +743,7 @@ rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, u8 hopcount) | |||
610 | 743 | ||
611 | return 0; | 744 | return 0; |
612 | } | 745 | } |
746 | EXPORT_SYMBOL_GPL(rio_mport_chk_dev_access); | ||
613 | 747 | ||
614 | /** | 748 | /** |
615 | * rio_chk_dev_access - Validate access to the specified device. | 749 | * rio_chk_dev_access - Validate access to the specified device. |
@@ -941,6 +1075,7 @@ rio_mport_get_efb(struct rio_mport *port, int local, u16 destid, | |||
941 | return RIO_GET_BLOCK_ID(reg_val); | 1075 | return RIO_GET_BLOCK_ID(reg_val); |
942 | } | 1076 | } |
943 | } | 1077 | } |
1078 | EXPORT_SYMBOL_GPL(rio_mport_get_efb); | ||
944 | 1079 | ||
945 | /** | 1080 | /** |
946 | * rio_mport_get_feature - query for devices' extended features | 1081 | * rio_mport_get_feature - query for devices' extended features |
@@ -997,6 +1132,7 @@ rio_mport_get_feature(struct rio_mport * port, int local, u16 destid, | |||
997 | 1132 | ||
998 | return 0; | 1133 | return 0; |
999 | } | 1134 | } |
1135 | EXPORT_SYMBOL_GPL(rio_mport_get_feature); | ||
1000 | 1136 | ||
1001 | /** | 1137 | /** |
1002 | * rio_get_asm - Begin or continue searching for a RIO device by vid/did/asm_vid/asm_did | 1138 | * rio_get_asm - Begin or continue searching for a RIO device by vid/did/asm_vid/asm_did |
@@ -1246,6 +1382,95 @@ EXPORT_SYMBOL_GPL(rio_dma_prep_slave_sg); | |||
1246 | 1382 | ||
1247 | #endif /* CONFIG_RAPIDIO_DMA_ENGINE */ | 1383 | #endif /* CONFIG_RAPIDIO_DMA_ENGINE */ |
1248 | 1384 | ||
1385 | /** | ||
1386 | * rio_find_mport - find RIO mport by its ID | ||
1387 | * @mport_id: number (ID) of mport device | ||
1388 | * | ||
1389 | * Given a RIO mport number, the desired mport is located | ||
1390 | * in the global list of mports. If the mport is found, a pointer to its | ||
1391 | * data structure is returned. If no mport is found, %NULL is returned. | ||
1392 | */ | ||
1393 | struct rio_mport *rio_find_mport(int mport_id) | ||
1394 | { | ||
1395 | struct rio_mport *port; | ||
1396 | |||
1397 | mutex_lock(&rio_mport_list_lock); | ||
1398 | list_for_each_entry(port, &rio_mports, node) { | ||
1399 | if (port->id == mport_id) | ||
1400 | goto found; | ||
1401 | } | ||
1402 | port = NULL; | ||
1403 | found: | ||
1404 | mutex_unlock(&rio_mport_list_lock); | ||
1405 | |||
1406 | return port; | ||
1407 | } | ||
1408 | |||
1409 | /** | ||
1410 | * rio_register_scan - enumeration/discovery method registration interface | ||
1411 | * @mport_id: mport device ID for which fabric scan routine has to be set | ||
1412 | * (RIO_MPORT_ANY = set for all available mports) | ||
1413 | * @scan_ops: enumeration/discovery control structure | ||
1414 | * | ||
1415 | * Assigns enumeration or discovery method to the specified mport device (or all | ||
1416 | * available mports if RIO_MPORT_ANY is specified). | ||
1417 | * Returns error if the mport already has an enumerator attached to it. | ||
1418 | * In case of RIO_MPORT_ANY ignores ports with valid scan routines and returns | ||
1419 | * an error if was unable to find at least one available mport. | ||
1420 | */ | ||
1421 | int rio_register_scan(int mport_id, struct rio_scan *scan_ops) | ||
1422 | { | ||
1423 | struct rio_mport *port; | ||
1424 | int rc = -EBUSY; | ||
1425 | |||
1426 | mutex_lock(&rio_mport_list_lock); | ||
1427 | list_for_each_entry(port, &rio_mports, node) { | ||
1428 | if (port->id == mport_id || mport_id == RIO_MPORT_ANY) { | ||
1429 | if (port->nscan && mport_id == RIO_MPORT_ANY) | ||
1430 | continue; | ||
1431 | else if (port->nscan) | ||
1432 | break; | ||
1433 | |||
1434 | port->nscan = scan_ops; | ||
1435 | rc = 0; | ||
1436 | |||
1437 | if (mport_id != RIO_MPORT_ANY) | ||
1438 | break; | ||
1439 | } | ||
1440 | } | ||
1441 | mutex_unlock(&rio_mport_list_lock); | ||
1442 | |||
1443 | return rc; | ||
1444 | } | ||
1445 | EXPORT_SYMBOL_GPL(rio_register_scan); | ||
1446 | |||
1447 | /** | ||
1448 | * rio_unregister_scan - removes enumeration/discovery method from mport | ||
1449 | * @mport_id: mport device ID for which fabric scan routine has to be | ||
1450 | * unregistered (RIO_MPORT_ANY = set for all available mports) | ||
1451 | * | ||
1452 | * Removes enumeration or discovery method assigned to the specified mport | ||
1453 | * device (or all available mports if RIO_MPORT_ANY is specified). | ||
1454 | */ | ||
1455 | int rio_unregister_scan(int mport_id) | ||
1456 | { | ||
1457 | struct rio_mport *port; | ||
1458 | |||
1459 | mutex_lock(&rio_mport_list_lock); | ||
1460 | list_for_each_entry(port, &rio_mports, node) { | ||
1461 | if (port->id == mport_id || mport_id == RIO_MPORT_ANY) { | ||
1462 | if (port->nscan) | ||
1463 | port->nscan = NULL; | ||
1464 | if (mport_id != RIO_MPORT_ANY) | ||
1465 | break; | ||
1466 | } | ||
1467 | } | ||
1468 | mutex_unlock(&rio_mport_list_lock); | ||
1469 | |||
1470 | return 0; | ||
1471 | } | ||
1472 | EXPORT_SYMBOL_GPL(rio_unregister_scan); | ||
1473 | |||
1249 | static void rio_fixup_device(struct rio_dev *dev) | 1474 | static void rio_fixup_device(struct rio_dev *dev) |
1250 | { | 1475 | { |
1251 | } | 1476 | } |
@@ -1274,7 +1499,7 @@ static void disc_work_handler(struct work_struct *_work) | |||
1274 | work = container_of(_work, struct rio_disc_work, work); | 1499 | work = container_of(_work, struct rio_disc_work, work); |
1275 | pr_debug("RIO: discovery work for mport %d %s\n", | 1500 | pr_debug("RIO: discovery work for mport %d %s\n", |
1276 | work->mport->id, work->mport->name); | 1501 | work->mport->id, work->mport->name); |
1277 | rio_disc_mport(work->mport); | 1502 | work->mport->nscan->discover(work->mport, 0); |
1278 | } | 1503 | } |
1279 | 1504 | ||
1280 | int rio_init_mports(void) | 1505 | int rio_init_mports(void) |
@@ -1290,12 +1515,15 @@ int rio_init_mports(void) | |||
1290 | * First, run enumerations and check if we need to perform discovery | 1515 | * First, run enumerations and check if we need to perform discovery |
1291 | * on any of the registered mports. | 1516 | * on any of the registered mports. |
1292 | */ | 1517 | */ |
1518 | mutex_lock(&rio_mport_list_lock); | ||
1293 | list_for_each_entry(port, &rio_mports, node) { | 1519 | list_for_each_entry(port, &rio_mports, node) { |
1294 | if (port->host_deviceid >= 0) | 1520 | if (port->host_deviceid >= 0) { |
1295 | rio_enum_mport(port); | 1521 | if (port->nscan) |
1296 | else | 1522 | port->nscan->enumerate(port, 0); |
1523 | } else | ||
1297 | n++; | 1524 | n++; |
1298 | } | 1525 | } |
1526 | mutex_unlock(&rio_mport_list_lock); | ||
1299 | 1527 | ||
1300 | if (!n) | 1528 | if (!n) |
1301 | goto no_disc; | 1529 | goto no_disc; |
@@ -1322,14 +1550,16 @@ int rio_init_mports(void) | |||
1322 | } | 1550 | } |
1323 | 1551 | ||
1324 | n = 0; | 1552 | n = 0; |
1553 | mutex_lock(&rio_mport_list_lock); | ||
1325 | list_for_each_entry(port, &rio_mports, node) { | 1554 | list_for_each_entry(port, &rio_mports, node) { |
1326 | if (port->host_deviceid < 0) { | 1555 | if (port->host_deviceid < 0 && port->nscan) { |
1327 | work[n].mport = port; | 1556 | work[n].mport = port; |
1328 | INIT_WORK(&work[n].work, disc_work_handler); | 1557 | INIT_WORK(&work[n].work, disc_work_handler); |
1329 | queue_work(rio_wq, &work[n].work); | 1558 | queue_work(rio_wq, &work[n].work); |
1330 | n++; | 1559 | n++; |
1331 | } | 1560 | } |
1332 | } | 1561 | } |
1562 | mutex_unlock(&rio_mport_list_lock); | ||
1333 | 1563 | ||
1334 | flush_workqueue(rio_wq); | 1564 | flush_workqueue(rio_wq); |
1335 | pr_debug("RIO: destroy discovery workqueue\n"); | 1565 | pr_debug("RIO: destroy discovery workqueue\n"); |
@@ -1342,8 +1572,6 @@ no_disc: | |||
1342 | return 0; | 1572 | return 0; |
1343 | } | 1573 | } |
1344 | 1574 | ||
1345 | device_initcall_sync(rio_init_mports); | ||
1346 | |||
1347 | static int hdids[RIO_MAX_MPORTS + 1]; | 1575 | static int hdids[RIO_MAX_MPORTS + 1]; |
1348 | 1576 | ||
1349 | static int rio_get_hdid(int index) | 1577 | static int rio_get_hdid(int index) |
@@ -1371,7 +1599,10 @@ int rio_register_mport(struct rio_mport *port) | |||
1371 | 1599 | ||
1372 | port->id = next_portid++; | 1600 | port->id = next_portid++; |
1373 | port->host_deviceid = rio_get_hdid(port->id); | 1601 | port->host_deviceid = rio_get_hdid(port->id); |
1602 | port->nscan = NULL; | ||
1603 | mutex_lock(&rio_mport_list_lock); | ||
1374 | list_add_tail(&port->node, &rio_mports); | 1604 | list_add_tail(&port->node, &rio_mports); |
1605 | mutex_unlock(&rio_mport_list_lock); | ||
1375 | return 0; | 1606 | return 0; |
1376 | } | 1607 | } |
1377 | 1608 | ||
@@ -1386,3 +1617,4 @@ EXPORT_SYMBOL_GPL(rio_request_inb_mbox); | |||
1386 | EXPORT_SYMBOL_GPL(rio_release_inb_mbox); | 1617 | EXPORT_SYMBOL_GPL(rio_release_inb_mbox); |
1387 | EXPORT_SYMBOL_GPL(rio_request_outb_mbox); | 1618 | EXPORT_SYMBOL_GPL(rio_request_outb_mbox); |
1388 | EXPORT_SYMBOL_GPL(rio_release_outb_mbox); | 1619 | EXPORT_SYMBOL_GPL(rio_release_outb_mbox); |
1620 | EXPORT_SYMBOL_GPL(rio_init_mports); | ||
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h index b1af414f15e6..c14f864dea5c 100644 --- a/drivers/rapidio/rio.h +++ b/drivers/rapidio/rio.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/rio.h> | 15 | #include <linux/rio.h> |
16 | 16 | ||
17 | #define RIO_MAX_CHK_RETRY 3 | 17 | #define RIO_MAX_CHK_RETRY 3 |
18 | #define RIO_MPORT_ANY (-1) | ||
18 | 19 | ||
19 | /* Functions internal to the RIO core code */ | 20 | /* Functions internal to the RIO core code */ |
20 | 21 | ||
@@ -27,8 +28,6 @@ extern u32 rio_mport_get_efb(struct rio_mport *port, int local, u16 destid, | |||
27 | extern int rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, | 28 | extern int rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, |
28 | u8 hopcount); | 29 | u8 hopcount); |
29 | extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); | 30 | extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); |
30 | extern int rio_enum_mport(struct rio_mport *mport); | ||
31 | extern int rio_disc_mport(struct rio_mport *mport); | ||
32 | extern int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, | 31 | extern int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, |
33 | u8 hopcount, u16 table, u16 route_destid, | 32 | u8 hopcount, u16 table, u16 route_destid, |
34 | u8 route_port); | 33 | u8 route_port); |
@@ -39,10 +38,18 @@ extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, | |||
39 | u8 hopcount, u16 table); | 38 | u8 hopcount, u16 table); |
40 | extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock); | 39 | extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock); |
41 | extern struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from); | 40 | extern struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from); |
41 | extern int rio_add_device(struct rio_dev *rdev); | ||
42 | extern void rio_switch_init(struct rio_dev *rdev, int do_enum); | ||
43 | extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid, | ||
44 | u8 hopcount, u8 port_num); | ||
45 | extern int rio_register_scan(int mport_id, struct rio_scan *scan_ops); | ||
46 | extern int rio_unregister_scan(int mport_id); | ||
47 | extern void rio_attach_device(struct rio_dev *rdev); | ||
48 | extern struct rio_mport *rio_find_mport(int mport_id); | ||
42 | 49 | ||
43 | /* Structures internal to the RIO core code */ | 50 | /* Structures internal to the RIO core code */ |
44 | extern struct device_attribute rio_dev_attrs[]; | 51 | extern struct device_attribute rio_dev_attrs[]; |
45 | extern spinlock_t rio_global_list_lock; | 52 | extern struct bus_attribute rio_bus_attrs[]; |
46 | 53 | ||
47 | extern struct rio_switch_ops __start_rio_switch_ops[]; | 54 | extern struct rio_switch_ops __start_rio_switch_ops[]; |
48 | extern struct rio_switch_ops __end_rio_switch_ops[]; | 55 | extern struct rio_switch_ops __end_rio_switch_ops[]; |
diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c index 48b6612fae7f..d5af7baa48b5 100644 --- a/drivers/rtc/rtc-max8998.c +++ b/drivers/rtc/rtc-max8998.c | |||
@@ -285,7 +285,7 @@ static int max8998_rtc_probe(struct platform_device *pdev) | |||
285 | info->irq, ret); | 285 | info->irq, ret); |
286 | 286 | ||
287 | dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name); | 287 | dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name); |
288 | if (pdata->rtc_delay) { | 288 | if (pdata && pdata->rtc_delay) { |
289 | info->lp3974_bug_workaround = true; | 289 | info->lp3974_bug_workaround = true; |
290 | dev_warn(&pdev->dev, "LP3974 with RTC REGERR option." | 290 | dev_warn(&pdev->dev, "LP3974 with RTC REGERR option." |
291 | " RTC updates will be extremely slow.\n"); | 291 | " RTC updates will be extremely slow.\n"); |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 8900ea784817..0f0609b1aa2c 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
@@ -306,7 +306,7 @@ static int pl031_remove(struct amba_device *adev) | |||
306 | struct pl031_local *ldata = dev_get_drvdata(&adev->dev); | 306 | struct pl031_local *ldata = dev_get_drvdata(&adev->dev); |
307 | 307 | ||
308 | amba_set_drvdata(adev, NULL); | 308 | amba_set_drvdata(adev, NULL); |
309 | free_irq(adev->irq[0], ldata->rtc); | 309 | free_irq(adev->irq[0], ldata); |
310 | rtc_device_unregister(ldata->rtc); | 310 | rtc_device_unregister(ldata->rtc); |
311 | iounmap(ldata->base); | 311 | iounmap(ldata->base); |
312 | kfree(ldata); | 312 | kfree(ldata); |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index d71d60f94fc1..2e937bdace6f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -2199,7 +2199,7 @@ config FB_XILINX | |||
2199 | 2199 | ||
2200 | config FB_GOLDFISH | 2200 | config FB_GOLDFISH |
2201 | tristate "Goldfish Framebuffer" | 2201 | tristate "Goldfish Framebuffer" |
2202 | depends on FB | 2202 | depends on FB && HAS_DMA |
2203 | select FB_CFB_FILLRECT | 2203 | select FB_CFB_FILLRECT |
2204 | select FB_CFB_COPYAREA | 2204 | select FB_CFB_COPYAREA |
2205 | select FB_CFB_IMAGEBLIT | 2205 | select FB_CFB_IMAGEBLIT |
@@ -2453,6 +2453,23 @@ config FB_HYPERV | |||
2453 | help | 2453 | help |
2454 | This framebuffer driver supports Microsoft Hyper-V Synthetic Video. | 2454 | This framebuffer driver supports Microsoft Hyper-V Synthetic Video. |
2455 | 2455 | ||
2456 | config FB_SIMPLE | ||
2457 | bool "Simple framebuffer support" | ||
2458 | depends on (FB = y) && OF | ||
2459 | select FB_CFB_FILLRECT | ||
2460 | select FB_CFB_COPYAREA | ||
2461 | select FB_CFB_IMAGEBLIT | ||
2462 | help | ||
2463 | Say Y if you want support for a simple frame-buffer. | ||
2464 | |||
2465 | This driver assumes that the display hardware has been initialized | ||
2466 | before the kernel boots, and the kernel will simply render to the | ||
2467 | pre-allocated frame buffer surface. | ||
2468 | |||
2469 | Configuration re: surface address, size, and format must be provided | ||
2470 | through device tree, or potentially plain old platform data in the | ||
2471 | future. | ||
2472 | |||
2456 | source "drivers/video/omap/Kconfig" | 2473 | source "drivers/video/omap/Kconfig" |
2457 | source "drivers/video/omap2/Kconfig" | 2474 | source "drivers/video/omap2/Kconfig" |
2458 | source "drivers/video/exynos/Kconfig" | 2475 | source "drivers/video/exynos/Kconfig" |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 7234e4a959e8..e8bae8dd4804 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -166,6 +166,7 @@ obj-$(CONFIG_FB_MX3) += mx3fb.o | |||
166 | obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o | 166 | obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o |
167 | obj-$(CONFIG_FB_MXS) += mxsfb.o | 167 | obj-$(CONFIG_FB_MXS) += mxsfb.o |
168 | obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o | 168 | obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o |
169 | obj-$(CONFIG_FB_SIMPLE) += simplefb.o | ||
169 | 170 | ||
170 | # the test framebuffer is last | 171 | # the test framebuffer is last |
171 | obj-$(CONFIG_FB_VIRTUAL) += vfb.o | 172 | obj-$(CONFIG_FB_VIRTUAL) += vfb.o |
diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c new file mode 100644 index 000000000000..e2e9e3e61b72 --- /dev/null +++ b/drivers/video/simplefb.c | |||
@@ -0,0 +1,234 @@ | |||
1 | /* | ||
2 | * Simplest possible simple frame-buffer driver, as a platform device | ||
3 | * | ||
4 | * Copyright (c) 2013, Stephen Warren | ||
5 | * | ||
6 | * Based on q40fb.c, which was: | ||
7 | * Copyright (C) 2001 Richard Zidlicky <rz@linux-m68k.org> | ||
8 | * | ||
9 | * Also based on offb.c, which was: | ||
10 | * Copyright (C) 1997 Geert Uytterhoeven | ||
11 | * Copyright (C) 1996 Paul Mackerras | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms and conditions of the GNU General Public License, | ||
15 | * version 2, as published by the Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
19 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
20 | * more details. | ||
21 | */ | ||
22 | |||
23 | #include <linux/errno.h> | ||
24 | #include <linux/fb.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | |||
29 | static struct fb_fix_screeninfo simplefb_fix = { | ||
30 | .id = "simple", | ||
31 | .type = FB_TYPE_PACKED_PIXELS, | ||
32 | .visual = FB_VISUAL_TRUECOLOR, | ||
33 | .accel = FB_ACCEL_NONE, | ||
34 | }; | ||
35 | |||
36 | static struct fb_var_screeninfo simplefb_var = { | ||
37 | .height = -1, | ||
38 | .width = -1, | ||
39 | .activate = FB_ACTIVATE_NOW, | ||
40 | .vmode = FB_VMODE_NONINTERLACED, | ||
41 | }; | ||
42 | |||
43 | static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | ||
44 | u_int transp, struct fb_info *info) | ||
45 | { | ||
46 | u32 *pal = info->pseudo_palette; | ||
47 | u32 cr = red >> (16 - info->var.red.length); | ||
48 | u32 cg = green >> (16 - info->var.green.length); | ||
49 | u32 cb = blue >> (16 - info->var.blue.length); | ||
50 | u32 value; | ||
51 | |||
52 | if (regno >= 16) | ||
53 | return -EINVAL; | ||
54 | |||
55 | value = (cr << info->var.red.offset) | | ||
56 | (cg << info->var.green.offset) | | ||
57 | (cb << info->var.blue.offset); | ||
58 | if (info->var.transp.length > 0) { | ||
59 | u32 mask = (1 << info->var.transp.length) - 1; | ||
60 | mask <<= info->var.transp.offset; | ||
61 | value |= mask; | ||
62 | } | ||
63 | pal[regno] = value; | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static struct fb_ops simplefb_ops = { | ||
69 | .owner = THIS_MODULE, | ||
70 | .fb_setcolreg = simplefb_setcolreg, | ||
71 | .fb_fillrect = cfb_fillrect, | ||
72 | .fb_copyarea = cfb_copyarea, | ||
73 | .fb_imageblit = cfb_imageblit, | ||
74 | }; | ||
75 | |||
76 | struct simplefb_format { | ||
77 | const char *name; | ||
78 | u32 bits_per_pixel; | ||
79 | struct fb_bitfield red; | ||
80 | struct fb_bitfield green; | ||
81 | struct fb_bitfield blue; | ||
82 | struct fb_bitfield transp; | ||
83 | }; | ||
84 | |||
85 | static struct simplefb_format simplefb_formats[] = { | ||
86 | { "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0} }, | ||
87 | }; | ||
88 | |||
89 | struct simplefb_params { | ||
90 | u32 width; | ||
91 | u32 height; | ||
92 | u32 stride; | ||
93 | struct simplefb_format *format; | ||
94 | }; | ||
95 | |||
96 | static int simplefb_parse_dt(struct platform_device *pdev, | ||
97 | struct simplefb_params *params) | ||
98 | { | ||
99 | struct device_node *np = pdev->dev.of_node; | ||
100 | int ret; | ||
101 | const char *format; | ||
102 | int i; | ||
103 | |||
104 | ret = of_property_read_u32(np, "width", ¶ms->width); | ||
105 | if (ret) { | ||
106 | dev_err(&pdev->dev, "Can't parse width property\n"); | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | ret = of_property_read_u32(np, "height", ¶ms->height); | ||
111 | if (ret) { | ||
112 | dev_err(&pdev->dev, "Can't parse height property\n"); | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | ret = of_property_read_u32(np, "stride", ¶ms->stride); | ||
117 | if (ret) { | ||
118 | dev_err(&pdev->dev, "Can't parse stride property\n"); | ||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | ret = of_property_read_string(np, "format", &format); | ||
123 | if (ret) { | ||
124 | dev_err(&pdev->dev, "Can't parse format property\n"); | ||
125 | return ret; | ||
126 | } | ||
127 | params->format = NULL; | ||
128 | for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) { | ||
129 | if (strcmp(format, simplefb_formats[i].name)) | ||
130 | continue; | ||
131 | params->format = &simplefb_formats[i]; | ||
132 | break; | ||
133 | } | ||
134 | if (!params->format) { | ||
135 | dev_err(&pdev->dev, "Invalid format value\n"); | ||
136 | return -EINVAL; | ||
137 | } | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int simplefb_probe(struct platform_device *pdev) | ||
143 | { | ||
144 | int ret; | ||
145 | struct simplefb_params params; | ||
146 | struct fb_info *info; | ||
147 | struct resource *mem; | ||
148 | |||
149 | if (fb_get_options("simplefb", NULL)) | ||
150 | return -ENODEV; | ||
151 | |||
152 | ret = simplefb_parse_dt(pdev, ¶ms); | ||
153 | if (ret) | ||
154 | return ret; | ||
155 | |||
156 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
157 | if (!mem) { | ||
158 | dev_err(&pdev->dev, "No memory resource\n"); | ||
159 | return -EINVAL; | ||
160 | } | ||
161 | |||
162 | info = framebuffer_alloc(sizeof(u32) * 16, &pdev->dev); | ||
163 | if (!info) | ||
164 | return -ENOMEM; | ||
165 | platform_set_drvdata(pdev, info); | ||
166 | |||
167 | info->fix = simplefb_fix; | ||
168 | info->fix.smem_start = mem->start; | ||
169 | info->fix.smem_len = resource_size(mem); | ||
170 | info->fix.line_length = params.stride; | ||
171 | |||
172 | info->var = simplefb_var; | ||
173 | info->var.xres = params.width; | ||
174 | info->var.yres = params.height; | ||
175 | info->var.xres_virtual = params.width; | ||
176 | info->var.yres_virtual = params.height; | ||
177 | info->var.bits_per_pixel = params.format->bits_per_pixel; | ||
178 | info->var.red = params.format->red; | ||
179 | info->var.green = params.format->green; | ||
180 | info->var.blue = params.format->blue; | ||
181 | info->var.transp = params.format->transp; | ||
182 | |||
183 | info->fbops = &simplefb_ops; | ||
184 | info->flags = FBINFO_DEFAULT; | ||
185 | info->screen_base = devm_ioremap(&pdev->dev, info->fix.smem_start, | ||
186 | info->fix.smem_len); | ||
187 | if (!info->screen_base) { | ||
188 | framebuffer_release(info); | ||
189 | return -ENODEV; | ||
190 | } | ||
191 | info->pseudo_palette = (void *)(info + 1); | ||
192 | |||
193 | ret = register_framebuffer(info); | ||
194 | if (ret < 0) { | ||
195 | dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret); | ||
196 | framebuffer_release(info); | ||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static int simplefb_remove(struct platform_device *pdev) | ||
206 | { | ||
207 | struct fb_info *info = platform_get_drvdata(pdev); | ||
208 | |||
209 | unregister_framebuffer(info); | ||
210 | framebuffer_release(info); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static const struct of_device_id simplefb_of_match[] = { | ||
216 | { .compatible = "simple-framebuffer", }, | ||
217 | { }, | ||
218 | }; | ||
219 | MODULE_DEVICE_TABLE(of, simplefb_of_match); | ||
220 | |||
221 | static struct platform_driver simplefb_driver = { | ||
222 | .driver = { | ||
223 | .name = "simple-framebuffer", | ||
224 | .owner = THIS_MODULE, | ||
225 | .of_match_table = simplefb_of_match, | ||
226 | }, | ||
227 | .probe = simplefb_probe, | ||
228 | .remove = simplefb_remove, | ||
229 | }; | ||
230 | module_platform_driver(simplefb_driver); | ||
231 | |||
232 | MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>"); | ||
233 | MODULE_DESCRIPTION("Simple framebuffer driver"); | ||
234 | MODULE_LICENSE("GPL v2"); | ||