diff options
Diffstat (limited to 'drivers')
345 files changed, 17663 insertions, 3577 deletions
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 7025593a58c8..d74926e0939e 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c | |||
@@ -603,6 +603,10 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) | |||
603 | if (ret) | 603 | if (ret) |
604 | goto err_out; | 604 | goto err_out; |
605 | 605 | ||
606 | /* Hard-coded primecell ID instead of plug-n-play */ | ||
607 | if (dev->periphid != 0) | ||
608 | goto skip_probe; | ||
609 | |||
606 | /* | 610 | /* |
607 | * Dynamically calculate the size of the resource | 611 | * Dynamically calculate the size of the resource |
608 | * and use this for iomap | 612 | * and use this for iomap |
@@ -643,6 +647,7 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) | |||
643 | if (ret) | 647 | if (ret) |
644 | goto err_release; | 648 | goto err_release; |
645 | 649 | ||
650 | skip_probe: | ||
646 | ret = device_add(&dev->dev); | 651 | ret = device_add(&dev->dev); |
647 | if (ret) | 652 | if (ret) |
648 | goto err_release; | 653 | goto err_release; |
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index ffd8797faf4f..471a04013fe0 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c | |||
@@ -6,6 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "bcma_private.h" | 8 | #include "bcma_private.h" |
9 | #include <linux/slab.h> | ||
9 | #include <linux/bcma/bcma.h> | 10 | #include <linux/bcma/bcma.h> |
10 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
11 | 12 | ||
diff --git a/drivers/block/brd.c b/drivers/block/brd.c index b7f51e4594f8..dba1c32e1ddf 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c | |||
@@ -35,10 +35,6 @@ | |||
35 | */ | 35 | */ |
36 | struct brd_device { | 36 | struct brd_device { |
37 | int brd_number; | 37 | int brd_number; |
38 | int brd_refcnt; | ||
39 | loff_t brd_offset; | ||
40 | loff_t brd_sizelimit; | ||
41 | unsigned brd_blocksize; | ||
42 | 38 | ||
43 | struct request_queue *brd_queue; | 39 | struct request_queue *brd_queue; |
44 | struct gendisk *brd_disk; | 40 | struct gendisk *brd_disk; |
@@ -440,11 +436,11 @@ static int rd_nr; | |||
440 | int rd_size = CONFIG_BLK_DEV_RAM_SIZE; | 436 | int rd_size = CONFIG_BLK_DEV_RAM_SIZE; |
441 | static int max_part; | 437 | static int max_part; |
442 | static int part_shift; | 438 | static int part_shift; |
443 | module_param(rd_nr, int, 0); | 439 | module_param(rd_nr, int, S_IRUGO); |
444 | MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices"); | 440 | MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices"); |
445 | module_param(rd_size, int, 0); | 441 | module_param(rd_size, int, S_IRUGO); |
446 | MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes."); | 442 | MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes."); |
447 | module_param(max_part, int, 0); | 443 | module_param(max_part, int, S_IRUGO); |
448 | MODULE_PARM_DESC(max_part, "Maximum number of partitions per RAM disk"); | 444 | MODULE_PARM_DESC(max_part, "Maximum number of partitions per RAM disk"); |
449 | MODULE_LICENSE("GPL"); | 445 | MODULE_LICENSE("GPL"); |
450 | MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR); | 446 | MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR); |
@@ -552,7 +548,7 @@ static struct kobject *brd_probe(dev_t dev, int *part, void *data) | |||
552 | struct kobject *kobj; | 548 | struct kobject *kobj; |
553 | 549 | ||
554 | mutex_lock(&brd_devices_mutex); | 550 | mutex_lock(&brd_devices_mutex); |
555 | brd = brd_init_one(dev & MINORMASK); | 551 | brd = brd_init_one(MINOR(dev) >> part_shift); |
556 | kobj = brd ? get_disk(brd->brd_disk) : ERR_PTR(-ENOMEM); | 552 | kobj = brd ? get_disk(brd->brd_disk) : ERR_PTR(-ENOMEM); |
557 | mutex_unlock(&brd_devices_mutex); | 553 | mutex_unlock(&brd_devices_mutex); |
558 | 554 | ||
@@ -575,25 +571,39 @@ static int __init brd_init(void) | |||
575 | * | 571 | * |
576 | * (1) if rd_nr is specified, create that many upfront, and this | 572 | * (1) if rd_nr is specified, create that many upfront, and this |
577 | * also becomes a hard limit. | 573 | * also becomes a hard limit. |
578 | * (2) if rd_nr is not specified, create 1 rd device on module | 574 | * (2) if rd_nr is not specified, create CONFIG_BLK_DEV_RAM_COUNT |
579 | * load, user can further extend brd device by create dev node | 575 | * (default 16) rd device on module load, user can further |
580 | * themselves and have kernel automatically instantiate actual | 576 | * extend brd device by create dev node themselves and have |
581 | * device on-demand. | 577 | * kernel automatically instantiate actual device on-demand. |
582 | */ | 578 | */ |
583 | 579 | ||
584 | part_shift = 0; | 580 | part_shift = 0; |
585 | if (max_part > 0) | 581 | if (max_part > 0) { |
586 | part_shift = fls(max_part); | 582 | part_shift = fls(max_part); |
587 | 583 | ||
584 | /* | ||
585 | * Adjust max_part according to part_shift as it is exported | ||
586 | * to user space so that user can decide correct minor number | ||
587 | * if [s]he want to create more devices. | ||
588 | * | ||
589 | * Note that -1 is required because partition 0 is reserved | ||
590 | * for the whole disk. | ||
591 | */ | ||
592 | max_part = (1UL << part_shift) - 1; | ||
593 | } | ||
594 | |||
595 | if ((1UL << part_shift) > DISK_MAX_PARTS) | ||
596 | return -EINVAL; | ||
597 | |||
588 | if (rd_nr > 1UL << (MINORBITS - part_shift)) | 598 | if (rd_nr > 1UL << (MINORBITS - part_shift)) |
589 | return -EINVAL; | 599 | return -EINVAL; |
590 | 600 | ||
591 | if (rd_nr) { | 601 | if (rd_nr) { |
592 | nr = rd_nr; | 602 | nr = rd_nr; |
593 | range = rd_nr; | 603 | range = rd_nr << part_shift; |
594 | } else { | 604 | } else { |
595 | nr = CONFIG_BLK_DEV_RAM_COUNT; | 605 | nr = CONFIG_BLK_DEV_RAM_COUNT; |
596 | range = 1UL << (MINORBITS - part_shift); | 606 | range = 1UL << MINORBITS; |
597 | } | 607 | } |
598 | 608 | ||
599 | if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) | 609 | if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) |
@@ -632,7 +642,7 @@ static void __exit brd_exit(void) | |||
632 | unsigned long range; | 642 | unsigned long range; |
633 | struct brd_device *brd, *next; | 643 | struct brd_device *brd, *next; |
634 | 644 | ||
635 | range = rd_nr ? rd_nr : 1UL << (MINORBITS - part_shift); | 645 | range = rd_nr ? rd_nr << part_shift : 1UL << MINORBITS; |
636 | 646 | ||
637 | list_for_each_entry_safe(brd, next, &brd_devices, brd_list) | 647 | list_for_each_entry_safe(brd, next, &brd_devices, brd_list) |
638 | brd_del_one(brd); | 648 | brd_del_one(brd); |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index c59a672a3de0..76c8da78212b 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -1540,9 +1540,9 @@ static const struct block_device_operations lo_fops = { | |||
1540 | * And now the modules code and kernel interface. | 1540 | * And now the modules code and kernel interface. |
1541 | */ | 1541 | */ |
1542 | static int max_loop; | 1542 | static int max_loop; |
1543 | module_param(max_loop, int, 0); | 1543 | module_param(max_loop, int, S_IRUGO); |
1544 | MODULE_PARM_DESC(max_loop, "Maximum number of loop devices"); | 1544 | MODULE_PARM_DESC(max_loop, "Maximum number of loop devices"); |
1545 | module_param(max_part, int, 0); | 1545 | module_param(max_part, int, S_IRUGO); |
1546 | MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device"); | 1546 | MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device"); |
1547 | MODULE_LICENSE("GPL"); | 1547 | MODULE_LICENSE("GPL"); |
1548 | MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); | 1548 | MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); |
@@ -1688,9 +1688,20 @@ static int __init loop_init(void) | |||
1688 | */ | 1688 | */ |
1689 | 1689 | ||
1690 | part_shift = 0; | 1690 | part_shift = 0; |
1691 | if (max_part > 0) | 1691 | if (max_part > 0) { |
1692 | part_shift = fls(max_part); | 1692 | part_shift = fls(max_part); |
1693 | 1693 | ||
1694 | /* | ||
1695 | * Adjust max_part according to part_shift as it is exported | ||
1696 | * to user space so that user can decide correct minor number | ||
1697 | * if [s]he want to create more devices. | ||
1698 | * | ||
1699 | * Note that -1 is required because partition 0 is reserved | ||
1700 | * for the whole disk. | ||
1701 | */ | ||
1702 | max_part = (1UL << part_shift) - 1; | ||
1703 | } | ||
1704 | |||
1694 | if ((1UL << part_shift) > DISK_MAX_PARTS) | 1705 | if ((1UL << part_shift) > DISK_MAX_PARTS) |
1695 | return -EINVAL; | 1706 | return -EINVAL; |
1696 | 1707 | ||
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 38223e93aa98..58c0e6387cf7 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <asm/system.h> | 36 | #include <asm/system.h> |
37 | #include <linux/poll.h> | 37 | #include <linux/poll.h> |
38 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
39 | #include <linux/seq_file.h> | ||
39 | #include <linux/spinlock.h> | 40 | #include <linux/spinlock.h> |
40 | #include <linux/mutex.h> | 41 | #include <linux/mutex.h> |
41 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
@@ -1896,102 +1897,128 @@ int ipmi_request_supply_msgs(ipmi_user_t user, | |||
1896 | EXPORT_SYMBOL(ipmi_request_supply_msgs); | 1897 | EXPORT_SYMBOL(ipmi_request_supply_msgs); |
1897 | 1898 | ||
1898 | #ifdef CONFIG_PROC_FS | 1899 | #ifdef CONFIG_PROC_FS |
1899 | static int ipmb_file_read_proc(char *page, char **start, off_t off, | 1900 | static int smi_ipmb_proc_show(struct seq_file *m, void *v) |
1900 | int count, int *eof, void *data) | ||
1901 | { | 1901 | { |
1902 | char *out = (char *) page; | 1902 | ipmi_smi_t intf = m->private; |
1903 | ipmi_smi_t intf = data; | ||
1904 | int i; | 1903 | int i; |
1905 | int rv = 0; | ||
1906 | 1904 | ||
1907 | for (i = 0; i < IPMI_MAX_CHANNELS; i++) | 1905 | seq_printf(m, "%x", intf->channels[0].address); |
1908 | rv += sprintf(out+rv, "%x ", intf->channels[i].address); | 1906 | for (i = 1; i < IPMI_MAX_CHANNELS; i++) |
1909 | out[rv-1] = '\n'; /* Replace the final space with a newline */ | 1907 | seq_printf(m, " %x", intf->channels[i].address); |
1910 | out[rv] = '\0'; | 1908 | return seq_putc(m, '\n'); |
1911 | rv++; | ||
1912 | return rv; | ||
1913 | } | 1909 | } |
1914 | 1910 | ||
1915 | static int version_file_read_proc(char *page, char **start, off_t off, | 1911 | static int smi_ipmb_proc_open(struct inode *inode, struct file *file) |
1916 | int count, int *eof, void *data) | ||
1917 | { | 1912 | { |
1918 | char *out = (char *) page; | 1913 | return single_open(file, smi_ipmb_proc_show, PDE(inode)->data); |
1919 | ipmi_smi_t intf = data; | 1914 | } |
1920 | 1915 | ||
1921 | return sprintf(out, "%u.%u\n", | 1916 | static const struct file_operations smi_ipmb_proc_ops = { |
1917 | .open = smi_ipmb_proc_open, | ||
1918 | .read = seq_read, | ||
1919 | .llseek = seq_lseek, | ||
1920 | .release = single_release, | ||
1921 | }; | ||
1922 | |||
1923 | static int smi_version_proc_show(struct seq_file *m, void *v) | ||
1924 | { | ||
1925 | ipmi_smi_t intf = m->private; | ||
1926 | |||
1927 | return seq_printf(m, "%u.%u\n", | ||
1922 | ipmi_version_major(&intf->bmc->id), | 1928 | ipmi_version_major(&intf->bmc->id), |
1923 | ipmi_version_minor(&intf->bmc->id)); | 1929 | ipmi_version_minor(&intf->bmc->id)); |
1924 | } | 1930 | } |
1925 | 1931 | ||
1926 | static int stat_file_read_proc(char *page, char **start, off_t off, | 1932 | static int smi_version_proc_open(struct inode *inode, struct file *file) |
1927 | int count, int *eof, void *data) | ||
1928 | { | 1933 | { |
1929 | char *out = (char *) page; | 1934 | return single_open(file, smi_version_proc_show, PDE(inode)->data); |
1930 | ipmi_smi_t intf = data; | 1935 | } |
1936 | |||
1937 | static const struct file_operations smi_version_proc_ops = { | ||
1938 | .open = smi_version_proc_open, | ||
1939 | .read = seq_read, | ||
1940 | .llseek = seq_lseek, | ||
1941 | .release = single_release, | ||
1942 | }; | ||
1931 | 1943 | ||
1932 | out += sprintf(out, "sent_invalid_commands: %u\n", | 1944 | static int smi_stats_proc_show(struct seq_file *m, void *v) |
1945 | { | ||
1946 | ipmi_smi_t intf = m->private; | ||
1947 | |||
1948 | seq_printf(m, "sent_invalid_commands: %u\n", | ||
1933 | ipmi_get_stat(intf, sent_invalid_commands)); | 1949 | ipmi_get_stat(intf, sent_invalid_commands)); |
1934 | out += sprintf(out, "sent_local_commands: %u\n", | 1950 | seq_printf(m, "sent_local_commands: %u\n", |
1935 | ipmi_get_stat(intf, sent_local_commands)); | 1951 | ipmi_get_stat(intf, sent_local_commands)); |
1936 | out += sprintf(out, "handled_local_responses: %u\n", | 1952 | seq_printf(m, "handled_local_responses: %u\n", |
1937 | ipmi_get_stat(intf, handled_local_responses)); | 1953 | ipmi_get_stat(intf, handled_local_responses)); |
1938 | out += sprintf(out, "unhandled_local_responses: %u\n", | 1954 | seq_printf(m, "unhandled_local_responses: %u\n", |
1939 | ipmi_get_stat(intf, unhandled_local_responses)); | 1955 | ipmi_get_stat(intf, unhandled_local_responses)); |
1940 | out += sprintf(out, "sent_ipmb_commands: %u\n", | 1956 | seq_printf(m, "sent_ipmb_commands: %u\n", |
1941 | ipmi_get_stat(intf, sent_ipmb_commands)); | 1957 | ipmi_get_stat(intf, sent_ipmb_commands)); |
1942 | out += sprintf(out, "sent_ipmb_command_errs: %u\n", | 1958 | seq_printf(m, "sent_ipmb_command_errs: %u\n", |
1943 | ipmi_get_stat(intf, sent_ipmb_command_errs)); | 1959 | ipmi_get_stat(intf, sent_ipmb_command_errs)); |
1944 | out += sprintf(out, "retransmitted_ipmb_commands: %u\n", | 1960 | seq_printf(m, "retransmitted_ipmb_commands: %u\n", |
1945 | ipmi_get_stat(intf, retransmitted_ipmb_commands)); | 1961 | ipmi_get_stat(intf, retransmitted_ipmb_commands)); |
1946 | out += sprintf(out, "timed_out_ipmb_commands: %u\n", | 1962 | seq_printf(m, "timed_out_ipmb_commands: %u\n", |
1947 | ipmi_get_stat(intf, timed_out_ipmb_commands)); | 1963 | ipmi_get_stat(intf, timed_out_ipmb_commands)); |
1948 | out += sprintf(out, "timed_out_ipmb_broadcasts: %u\n", | 1964 | seq_printf(m, "timed_out_ipmb_broadcasts: %u\n", |
1949 | ipmi_get_stat(intf, timed_out_ipmb_broadcasts)); | 1965 | ipmi_get_stat(intf, timed_out_ipmb_broadcasts)); |
1950 | out += sprintf(out, "sent_ipmb_responses: %u\n", | 1966 | seq_printf(m, "sent_ipmb_responses: %u\n", |
1951 | ipmi_get_stat(intf, sent_ipmb_responses)); | 1967 | ipmi_get_stat(intf, sent_ipmb_responses)); |
1952 | out += sprintf(out, "handled_ipmb_responses: %u\n", | 1968 | seq_printf(m, "handled_ipmb_responses: %u\n", |
1953 | ipmi_get_stat(intf, handled_ipmb_responses)); | 1969 | ipmi_get_stat(intf, handled_ipmb_responses)); |
1954 | out += sprintf(out, "invalid_ipmb_responses: %u\n", | 1970 | seq_printf(m, "invalid_ipmb_responses: %u\n", |
1955 | ipmi_get_stat(intf, invalid_ipmb_responses)); | 1971 | ipmi_get_stat(intf, invalid_ipmb_responses)); |
1956 | out += sprintf(out, "unhandled_ipmb_responses: %u\n", | 1972 | seq_printf(m, "unhandled_ipmb_responses: %u\n", |
1957 | ipmi_get_stat(intf, unhandled_ipmb_responses)); | 1973 | ipmi_get_stat(intf, unhandled_ipmb_responses)); |
1958 | out += sprintf(out, "sent_lan_commands: %u\n", | 1974 | seq_printf(m, "sent_lan_commands: %u\n", |
1959 | ipmi_get_stat(intf, sent_lan_commands)); | 1975 | ipmi_get_stat(intf, sent_lan_commands)); |
1960 | out += sprintf(out, "sent_lan_command_errs: %u\n", | 1976 | seq_printf(m, "sent_lan_command_errs: %u\n", |
1961 | ipmi_get_stat(intf, sent_lan_command_errs)); | 1977 | ipmi_get_stat(intf, sent_lan_command_errs)); |
1962 | out += sprintf(out, "retransmitted_lan_commands: %u\n", | 1978 | seq_printf(m, "retransmitted_lan_commands: %u\n", |
1963 | ipmi_get_stat(intf, retransmitted_lan_commands)); | 1979 | ipmi_get_stat(intf, retransmitted_lan_commands)); |
1964 | out += sprintf(out, "timed_out_lan_commands: %u\n", | 1980 | seq_printf(m, "timed_out_lan_commands: %u\n", |
1965 | ipmi_get_stat(intf, timed_out_lan_commands)); | 1981 | ipmi_get_stat(intf, timed_out_lan_commands)); |
1966 | out += sprintf(out, "sent_lan_responses: %u\n", | 1982 | seq_printf(m, "sent_lan_responses: %u\n", |
1967 | ipmi_get_stat(intf, sent_lan_responses)); | 1983 | ipmi_get_stat(intf, sent_lan_responses)); |
1968 | out += sprintf(out, "handled_lan_responses: %u\n", | 1984 | seq_printf(m, "handled_lan_responses: %u\n", |
1969 | ipmi_get_stat(intf, handled_lan_responses)); | 1985 | ipmi_get_stat(intf, handled_lan_responses)); |
1970 | out += sprintf(out, "invalid_lan_responses: %u\n", | 1986 | seq_printf(m, "invalid_lan_responses: %u\n", |
1971 | ipmi_get_stat(intf, invalid_lan_responses)); | 1987 | ipmi_get_stat(intf, invalid_lan_responses)); |
1972 | out += sprintf(out, "unhandled_lan_responses: %u\n", | 1988 | seq_printf(m, "unhandled_lan_responses: %u\n", |
1973 | ipmi_get_stat(intf, unhandled_lan_responses)); | 1989 | ipmi_get_stat(intf, unhandled_lan_responses)); |
1974 | out += sprintf(out, "handled_commands: %u\n", | 1990 | seq_printf(m, "handled_commands: %u\n", |
1975 | ipmi_get_stat(intf, handled_commands)); | 1991 | ipmi_get_stat(intf, handled_commands)); |
1976 | out += sprintf(out, "invalid_commands: %u\n", | 1992 | seq_printf(m, "invalid_commands: %u\n", |
1977 | ipmi_get_stat(intf, invalid_commands)); | 1993 | ipmi_get_stat(intf, invalid_commands)); |
1978 | out += sprintf(out, "unhandled_commands: %u\n", | 1994 | seq_printf(m, "unhandled_commands: %u\n", |
1979 | ipmi_get_stat(intf, unhandled_commands)); | 1995 | ipmi_get_stat(intf, unhandled_commands)); |
1980 | out += sprintf(out, "invalid_events: %u\n", | 1996 | seq_printf(m, "invalid_events: %u\n", |
1981 | ipmi_get_stat(intf, invalid_events)); | 1997 | ipmi_get_stat(intf, invalid_events)); |
1982 | out += sprintf(out, "events: %u\n", | 1998 | seq_printf(m, "events: %u\n", |
1983 | ipmi_get_stat(intf, events)); | 1999 | ipmi_get_stat(intf, events)); |
1984 | out += sprintf(out, "failed rexmit LAN msgs: %u\n", | 2000 | seq_printf(m, "failed rexmit LAN msgs: %u\n", |
1985 | ipmi_get_stat(intf, dropped_rexmit_lan_commands)); | 2001 | ipmi_get_stat(intf, dropped_rexmit_lan_commands)); |
1986 | out += sprintf(out, "failed rexmit IPMB msgs: %u\n", | 2002 | seq_printf(m, "failed rexmit IPMB msgs: %u\n", |
1987 | ipmi_get_stat(intf, dropped_rexmit_ipmb_commands)); | 2003 | ipmi_get_stat(intf, dropped_rexmit_ipmb_commands)); |
2004 | return 0; | ||
2005 | } | ||
1988 | 2006 | ||
1989 | return (out - ((char *) page)); | 2007 | static int smi_stats_proc_open(struct inode *inode, struct file *file) |
2008 | { | ||
2009 | return single_open(file, smi_stats_proc_show, PDE(inode)->data); | ||
1990 | } | 2010 | } |
2011 | |||
2012 | static const struct file_operations smi_stats_proc_ops = { | ||
2013 | .open = smi_stats_proc_open, | ||
2014 | .read = seq_read, | ||
2015 | .llseek = seq_lseek, | ||
2016 | .release = single_release, | ||
2017 | }; | ||
1991 | #endif /* CONFIG_PROC_FS */ | 2018 | #endif /* CONFIG_PROC_FS */ |
1992 | 2019 | ||
1993 | int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, | 2020 | int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, |
1994 | read_proc_t *read_proc, | 2021 | const struct file_operations *proc_ops, |
1995 | void *data) | 2022 | void *data) |
1996 | { | 2023 | { |
1997 | int rv = 0; | 2024 | int rv = 0; |
@@ -2010,15 +2037,12 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, | |||
2010 | } | 2037 | } |
2011 | strcpy(entry->name, name); | 2038 | strcpy(entry->name, name); |
2012 | 2039 | ||
2013 | file = create_proc_entry(name, 0, smi->proc_dir); | 2040 | file = proc_create_data(name, 0, smi->proc_dir, proc_ops, data); |
2014 | if (!file) { | 2041 | if (!file) { |
2015 | kfree(entry->name); | 2042 | kfree(entry->name); |
2016 | kfree(entry); | 2043 | kfree(entry); |
2017 | rv = -ENOMEM; | 2044 | rv = -ENOMEM; |
2018 | } else { | 2045 | } else { |
2019 | file->data = data; | ||
2020 | file->read_proc = read_proc; | ||
2021 | |||
2022 | mutex_lock(&smi->proc_entry_lock); | 2046 | mutex_lock(&smi->proc_entry_lock); |
2023 | /* Stick it on the list. */ | 2047 | /* Stick it on the list. */ |
2024 | entry->next = smi->proc_entries; | 2048 | entry->next = smi->proc_entries; |
@@ -2043,17 +2067,17 @@ static int add_proc_entries(ipmi_smi_t smi, int num) | |||
2043 | 2067 | ||
2044 | if (rv == 0) | 2068 | if (rv == 0) |
2045 | rv = ipmi_smi_add_proc_entry(smi, "stats", | 2069 | rv = ipmi_smi_add_proc_entry(smi, "stats", |
2046 | stat_file_read_proc, | 2070 | &smi_stats_proc_ops, |
2047 | smi); | 2071 | smi); |
2048 | 2072 | ||
2049 | if (rv == 0) | 2073 | if (rv == 0) |
2050 | rv = ipmi_smi_add_proc_entry(smi, "ipmb", | 2074 | rv = ipmi_smi_add_proc_entry(smi, "ipmb", |
2051 | ipmb_file_read_proc, | 2075 | &smi_ipmb_proc_ops, |
2052 | smi); | 2076 | smi); |
2053 | 2077 | ||
2054 | if (rv == 0) | 2078 | if (rv == 0) |
2055 | rv = ipmi_smi_add_proc_entry(smi, "version", | 2079 | rv = ipmi_smi_add_proc_entry(smi, "version", |
2056 | version_file_read_proc, | 2080 | &smi_version_proc_ops, |
2057 | smi); | 2081 | smi); |
2058 | #endif /* CONFIG_PROC_FS */ | 2082 | #endif /* CONFIG_PROC_FS */ |
2059 | 2083 | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 64c6b8530615..9397ab49b72e 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/moduleparam.h> | 43 | #include <linux/moduleparam.h> |
44 | #include <asm/system.h> | 44 | #include <asm/system.h> |
45 | #include <linux/sched.h> | 45 | #include <linux/sched.h> |
46 | #include <linux/seq_file.h> | ||
46 | #include <linux/timer.h> | 47 | #include <linux/timer.h> |
47 | #include <linux/errno.h> | 48 | #include <linux/errno.h> |
48 | #include <linux/spinlock.h> | 49 | #include <linux/spinlock.h> |
@@ -2805,54 +2806,73 @@ static int try_enable_event_buffer(struct smi_info *smi_info) | |||
2805 | return rv; | 2806 | return rv; |
2806 | } | 2807 | } |
2807 | 2808 | ||
2808 | static int type_file_read_proc(char *page, char **start, off_t off, | 2809 | static int smi_type_proc_show(struct seq_file *m, void *v) |
2809 | int count, int *eof, void *data) | ||
2810 | { | 2810 | { |
2811 | struct smi_info *smi = data; | 2811 | struct smi_info *smi = m->private; |
2812 | 2812 | ||
2813 | return sprintf(page, "%s\n", si_to_str[smi->si_type]); | 2813 | return seq_printf(m, "%s\n", si_to_str[smi->si_type]); |
2814 | } | 2814 | } |
2815 | 2815 | ||
2816 | static int stat_file_read_proc(char *page, char **start, off_t off, | 2816 | static int smi_type_proc_open(struct inode *inode, struct file *file) |
2817 | int count, int *eof, void *data) | ||
2818 | { | 2817 | { |
2819 | char *out = (char *) page; | 2818 | return single_open(file, smi_type_proc_show, PDE(inode)->data); |
2820 | struct smi_info *smi = data; | 2819 | } |
2820 | |||
2821 | static const struct file_operations smi_type_proc_ops = { | ||
2822 | .open = smi_type_proc_open, | ||
2823 | .read = seq_read, | ||
2824 | .llseek = seq_lseek, | ||
2825 | .release = single_release, | ||
2826 | }; | ||
2827 | |||
2828 | static int smi_si_stats_proc_show(struct seq_file *m, void *v) | ||
2829 | { | ||
2830 | struct smi_info *smi = m->private; | ||
2821 | 2831 | ||
2822 | out += sprintf(out, "interrupts_enabled: %d\n", | 2832 | seq_printf(m, "interrupts_enabled: %d\n", |
2823 | smi->irq && !smi->interrupt_disabled); | 2833 | smi->irq && !smi->interrupt_disabled); |
2824 | out += sprintf(out, "short_timeouts: %u\n", | 2834 | seq_printf(m, "short_timeouts: %u\n", |
2825 | smi_get_stat(smi, short_timeouts)); | 2835 | smi_get_stat(smi, short_timeouts)); |
2826 | out += sprintf(out, "long_timeouts: %u\n", | 2836 | seq_printf(m, "long_timeouts: %u\n", |
2827 | smi_get_stat(smi, long_timeouts)); | 2837 | smi_get_stat(smi, long_timeouts)); |
2828 | out += sprintf(out, "idles: %u\n", | 2838 | seq_printf(m, "idles: %u\n", |
2829 | smi_get_stat(smi, idles)); | 2839 | smi_get_stat(smi, idles)); |
2830 | out += sprintf(out, "interrupts: %u\n", | 2840 | seq_printf(m, "interrupts: %u\n", |
2831 | smi_get_stat(smi, interrupts)); | 2841 | smi_get_stat(smi, interrupts)); |
2832 | out += sprintf(out, "attentions: %u\n", | 2842 | seq_printf(m, "attentions: %u\n", |
2833 | smi_get_stat(smi, attentions)); | 2843 | smi_get_stat(smi, attentions)); |
2834 | out += sprintf(out, "flag_fetches: %u\n", | 2844 | seq_printf(m, "flag_fetches: %u\n", |
2835 | smi_get_stat(smi, flag_fetches)); | 2845 | smi_get_stat(smi, flag_fetches)); |
2836 | out += sprintf(out, "hosed_count: %u\n", | 2846 | seq_printf(m, "hosed_count: %u\n", |
2837 | smi_get_stat(smi, hosed_count)); | 2847 | smi_get_stat(smi, hosed_count)); |
2838 | out += sprintf(out, "complete_transactions: %u\n", | 2848 | seq_printf(m, "complete_transactions: %u\n", |
2839 | smi_get_stat(smi, complete_transactions)); | 2849 | smi_get_stat(smi, complete_transactions)); |
2840 | out += sprintf(out, "events: %u\n", | 2850 | seq_printf(m, "events: %u\n", |
2841 | smi_get_stat(smi, events)); | 2851 | smi_get_stat(smi, events)); |
2842 | out += sprintf(out, "watchdog_pretimeouts: %u\n", | 2852 | seq_printf(m, "watchdog_pretimeouts: %u\n", |
2843 | smi_get_stat(smi, watchdog_pretimeouts)); | 2853 | smi_get_stat(smi, watchdog_pretimeouts)); |
2844 | out += sprintf(out, "incoming_messages: %u\n", | 2854 | seq_printf(m, "incoming_messages: %u\n", |
2845 | smi_get_stat(smi, incoming_messages)); | 2855 | smi_get_stat(smi, incoming_messages)); |
2856 | return 0; | ||
2857 | } | ||
2846 | 2858 | ||
2847 | return out - page; | 2859 | static int smi_si_stats_proc_open(struct inode *inode, struct file *file) |
2860 | { | ||
2861 | return single_open(file, smi_si_stats_proc_show, PDE(inode)->data); | ||
2848 | } | 2862 | } |
2849 | 2863 | ||
2850 | static int param_read_proc(char *page, char **start, off_t off, | 2864 | static const struct file_operations smi_si_stats_proc_ops = { |
2851 | int count, int *eof, void *data) | 2865 | .open = smi_si_stats_proc_open, |
2866 | .read = seq_read, | ||
2867 | .llseek = seq_lseek, | ||
2868 | .release = single_release, | ||
2869 | }; | ||
2870 | |||
2871 | static int smi_params_proc_show(struct seq_file *m, void *v) | ||
2852 | { | 2872 | { |
2853 | struct smi_info *smi = data; | 2873 | struct smi_info *smi = m->private; |
2854 | 2874 | ||
2855 | return sprintf(page, | 2875 | return seq_printf(m, |
2856 | "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n", | 2876 | "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n", |
2857 | si_to_str[smi->si_type], | 2877 | si_to_str[smi->si_type], |
2858 | addr_space_to_str[smi->io.addr_type], | 2878 | addr_space_to_str[smi->io.addr_type], |
@@ -2864,6 +2884,18 @@ static int param_read_proc(char *page, char **start, off_t off, | |||
2864 | smi->slave_addr); | 2884 | smi->slave_addr); |
2865 | } | 2885 | } |
2866 | 2886 | ||
2887 | static int smi_params_proc_open(struct inode *inode, struct file *file) | ||
2888 | { | ||
2889 | return single_open(file, smi_params_proc_show, PDE(inode)->data); | ||
2890 | } | ||
2891 | |||
2892 | static const struct file_operations smi_params_proc_ops = { | ||
2893 | .open = smi_params_proc_open, | ||
2894 | .read = seq_read, | ||
2895 | .llseek = seq_lseek, | ||
2896 | .release = single_release, | ||
2897 | }; | ||
2898 | |||
2867 | /* | 2899 | /* |
2868 | * oem_data_avail_to_receive_msg_avail | 2900 | * oem_data_avail_to_receive_msg_avail |
2869 | * @info - smi_info structure with msg_flags set | 2901 | * @info - smi_info structure with msg_flags set |
@@ -3257,7 +3289,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3257 | } | 3289 | } |
3258 | 3290 | ||
3259 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "type", | 3291 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "type", |
3260 | type_file_read_proc, | 3292 | &smi_type_proc_ops, |
3261 | new_smi); | 3293 | new_smi); |
3262 | if (rv) { | 3294 | if (rv) { |
3263 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); | 3295 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); |
@@ -3265,7 +3297,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3265 | } | 3297 | } |
3266 | 3298 | ||
3267 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats", | 3299 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats", |
3268 | stat_file_read_proc, | 3300 | &smi_si_stats_proc_ops, |
3269 | new_smi); | 3301 | new_smi); |
3270 | if (rv) { | 3302 | if (rv) { |
3271 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); | 3303 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); |
@@ -3273,7 +3305,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3273 | } | 3305 | } |
3274 | 3306 | ||
3275 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "params", | 3307 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "params", |
3276 | param_read_proc, | 3308 | &smi_params_proc_ops, |
3277 | new_smi); | 3309 | new_smi); |
3278 | if (rv) { | 3310 | if (rv) { |
3279 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); | 3311 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); |
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 966a95bc974b..25d139c9dbed 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c | |||
@@ -271,14 +271,13 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, | |||
271 | pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | 271 | pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; |
272 | vdata_size = sizeof(struct vma_data) + pages * sizeof(long); | 272 | vdata_size = sizeof(struct vma_data) + pages * sizeof(long); |
273 | if (vdata_size <= PAGE_SIZE) | 273 | if (vdata_size <= PAGE_SIZE) |
274 | vdata = kmalloc(vdata_size, GFP_KERNEL); | 274 | vdata = kzalloc(vdata_size, GFP_KERNEL); |
275 | else { | 275 | else { |
276 | vdata = vmalloc(vdata_size); | 276 | vdata = vzalloc(vdata_size); |
277 | flags = VMD_VMALLOCED; | 277 | flags = VMD_VMALLOCED; |
278 | } | 278 | } |
279 | if (!vdata) | 279 | if (!vdata) |
280 | return -ENOMEM; | 280 | return -ENOMEM; |
281 | memset(vdata, 0, vdata_size); | ||
282 | 281 | ||
283 | vdata->vm_start = vma->vm_start; | 282 | vdata->vm_start = vma->vm_start; |
284 | vdata->vm_end = vma->vm_end; | 283 | vdata->vm_end = vma->vm_end; |
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index f176dbaeb15a..3fcf80ff12f2 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c | |||
@@ -457,6 +457,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
457 | return -ENODEV; | 457 | return -ENODEV; |
458 | 458 | ||
459 | modes = port->modes; | 459 | modes = port->modes; |
460 | parport_put_port(port); | ||
460 | if (copy_to_user (argp, &modes, sizeof (modes))) { | 461 | if (copy_to_user (argp, &modes, sizeof (modes))) { |
461 | return -EFAULT; | 462 | return -EFAULT; |
462 | } | 463 | } |
diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index cace0a7b707a..e47e73bbbcc5 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/edac.h> | 19 | #include <linux/edac.h> |
20 | #include "edac_core.h" | 20 | #include "edac_core.h" |
21 | 21 | ||
22 | #define AMD76X_REVISION " Ver: 2.0.2 " __DATE__ | 22 | #define AMD76X_REVISION " Ver: 2.0.2" |
23 | #define EDAC_MOD_STR "amd76x_edac" | 23 | #define EDAC_MOD_STR "amd76x_edac" |
24 | 24 | ||
25 | #define amd76x_printk(level, fmt, arg...) \ | 25 | #define amd76x_printk(level, fmt, arg...) \ |
diff --git a/drivers/edac/amd8111_edac.c b/drivers/edac/amd8111_edac.c index 35b78d04bbfa..ddd890052ce2 100644 --- a/drivers/edac/amd8111_edac.c +++ b/drivers/edac/amd8111_edac.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include "edac_module.h" | 33 | #include "edac_module.h" |
34 | #include "amd8111_edac.h" | 34 | #include "amd8111_edac.h" |
35 | 35 | ||
36 | #define AMD8111_EDAC_REVISION " Ver: 1.0.0 " __DATE__ | 36 | #define AMD8111_EDAC_REVISION " Ver: 1.0.0" |
37 | #define AMD8111_EDAC_MOD_STR "amd8111_edac" | 37 | #define AMD8111_EDAC_MOD_STR "amd8111_edac" |
38 | 38 | ||
39 | #define PCI_DEVICE_ID_AMD_8111_PCI 0x7460 | 39 | #define PCI_DEVICE_ID_AMD_8111_PCI 0x7460 |
diff --git a/drivers/edac/amd8131_edac.c b/drivers/edac/amd8131_edac.c index b432d60c622a..a5c680561c73 100644 --- a/drivers/edac/amd8131_edac.c +++ b/drivers/edac/amd8131_edac.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include "edac_module.h" | 33 | #include "edac_module.h" |
34 | #include "amd8131_edac.h" | 34 | #include "amd8131_edac.h" |
35 | 35 | ||
36 | #define AMD8131_EDAC_REVISION " Ver: 1.0.0 " __DATE__ | 36 | #define AMD8131_EDAC_REVISION " Ver: 1.0.0" |
37 | #define AMD8131_EDAC_MOD_STR "amd8131_edac" | 37 | #define AMD8131_EDAC_MOD_STR "amd8131_edac" |
38 | 38 | ||
39 | /* Wrapper functions for accessing PCI configuration space */ | 39 | /* Wrapper functions for accessing PCI configuration space */ |
diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index 837ad8f85b48..a687a0d16962 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include "edac_core.h" | 30 | #include "edac_core.h" |
31 | #include "edac_module.h" | 31 | #include "edac_module.h" |
32 | 32 | ||
33 | #define CPC925_EDAC_REVISION " Ver: 1.0.0 " __DATE__ | 33 | #define CPC925_EDAC_REVISION " Ver: 1.0.0" |
34 | #define CPC925_EDAC_MOD_STR "cpc925_edac" | 34 | #define CPC925_EDAC_MOD_STR "cpc925_edac" |
35 | 35 | ||
36 | #define cpc925_printk(level, fmt, arg...) \ | 36 | #define cpc925_printk(level, fmt, arg...) \ |
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index ec302d426589..1af531a11d21 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/edac.h> | 24 | #include <linux/edac.h> |
25 | #include "edac_core.h" | 25 | #include "edac_core.h" |
26 | 26 | ||
27 | #define E752X_REVISION " Ver: 2.0.2 " __DATE__ | 27 | #define E752X_REVISION " Ver: 2.0.2" |
28 | #define EDAC_MOD_STR "e752x_edac" | 28 | #define EDAC_MOD_STR "e752x_edac" |
29 | 29 | ||
30 | static int report_non_memory_errors; | 30 | static int report_non_memory_errors; |
diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 1731d7245816..6ffb6d23281f 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/edac.h> | 29 | #include <linux/edac.h> |
30 | #include "edac_core.h" | 30 | #include "edac_core.h" |
31 | 31 | ||
32 | #define E7XXX_REVISION " Ver: 2.0.2 " __DATE__ | 32 | #define E7XXX_REVISION " Ver: 2.0.2" |
33 | #define EDAC_MOD_STR "e7xxx_edac" | 33 | #define EDAC_MOD_STR "e7xxx_edac" |
34 | 34 | ||
35 | #define e7xxx_printk(level, fmt, arg...) \ | 35 | #define e7xxx_printk(level, fmt, arg...) \ |
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index eefa3501916b..55b8278bb172 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h | |||
@@ -421,10 +421,6 @@ struct mem_ctl_info { | |||
421 | u32 ce_count; /* Total Correctable Errors for this MC */ | 421 | u32 ce_count; /* Total Correctable Errors for this MC */ |
422 | unsigned long start_time; /* mci load start time (in jiffies) */ | 422 | unsigned long start_time; /* mci load start time (in jiffies) */ |
423 | 423 | ||
424 | /* this stuff is for safe removal of mc devices from global list while | ||
425 | * NMI handlers may be traversing list | ||
426 | */ | ||
427 | struct rcu_head rcu; | ||
428 | struct completion complete; | 424 | struct completion complete; |
429 | 425 | ||
430 | /* edac sysfs device control */ | 426 | /* edac sysfs device control */ |
@@ -620,10 +616,6 @@ struct edac_device_ctl_info { | |||
620 | 616 | ||
621 | unsigned long start_time; /* edac_device load start time (jiffies) */ | 617 | unsigned long start_time; /* edac_device load start time (jiffies) */ |
622 | 618 | ||
623 | /* these are for safe removal of mc devices from global list while | ||
624 | * NMI handlers may be traversing list | ||
625 | */ | ||
626 | struct rcu_head rcu; | ||
627 | struct completion removal_complete; | 619 | struct completion removal_complete; |
628 | 620 | ||
629 | /* sysfs top name under 'edac' directory | 621 | /* sysfs top name under 'edac' directory |
@@ -722,10 +714,6 @@ struct edac_pci_ctl_info { | |||
722 | 714 | ||
723 | unsigned long start_time; /* edac_pci load start time (jiffies) */ | 715 | unsigned long start_time; /* edac_pci load start time (jiffies) */ |
724 | 716 | ||
725 | /* these are for safe removal of devices from global list while | ||
726 | * NMI handlers may be traversing list | ||
727 | */ | ||
728 | struct rcu_head rcu; | ||
729 | struct completion complete; | 717 | struct completion complete; |
730 | 718 | ||
731 | /* sysfs top name under 'edac' directory | 719 | /* sysfs top name under 'edac' directory |
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index a7408cf86f37..c3f67437afb6 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c | |||
@@ -346,30 +346,18 @@ fail1: | |||
346 | } | 346 | } |
347 | 347 | ||
348 | /* | 348 | /* |
349 | * complete_edac_device_list_del | ||
350 | * | ||
351 | * callback function when reference count is zero | ||
352 | */ | ||
353 | static void complete_edac_device_list_del(struct rcu_head *head) | ||
354 | { | ||
355 | struct edac_device_ctl_info *edac_dev; | ||
356 | |||
357 | edac_dev = container_of(head, struct edac_device_ctl_info, rcu); | ||
358 | INIT_LIST_HEAD(&edac_dev->link); | ||
359 | } | ||
360 | |||
361 | /* | ||
362 | * del_edac_device_from_global_list | 349 | * del_edac_device_from_global_list |
363 | * | ||
364 | * remove the RCU, setup for a callback call, | ||
365 | * then wait for the callback to occur | ||
366 | */ | 350 | */ |
367 | static void del_edac_device_from_global_list(struct edac_device_ctl_info | 351 | static void del_edac_device_from_global_list(struct edac_device_ctl_info |
368 | *edac_device) | 352 | *edac_device) |
369 | { | 353 | { |
370 | list_del_rcu(&edac_device->link); | 354 | list_del_rcu(&edac_device->link); |
371 | call_rcu(&edac_device->rcu, complete_edac_device_list_del); | 355 | |
372 | rcu_barrier(); | 356 | /* these are for safe removal of devices from global list while |
357 | * NMI handlers may be traversing list | ||
358 | */ | ||
359 | synchronize_rcu(); | ||
360 | INIT_LIST_HEAD(&edac_device->link); | ||
373 | } | 361 | } |
374 | 362 | ||
375 | /* | 363 | /* |
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 1d8056049072..d69144a09043 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
@@ -447,20 +447,16 @@ fail1: | |||
447 | return 1; | 447 | return 1; |
448 | } | 448 | } |
449 | 449 | ||
450 | static void complete_mc_list_del(struct rcu_head *head) | ||
451 | { | ||
452 | struct mem_ctl_info *mci; | ||
453 | |||
454 | mci = container_of(head, struct mem_ctl_info, rcu); | ||
455 | INIT_LIST_HEAD(&mci->link); | ||
456 | } | ||
457 | |||
458 | static void del_mc_from_global_list(struct mem_ctl_info *mci) | 450 | static void del_mc_from_global_list(struct mem_ctl_info *mci) |
459 | { | 451 | { |
460 | atomic_dec(&edac_handlers); | 452 | atomic_dec(&edac_handlers); |
461 | list_del_rcu(&mci->link); | 453 | list_del_rcu(&mci->link); |
462 | call_rcu(&mci->rcu, complete_mc_list_del); | 454 | |
463 | rcu_barrier(); | 455 | /* these are for safe removal of devices from global list while |
456 | * NMI handlers may be traversing list | ||
457 | */ | ||
458 | synchronize_rcu(); | ||
459 | INIT_LIST_HEAD(&mci->link); | ||
464 | } | 460 | } |
465 | 461 | ||
466 | /** | 462 | /** |
diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c index be4b075c3098..5ddaa86d6a6e 100644 --- a/drivers/edac/edac_module.c +++ b/drivers/edac/edac_module.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include "edac_core.h" | 15 | #include "edac_core.h" |
16 | #include "edac_module.h" | 16 | #include "edac_module.h" |
17 | 17 | ||
18 | #define EDAC_VERSION "Ver: 2.1.0 " __DATE__ | 18 | #define EDAC_VERSION "Ver: 2.1.0" |
19 | 19 | ||
20 | #ifdef CONFIG_EDAC_DEBUG | 20 | #ifdef CONFIG_EDAC_DEBUG |
21 | /* Values of 0 to 4 will generate output */ | 21 | /* Values of 0 to 4 will generate output */ |
diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index efb5d5650783..2b378207d571 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c | |||
@@ -164,19 +164,6 @@ fail1: | |||
164 | } | 164 | } |
165 | 165 | ||
166 | /* | 166 | /* |
167 | * complete_edac_pci_list_del | ||
168 | * | ||
169 | * RCU completion callback to indicate item is deleted | ||
170 | */ | ||
171 | static void complete_edac_pci_list_del(struct rcu_head *head) | ||
172 | { | ||
173 | struct edac_pci_ctl_info *pci; | ||
174 | |||
175 | pci = container_of(head, struct edac_pci_ctl_info, rcu); | ||
176 | INIT_LIST_HEAD(&pci->link); | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * del_edac_pci_from_global_list | 167 | * del_edac_pci_from_global_list |
181 | * | 168 | * |
182 | * remove the PCI control struct from the global list | 169 | * remove the PCI control struct from the global list |
@@ -184,8 +171,12 @@ static void complete_edac_pci_list_del(struct rcu_head *head) | |||
184 | static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci) | 171 | static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci) |
185 | { | 172 | { |
186 | list_del_rcu(&pci->link); | 173 | list_del_rcu(&pci->link); |
187 | call_rcu(&pci->rcu, complete_edac_pci_list_del); | 174 | |
188 | rcu_barrier(); | 175 | /* these are for safe removal of devices from global list while |
176 | * NMI handlers may be traversing list | ||
177 | */ | ||
178 | synchronize_rcu(); | ||
179 | INIT_LIST_HEAD(&pci->link); | ||
189 | } | 180 | } |
190 | 181 | ||
191 | #if 0 | 182 | #if 0 |
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 87f427c2ce5c..4dc3ac25a422 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c | |||
@@ -27,7 +27,7 @@ | |||
27 | /* | 27 | /* |
28 | * Alter this version for the I5000 module when modifications are made | 28 | * Alter this version for the I5000 module when modifications are made |
29 | */ | 29 | */ |
30 | #define I5000_REVISION " Ver: 2.0.12 " __DATE__ | 30 | #define I5000_REVISION " Ver: 2.0.12" |
31 | #define EDAC_MOD_STR "i5000_edac" | 31 | #define EDAC_MOD_STR "i5000_edac" |
32 | 32 | ||
33 | #define i5000_printk(level, fmt, arg...) \ | 33 | #define i5000_printk(level, fmt, arg...) \ |
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 80a465efbae8..74d6ec342afb 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c | |||
@@ -33,7 +33,7 @@ | |||
33 | /* | 33 | /* |
34 | * Alter this version for the I5400 module when modifications are made | 34 | * Alter this version for the I5400 module when modifications are made |
35 | */ | 35 | */ |
36 | #define I5400_REVISION " Ver: 1.0.0 " __DATE__ | 36 | #define I5400_REVISION " Ver: 1.0.0" |
37 | 37 | ||
38 | #define EDAC_MOD_STR "i5400_edac" | 38 | #define EDAC_MOD_STR "i5400_edac" |
39 | 39 | ||
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 363cc1602944..a76fe8366b68 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c | |||
@@ -31,7 +31,7 @@ | |||
31 | /* | 31 | /* |
32 | * Alter this version for the I7300 module when modifications are made | 32 | * Alter this version for the I7300 module when modifications are made |
33 | */ | 33 | */ |
34 | #define I7300_REVISION " Ver: 1.0.0 " __DATE__ | 34 | #define I7300_REVISION " Ver: 1.0.0" |
35 | 35 | ||
36 | #define EDAC_MOD_STR "i7300_edac" | 36 | #define EDAC_MOD_STR "i7300_edac" |
37 | 37 | ||
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 465cbc25149f..04f1e7ce02b1 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c | |||
@@ -59,7 +59,7 @@ MODULE_PARM_DESC(use_pci_fixup, "Enable PCI fixup to seek for hidden devices"); | |||
59 | /* | 59 | /* |
60 | * Alter this version for the module when modifications are made | 60 | * Alter this version for the module when modifications are made |
61 | */ | 61 | */ |
62 | #define I7CORE_REVISION " Ver: 1.0.0 " __DATE__ | 62 | #define I7CORE_REVISION " Ver: 1.0.0" |
63 | #define EDAC_MOD_STR "i7core_edac" | 63 | #define EDAC_MOD_STR "i7core_edac" |
64 | 64 | ||
65 | /* | 65 | /* |
diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index b8a95cf50718..931a05775049 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/edac.h> | 16 | #include <linux/edac.h> |
17 | #include "edac_core.h" | 17 | #include "edac_core.h" |
18 | 18 | ||
19 | #define I82860_REVISION " Ver: 2.0.2 " __DATE__ | 19 | #define I82860_REVISION " Ver: 2.0.2" |
20 | #define EDAC_MOD_STR "i82860_edac" | 20 | #define EDAC_MOD_STR "i82860_edac" |
21 | 21 | ||
22 | #define i82860_printk(level, fmt, arg...) \ | 22 | #define i82860_printk(level, fmt, arg...) \ |
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index b2fd1e899142..33864c63c684 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/edac.h> | 20 | #include <linux/edac.h> |
21 | #include "edac_core.h" | 21 | #include "edac_core.h" |
22 | 22 | ||
23 | #define I82875P_REVISION " Ver: 2.0.2 " __DATE__ | 23 | #define I82875P_REVISION " Ver: 2.0.2" |
24 | #define EDAC_MOD_STR "i82875p_edac" | 24 | #define EDAC_MOD_STR "i82875p_edac" |
25 | 25 | ||
26 | #define i82875p_printk(level, fmt, arg...) \ | 26 | #define i82875p_printk(level, fmt, arg...) \ |
diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 92e65e7038e9..a5da732fe5b2 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/edac.h> | 16 | #include <linux/edac.h> |
17 | #include "edac_core.h" | 17 | #include "edac_core.h" |
18 | 18 | ||
19 | #define I82975X_REVISION " Ver: 1.0.0 " __DATE__ | 19 | #define I82975X_REVISION " Ver: 1.0.0" |
20 | #define EDAC_MOD_STR "i82975x_edac" | 20 | #define EDAC_MOD_STR "i82975x_edac" |
21 | 21 | ||
22 | #define i82975x_printk(level, fmt, arg...) \ | 22 | #define i82975x_printk(level, fmt, arg...) \ |
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h index cb24df839460..932016f2cf06 100644 --- a/drivers/edac/mpc85xx_edac.h +++ b/drivers/edac/mpc85xx_edac.h | |||
@@ -11,7 +11,7 @@ | |||
11 | #ifndef _MPC85XX_EDAC_H_ | 11 | #ifndef _MPC85XX_EDAC_H_ |
12 | #define _MPC85XX_EDAC_H_ | 12 | #define _MPC85XX_EDAC_H_ |
13 | 13 | ||
14 | #define MPC85XX_REVISION " Ver: 2.0.0 " __DATE__ | 14 | #define MPC85XX_REVISION " Ver: 2.0.0" |
15 | #define EDAC_MOD_STR "MPC85xx_edac" | 15 | #define EDAC_MOD_STR "MPC85xx_edac" |
16 | 16 | ||
17 | #define mpc85xx_printk(level, fmt, arg...) \ | 17 | #define mpc85xx_printk(level, fmt, arg...) \ |
diff --git a/drivers/edac/mv64x60_edac.h b/drivers/edac/mv64x60_edac.h index e042e2daa8f4..c7f209c92a1a 100644 --- a/drivers/edac/mv64x60_edac.h +++ b/drivers/edac/mv64x60_edac.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #ifndef _MV64X60_EDAC_H_ | 12 | #ifndef _MV64X60_EDAC_H_ |
13 | #define _MV64X60_EDAC_H_ | 13 | #define _MV64X60_EDAC_H_ |
14 | 14 | ||
15 | #define MV64x60_REVISION " Ver: 2.0.0 " __DATE__ | 15 | #define MV64x60_REVISION " Ver: 2.0.0" |
16 | #define EDAC_MOD_STR "MV64x60_edac" | 16 | #define EDAC_MOD_STR "MV64x60_edac" |
17 | 17 | ||
18 | #define mv64x60_printk(level, fmt, arg...) \ | 18 | #define mv64x60_printk(level, fmt, arg...) \ |
diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index af8e7b1aa290..0de7d8770891 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c | |||
@@ -113,7 +113,7 @@ | |||
113 | #define EDAC_OPSTATE_UNKNOWN_STR "unknown" | 113 | #define EDAC_OPSTATE_UNKNOWN_STR "unknown" |
114 | 114 | ||
115 | #define PPC4XX_EDAC_MODULE_NAME "ppc4xx_edac" | 115 | #define PPC4XX_EDAC_MODULE_NAME "ppc4xx_edac" |
116 | #define PPC4XX_EDAC_MODULE_REVISION "v1.0.0 " __DATE__ | 116 | #define PPC4XX_EDAC_MODULE_REVISION "v1.0.0" |
117 | 117 | ||
118 | #define PPC4XX_EDAC_MESSAGE_SIZE 256 | 118 | #define PPC4XX_EDAC_MESSAGE_SIZE 256 |
119 | 119 | ||
diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 678513738c33..b153674431f1 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/edac.h> | 22 | #include <linux/edac.h> |
23 | #include "edac_core.h" | 23 | #include "edac_core.h" |
24 | 24 | ||
25 | #define R82600_REVISION " Ver: 2.0.2 " __DATE__ | 25 | #define R82600_REVISION " Ver: 2.0.2" |
26 | #define EDAC_MOD_STR "r82600_edac" | 26 | #define EDAC_MOD_STR "r82600_edac" |
27 | 27 | ||
28 | #define r82600_printk(level, fmt, arg...) \ | 28 | #define r82600_printk(level, fmt, arg...) \ |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 978852afc9dc..592397629ddc 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -454,4 +454,11 @@ config AB8500_GPIO | |||
454 | depends on AB8500_CORE && BROKEN | 454 | depends on AB8500_CORE && BROKEN |
455 | help | 455 | help |
456 | Select this to enable the AB8500 IC GPIO driver | 456 | Select this to enable the AB8500 IC GPIO driver |
457 | |||
458 | config GPIO_TPS65910 | ||
459 | bool "TPS65910 GPIO" | ||
460 | depends on MFD_TPS65910 | ||
461 | help | ||
462 | Select this option to enable GPIO driver for the TPS65910 | ||
463 | chip family. | ||
457 | endif | 464 | endif |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4182040a3522..b605f8ec6fbe 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -47,3 +47,4 @@ obj-$(CONFIG_GPIO_SX150X) += sx150x.o | |||
47 | obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o | 47 | obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o |
48 | obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o | 48 | obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o |
49 | obj-$(CONFIG_AB8500_GPIO) += ab8500-gpio.o | 49 | obj-$(CONFIG_AB8500_GPIO) += ab8500-gpio.o |
50 | obj-$(CONFIG_GPIO_TPS65910) += tps65910-gpio.o | ||
diff --git a/drivers/gpio/tps65910-gpio.c b/drivers/gpio/tps65910-gpio.c new file mode 100644 index 000000000000..8d1ddfdd63eb --- /dev/null +++ b/drivers/gpio/tps65910-gpio.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * tps65910-gpio.c -- TI TPS6591x | ||
3 | * | ||
4 | * Copyright 2010 Texas Instruments Inc. | ||
5 | * | ||
6 | * Author: Graeme Gregory <gg@slimlogic.co.uk> | ||
7 | * Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/gpio.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/mfd/tps65910.h> | ||
22 | |||
23 | static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset) | ||
24 | { | ||
25 | struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); | ||
26 | uint8_t val; | ||
27 | |||
28 | tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val); | ||
29 | |||
30 | if (val & GPIO_STS_MASK) | ||
31 | return 1; | ||
32 | |||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset, | ||
37 | int value) | ||
38 | { | ||
39 | struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); | ||
40 | |||
41 | if (value) | ||
42 | tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset, | ||
43 | GPIO_SET_MASK); | ||
44 | else | ||
45 | tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset, | ||
46 | GPIO_SET_MASK); | ||
47 | } | ||
48 | |||
49 | static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset, | ||
50 | int value) | ||
51 | { | ||
52 | struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); | ||
53 | |||
54 | /* Set the initial value */ | ||
55 | tps65910_gpio_set(gc, 0, value); | ||
56 | |||
57 | return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset, | ||
58 | GPIO_CFG_MASK); | ||
59 | } | ||
60 | |||
61 | static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset) | ||
62 | { | ||
63 | struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio); | ||
64 | |||
65 | return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset, | ||
66 | GPIO_CFG_MASK); | ||
67 | } | ||
68 | |||
69 | void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) | ||
70 | { | ||
71 | int ret; | ||
72 | |||
73 | if (!gpio_base) | ||
74 | return; | ||
75 | |||
76 | tps65910->gpio.owner = THIS_MODULE; | ||
77 | tps65910->gpio.label = tps65910->i2c_client->name; | ||
78 | tps65910->gpio.dev = tps65910->dev; | ||
79 | tps65910->gpio.base = gpio_base; | ||
80 | |||
81 | switch(tps65910_chip_id(tps65910)) { | ||
82 | case TPS65910: | ||
83 | tps65910->gpio.ngpio = 6; | ||
84 | case TPS65911: | ||
85 | tps65910->gpio.ngpio = 9; | ||
86 | default: | ||
87 | return; | ||
88 | } | ||
89 | tps65910->gpio.can_sleep = 1; | ||
90 | |||
91 | tps65910->gpio.direction_input = tps65910_gpio_input; | ||
92 | tps65910->gpio.direction_output = tps65910_gpio_output; | ||
93 | tps65910->gpio.set = tps65910_gpio_set; | ||
94 | tps65910->gpio.get = tps65910_gpio_get; | ||
95 | |||
96 | ret = gpiochip_add(&tps65910->gpio); | ||
97 | |||
98 | if (ret) | ||
99 | dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret); | ||
100 | } | ||
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 9577c432e77f..de3d2465fe24 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -350,6 +350,7 @@ static int get_pkg_tjmax(unsigned int cpu, struct device *dev) | |||
350 | 350 | ||
351 | static int create_name_attr(struct platform_data *pdata, struct device *dev) | 351 | static int create_name_attr(struct platform_data *pdata, struct device *dev) |
352 | { | 352 | { |
353 | sysfs_attr_init(&pdata->name_attr.attr); | ||
353 | pdata->name_attr.attr.name = "name"; | 354 | pdata->name_attr.attr.name = "name"; |
354 | pdata->name_attr.attr.mode = S_IRUGO; | 355 | pdata->name_attr.attr.mode = S_IRUGO; |
355 | pdata->name_attr.show = show_name; | 356 | pdata->name_attr.show = show_name; |
@@ -372,6 +373,7 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev, | |||
372 | for (i = 0; i < MAX_ATTRS; i++) { | 373 | for (i = 0; i < MAX_ATTRS; i++) { |
373 | snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], | 374 | snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], |
374 | attr_no); | 375 | attr_no); |
376 | sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); | ||
375 | tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; | 377 | tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; |
376 | tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO; | 378 | tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO; |
377 | tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; | 379 | tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; |
@@ -422,7 +424,7 @@ static void update_ttarget(__u8 cpu_model, struct temp_data *tdata, | |||
422 | } | 424 | } |
423 | } | 425 | } |
424 | 426 | ||
425 | static int chk_ucode_version(struct platform_device *pdev) | 427 | static int __devinit chk_ucode_version(struct platform_device *pdev) |
426 | { | 428 | { |
427 | struct cpuinfo_x86 *c = &cpu_data(pdev->id); | 429 | struct cpuinfo_x86 *c = &cpu_data(pdev->id); |
428 | int err; | 430 | int err; |
@@ -509,8 +511,8 @@ static int create_core_data(struct platform_data *pdata, | |||
509 | /* | 511 | /* |
510 | * Provide a single set of attributes for all HT siblings of a core | 512 | * Provide a single set of attributes for all HT siblings of a core |
511 | * to avoid duplicate sensors (the processor ID and core ID of all | 513 | * to avoid duplicate sensors (the processor ID and core ID of all |
512 | * HT siblings of a core is the same). | 514 | * HT siblings of a core are the same). |
513 | * Skip if a HT sibling of this core is already online. | 515 | * Skip if a HT sibling of this core is already registered. |
514 | * This is not an error. | 516 | * This is not an error. |
515 | */ | 517 | */ |
516 | if (pdata->core_data[attr_no] != NULL) | 518 | if (pdata->core_data[attr_no] != NULL) |
@@ -770,10 +772,10 @@ static void __cpuinit put_core_offline(unsigned int cpu) | |||
770 | coretemp_remove_core(pdata, &pdev->dev, indx); | 772 | coretemp_remove_core(pdata, &pdev->dev, indx); |
771 | 773 | ||
772 | /* | 774 | /* |
773 | * If a core is taken offline, but a HT sibling of the same core is | 775 | * If a HT sibling of a core is taken offline, but another HT sibling |
774 | * still online, register the alternate sibling. This ensures that | 776 | * of the same core is still online, register the alternate sibling. |
775 | * exactly one set of attributes is provided as long as at least one | 777 | * This ensures that exactly one set of attributes is provided as long |
776 | * HT sibling of a core is online. | 778 | * as at least one HT sibling of a core is online. |
777 | */ | 779 | */ |
778 | for_each_sibling(i, cpu) { | 780 | for_each_sibling(i, cpu) { |
779 | if (i != cpu) { | 781 | if (i != cpu) { |
diff --git a/drivers/hwmon/pmbus_core.c b/drivers/hwmon/pmbus_core.c index 98799bab69ce..354770ed3186 100644 --- a/drivers/hwmon/pmbus_core.c +++ b/drivers/hwmon/pmbus_core.c | |||
@@ -707,6 +707,7 @@ do { \ | |||
707 | struct sensor_device_attribute *a \ | 707 | struct sensor_device_attribute *a \ |
708 | = &data->_type##s[data->num_##_type##s].attribute; \ | 708 | = &data->_type##s[data->num_##_type##s].attribute; \ |
709 | BUG_ON(data->num_attributes >= data->max_attributes); \ | 709 | BUG_ON(data->num_attributes >= data->max_attributes); \ |
710 | sysfs_attr_init(&a->dev_attr.attr); \ | ||
710 | a->dev_attr.attr.name = _name; \ | 711 | a->dev_attr.attr.name = _name; \ |
711 | a->dev_attr.attr.mode = _mode; \ | 712 | a->dev_attr.attr.mode = _mode; \ |
712 | a->dev_attr.show = _show; \ | 713 | a->dev_attr.show = _show; \ |
diff --git a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c index d36a4c09e25d..0bbee7824d78 100644 --- a/drivers/isdn/hardware/eicon/divasfunc.c +++ b/drivers/isdn/hardware/eicon/divasfunc.c | |||
@@ -113,9 +113,8 @@ void diva_xdi_didd_remove_adapter(int card) | |||
113 | static void start_dbg(void) | 113 | static void start_dbg(void) |
114 | { | 114 | { |
115 | DbgRegister("DIVAS", DRIVERRELEASE_DIVAS, (debugmask) ? debugmask : DBG_DEFAULT); | 115 | DbgRegister("DIVAS", DRIVERRELEASE_DIVAS, (debugmask) ? debugmask : DBG_DEFAULT); |
116 | DBG_LOG(("DIVA ISDNXDI BUILD (%s[%s]-%s-%s)", | 116 | DBG_LOG(("DIVA ISDNXDI BUILD (%s[%s])", |
117 | DIVA_BUILD, diva_xdi_common_code_build, __DATE__, | 117 | DIVA_BUILD, diva_xdi_common_code_build)) |
118 | __TIME__)) | ||
119 | } | 118 | } |
120 | 119 | ||
121 | /* | 120 | /* |
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 2d8b4044be36..b2b0c45f32a9 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
23 | #include <linux/i2c-algo-bit.h> | ||
23 | #include <linux/init.h> | 24 | #include <linux/init.h> |
24 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
@@ -49,11 +50,12 @@ | |||
49 | 50 | ||
50 | #define UNSET (-1U) | 51 | #define UNSET (-1U) |
51 | 52 | ||
52 | #define DM1105_BOARD_NOAUTO UNSET | 53 | #define DM1105_BOARD_NOAUTO UNSET |
53 | #define DM1105_BOARD_UNKNOWN 0 | 54 | #define DM1105_BOARD_UNKNOWN 0 |
54 | #define DM1105_BOARD_DVBWORLD_2002 1 | 55 | #define DM1105_BOARD_DVBWORLD_2002 1 |
55 | #define DM1105_BOARD_DVBWORLD_2004 2 | 56 | #define DM1105_BOARD_DVBWORLD_2004 2 |
56 | #define DM1105_BOARD_AXESS_DM05 3 | 57 | #define DM1105_BOARD_AXESS_DM05 3 |
58 | #define DM1105_BOARD_UNBRANDED_I2C_ON_GPIO 4 | ||
57 | 59 | ||
58 | /* ----------------------------------------------- */ | 60 | /* ----------------------------------------------- */ |
59 | /* | 61 | /* |
@@ -157,22 +159,38 @@ | |||
157 | #define DM1105_MAX 0x04 | 159 | #define DM1105_MAX 0x04 |
158 | 160 | ||
159 | #define DRIVER_NAME "dm1105" | 161 | #define DRIVER_NAME "dm1105" |
162 | #define DM1105_I2C_GPIO_NAME "dm1105-gpio" | ||
160 | 163 | ||
161 | #define DM1105_DMA_PACKETS 47 | 164 | #define DM1105_DMA_PACKETS 47 |
162 | #define DM1105_DMA_PACKET_LENGTH (128*4) | 165 | #define DM1105_DMA_PACKET_LENGTH (128*4) |
163 | #define DM1105_DMA_BYTES (128 * 4 * DM1105_DMA_PACKETS) | 166 | #define DM1105_DMA_BYTES (128 * 4 * DM1105_DMA_PACKETS) |
164 | 167 | ||
168 | /* */ | ||
169 | #define GPIO08 (1 << 8) | ||
170 | #define GPIO13 (1 << 13) | ||
171 | #define GPIO14 (1 << 14) | ||
172 | #define GPIO15 (1 << 15) | ||
173 | #define GPIO16 (1 << 16) | ||
174 | #define GPIO17 (1 << 17) | ||
175 | #define GPIO_ALL 0x03ffff | ||
176 | |||
165 | /* GPIO's for LNB power control */ | 177 | /* GPIO's for LNB power control */ |
166 | #define DM1105_LNB_MASK 0x00000000 | 178 | #define DM1105_LNB_MASK (GPIO_ALL & ~(GPIO14 | GPIO13)) |
167 | #define DM1105_LNB_OFF 0x00020000 | 179 | #define DM1105_LNB_OFF GPIO17 |
168 | #define DM1105_LNB_13V 0x00010100 | 180 | #define DM1105_LNB_13V (GPIO16 | GPIO08) |
169 | #define DM1105_LNB_18V 0x00000100 | 181 | #define DM1105_LNB_18V GPIO08 |
170 | 182 | ||
171 | /* GPIO's for LNB power control for Axess DM05 */ | 183 | /* GPIO's for LNB power control for Axess DM05 */ |
172 | #define DM05_LNB_MASK 0x00000000 | 184 | #define DM05_LNB_MASK (GPIO_ALL & ~(GPIO14 | GPIO13)) |
173 | #define DM05_LNB_OFF 0x00020000/* actually 13v */ | 185 | #define DM05_LNB_OFF GPIO17/* actually 13v */ |
174 | #define DM05_LNB_13V 0x00020000 | 186 | #define DM05_LNB_13V GPIO17 |
175 | #define DM05_LNB_18V 0x00030000 | 187 | #define DM05_LNB_18V (GPIO17 | GPIO16) |
188 | |||
189 | /* GPIO's for LNB power control for unbranded with I2C on GPIO */ | ||
190 | #define UNBR_LNB_MASK (GPIO17 | GPIO16) | ||
191 | #define UNBR_LNB_OFF 0 | ||
192 | #define UNBR_LNB_13V GPIO17 | ||
193 | #define UNBR_LNB_18V (GPIO17 | GPIO16) | ||
176 | 194 | ||
177 | static unsigned int card[] = {[0 ... 3] = UNSET }; | 195 | static unsigned int card[] = {[0 ... 3] = UNSET }; |
178 | module_param_array(card, int, NULL, 0444); | 196 | module_param_array(card, int, NULL, 0444); |
@@ -187,7 +205,11 @@ static unsigned int dm1105_devcount; | |||
187 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 205 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
188 | 206 | ||
189 | struct dm1105_board { | 207 | struct dm1105_board { |
190 | char *name; | 208 | char *name; |
209 | struct { | ||
210 | u32 mask, off, v13, v18; | ||
211 | } lnb; | ||
212 | u32 gpio_scl, gpio_sda; | ||
191 | }; | 213 | }; |
192 | 214 | ||
193 | struct dm1105_subid { | 215 | struct dm1105_subid { |
@@ -199,15 +221,50 @@ struct dm1105_subid { | |||
199 | static const struct dm1105_board dm1105_boards[] = { | 221 | static const struct dm1105_board dm1105_boards[] = { |
200 | [DM1105_BOARD_UNKNOWN] = { | 222 | [DM1105_BOARD_UNKNOWN] = { |
201 | .name = "UNKNOWN/GENERIC", | 223 | .name = "UNKNOWN/GENERIC", |
224 | .lnb = { | ||
225 | .mask = DM1105_LNB_MASK, | ||
226 | .off = DM1105_LNB_OFF, | ||
227 | .v13 = DM1105_LNB_13V, | ||
228 | .v18 = DM1105_LNB_18V, | ||
229 | }, | ||
202 | }, | 230 | }, |
203 | [DM1105_BOARD_DVBWORLD_2002] = { | 231 | [DM1105_BOARD_DVBWORLD_2002] = { |
204 | .name = "DVBWorld PCI 2002", | 232 | .name = "DVBWorld PCI 2002", |
233 | .lnb = { | ||
234 | .mask = DM1105_LNB_MASK, | ||
235 | .off = DM1105_LNB_OFF, | ||
236 | .v13 = DM1105_LNB_13V, | ||
237 | .v18 = DM1105_LNB_18V, | ||
238 | }, | ||
205 | }, | 239 | }, |
206 | [DM1105_BOARD_DVBWORLD_2004] = { | 240 | [DM1105_BOARD_DVBWORLD_2004] = { |
207 | .name = "DVBWorld PCI 2004", | 241 | .name = "DVBWorld PCI 2004", |
242 | .lnb = { | ||
243 | .mask = DM1105_LNB_MASK, | ||
244 | .off = DM1105_LNB_OFF, | ||
245 | .v13 = DM1105_LNB_13V, | ||
246 | .v18 = DM1105_LNB_18V, | ||
247 | }, | ||
208 | }, | 248 | }, |
209 | [DM1105_BOARD_AXESS_DM05] = { | 249 | [DM1105_BOARD_AXESS_DM05] = { |
210 | .name = "Axess/EasyTv DM05", | 250 | .name = "Axess/EasyTv DM05", |
251 | .lnb = { | ||
252 | .mask = DM05_LNB_MASK, | ||
253 | .off = DM05_LNB_OFF, | ||
254 | .v13 = DM05_LNB_13V, | ||
255 | .v18 = DM05_LNB_18V, | ||
256 | }, | ||
257 | }, | ||
258 | [DM1105_BOARD_UNBRANDED_I2C_ON_GPIO] = { | ||
259 | .name = "Unbranded DM1105 with i2c on GPIOs", | ||
260 | .lnb = { | ||
261 | .mask = UNBR_LNB_MASK, | ||
262 | .off = UNBR_LNB_OFF, | ||
263 | .v13 = UNBR_LNB_13V, | ||
264 | .v18 = UNBR_LNB_18V, | ||
265 | }, | ||
266 | .gpio_scl = GPIO14, | ||
267 | .gpio_sda = GPIO13, | ||
211 | }, | 268 | }, |
212 | }; | 269 | }; |
213 | 270 | ||
@@ -293,6 +350,8 @@ struct dm1105_dev { | |||
293 | 350 | ||
294 | /* i2c */ | 351 | /* i2c */ |
295 | struct i2c_adapter i2c_adap; | 352 | struct i2c_adapter i2c_adap; |
353 | struct i2c_adapter i2c_bb_adap; | ||
354 | struct i2c_algo_bit_data i2c_bit; | ||
296 | 355 | ||
297 | /* irq */ | 356 | /* irq */ |
298 | struct work_struct work; | 357 | struct work_struct work; |
@@ -328,6 +387,103 @@ struct dm1105_dev { | |||
328 | #define dm_setl(reg, bit) dm_andorl((reg), (bit), (bit)) | 387 | #define dm_setl(reg, bit) dm_andorl((reg), (bit), (bit)) |
329 | #define dm_clearl(reg, bit) dm_andorl((reg), (bit), 0) | 388 | #define dm_clearl(reg, bit) dm_andorl((reg), (bit), 0) |
330 | 389 | ||
390 | /* The chip has 18 GPIOs. In HOST mode GPIO's used as 15 bit address lines, | ||
391 | so we can use only 3 GPIO's from GPIO15 to GPIO17. | ||
392 | Here I don't check whether HOST is enebled as it is not implemented yet. | ||
393 | */ | ||
394 | static void dm1105_gpio_set(struct dm1105_dev *dev, u32 mask) | ||
395 | { | ||
396 | if (mask & 0xfffc0000) | ||
397 | printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); | ||
398 | |||
399 | if (mask & 0x0003ffff) | ||
400 | dm_setl(DM1105_GPIOVAL, mask & 0x0003ffff); | ||
401 | |||
402 | } | ||
403 | |||
404 | static void dm1105_gpio_clear(struct dm1105_dev *dev, u32 mask) | ||
405 | { | ||
406 | if (mask & 0xfffc0000) | ||
407 | printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); | ||
408 | |||
409 | if (mask & 0x0003ffff) | ||
410 | dm_clearl(DM1105_GPIOVAL, mask & 0x0003ffff); | ||
411 | |||
412 | } | ||
413 | |||
414 | static void dm1105_gpio_andor(struct dm1105_dev *dev, u32 mask, u32 val) | ||
415 | { | ||
416 | if (mask & 0xfffc0000) | ||
417 | printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); | ||
418 | |||
419 | if (mask & 0x0003ffff) | ||
420 | dm_andorl(DM1105_GPIOVAL, mask & 0x0003ffff, val); | ||
421 | |||
422 | } | ||
423 | |||
424 | static u32 dm1105_gpio_get(struct dm1105_dev *dev, u32 mask) | ||
425 | { | ||
426 | if (mask & 0xfffc0000) | ||
427 | printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); | ||
428 | |||
429 | if (mask & 0x0003ffff) | ||
430 | return dm_readl(DM1105_GPIOVAL) & mask & 0x0003ffff; | ||
431 | |||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static void dm1105_gpio_enable(struct dm1105_dev *dev, u32 mask, int asoutput) | ||
436 | { | ||
437 | if (mask & 0xfffc0000) | ||
438 | printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); | ||
439 | |||
440 | if ((mask & 0x0003ffff) && asoutput) | ||
441 | dm_clearl(DM1105_GPIOCTR, mask & 0x0003ffff); | ||
442 | else if ((mask & 0x0003ffff) && !asoutput) | ||
443 | dm_setl(DM1105_GPIOCTR, mask & 0x0003ffff); | ||
444 | |||
445 | } | ||
446 | |||
447 | static void dm1105_setline(struct dm1105_dev *dev, u32 line, int state) | ||
448 | { | ||
449 | if (state) | ||
450 | dm1105_gpio_enable(dev, line, 0); | ||
451 | else { | ||
452 | dm1105_gpio_enable(dev, line, 1); | ||
453 | dm1105_gpio_clear(dev, line); | ||
454 | } | ||
455 | } | ||
456 | |||
457 | static void dm1105_setsda(void *data, int state) | ||
458 | { | ||
459 | struct dm1105_dev *dev = data; | ||
460 | |||
461 | dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_sda, state); | ||
462 | } | ||
463 | |||
464 | static void dm1105_setscl(void *data, int state) | ||
465 | { | ||
466 | struct dm1105_dev *dev = data; | ||
467 | |||
468 | dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_scl, state); | ||
469 | } | ||
470 | |||
471 | static int dm1105_getsda(void *data) | ||
472 | { | ||
473 | struct dm1105_dev *dev = data; | ||
474 | |||
475 | return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_sda) | ||
476 | ? 1 : 0; | ||
477 | } | ||
478 | |||
479 | static int dm1105_getscl(void *data) | ||
480 | { | ||
481 | struct dm1105_dev *dev = data; | ||
482 | |||
483 | return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_scl) | ||
484 | ? 1 : 0; | ||
485 | } | ||
486 | |||
331 | static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, | 487 | static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, |
332 | struct i2c_msg *msgs, int num) | 488 | struct i2c_msg *msgs, int num) |
333 | { | 489 | { |
@@ -436,31 +592,20 @@ static inline struct dm1105_dev *frontend_to_dm1105_dev(struct dvb_frontend *fe) | |||
436 | static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | 592 | static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) |
437 | { | 593 | { |
438 | struct dm1105_dev *dev = frontend_to_dm1105_dev(fe); | 594 | struct dm1105_dev *dev = frontend_to_dm1105_dev(fe); |
439 | u32 lnb_mask, lnb_13v, lnb_18v, lnb_off; | ||
440 | 595 | ||
441 | switch (dev->boardnr) { | 596 | dm1105_gpio_enable(dev, dm1105_boards[dev->boardnr].lnb.mask, 1); |
442 | case DM1105_BOARD_AXESS_DM05: | ||
443 | lnb_mask = DM05_LNB_MASK; | ||
444 | lnb_off = DM05_LNB_OFF; | ||
445 | lnb_13v = DM05_LNB_13V; | ||
446 | lnb_18v = DM05_LNB_18V; | ||
447 | break; | ||
448 | case DM1105_BOARD_DVBWORLD_2002: | ||
449 | case DM1105_BOARD_DVBWORLD_2004: | ||
450 | default: | ||
451 | lnb_mask = DM1105_LNB_MASK; | ||
452 | lnb_off = DM1105_LNB_OFF; | ||
453 | lnb_13v = DM1105_LNB_13V; | ||
454 | lnb_18v = DM1105_LNB_18V; | ||
455 | } | ||
456 | |||
457 | dm_writel(DM1105_GPIOCTR, lnb_mask); | ||
458 | if (voltage == SEC_VOLTAGE_18) | 597 | if (voltage == SEC_VOLTAGE_18) |
459 | dm_writel(DM1105_GPIOVAL, lnb_18v); | 598 | dm1105_gpio_andor(dev, |
599 | dm1105_boards[dev->boardnr].lnb.mask, | ||
600 | dm1105_boards[dev->boardnr].lnb.v18); | ||
460 | else if (voltage == SEC_VOLTAGE_13) | 601 | else if (voltage == SEC_VOLTAGE_13) |
461 | dm_writel(DM1105_GPIOVAL, lnb_13v); | 602 | dm1105_gpio_andor(dev, |
603 | dm1105_boards[dev->boardnr].lnb.mask, | ||
604 | dm1105_boards[dev->boardnr].lnb.v13); | ||
462 | else | 605 | else |
463 | dm_writel(DM1105_GPIOVAL, lnb_off); | 606 | dm1105_gpio_andor(dev, |
607 | dm1105_boards[dev->boardnr].lnb.mask, | ||
608 | dm1105_boards[dev->boardnr].lnb.off); | ||
464 | 609 | ||
465 | return 0; | 610 | return 0; |
466 | } | 611 | } |
@@ -708,6 +853,38 @@ static int __devinit frontend_init(struct dm1105_dev *dev) | |||
708 | int ret; | 853 | int ret; |
709 | 854 | ||
710 | switch (dev->boardnr) { | 855 | switch (dev->boardnr) { |
856 | case DM1105_BOARD_UNBRANDED_I2C_ON_GPIO: | ||
857 | dm1105_gpio_enable(dev, GPIO15, 1); | ||
858 | dm1105_gpio_clear(dev, GPIO15); | ||
859 | msleep(100); | ||
860 | dm1105_gpio_set(dev, GPIO15); | ||
861 | msleep(200); | ||
862 | dev->fe = dvb_attach( | ||
863 | stv0299_attach, &sharp_z0194a_config, | ||
864 | &dev->i2c_bb_adap); | ||
865 | if (dev->fe) { | ||
866 | dev->fe->ops.set_voltage = dm1105_set_voltage; | ||
867 | dvb_attach(dvb_pll_attach, dev->fe, 0x60, | ||
868 | &dev->i2c_bb_adap, DVB_PLL_OPERA1); | ||
869 | break; | ||
870 | } | ||
871 | |||
872 | dev->fe = dvb_attach( | ||
873 | stv0288_attach, &earda_config, | ||
874 | &dev->i2c_bb_adap); | ||
875 | if (dev->fe) { | ||
876 | dev->fe->ops.set_voltage = dm1105_set_voltage; | ||
877 | dvb_attach(stb6000_attach, dev->fe, 0x61, | ||
878 | &dev->i2c_bb_adap); | ||
879 | break; | ||
880 | } | ||
881 | |||
882 | dev->fe = dvb_attach( | ||
883 | si21xx_attach, &serit_config, | ||
884 | &dev->i2c_bb_adap); | ||
885 | if (dev->fe) | ||
886 | dev->fe->ops.set_voltage = dm1105_set_voltage; | ||
887 | break; | ||
711 | case DM1105_BOARD_DVBWORLD_2004: | 888 | case DM1105_BOARD_DVBWORLD_2004: |
712 | dev->fe = dvb_attach( | 889 | dev->fe = dvb_attach( |
713 | cx24116_attach, &serit_sp2633_config, | 890 | cx24116_attach, &serit_sp2633_config, |
@@ -870,11 +1047,32 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, | |||
870 | if (ret < 0) | 1047 | if (ret < 0) |
871 | goto err_dm1105_hw_exit; | 1048 | goto err_dm1105_hw_exit; |
872 | 1049 | ||
1050 | i2c_set_adapdata(&dev->i2c_bb_adap, dev); | ||
1051 | strcpy(dev->i2c_bb_adap.name, DM1105_I2C_GPIO_NAME); | ||
1052 | dev->i2c_bb_adap.owner = THIS_MODULE; | ||
1053 | dev->i2c_bb_adap.dev.parent = &pdev->dev; | ||
1054 | dev->i2c_bb_adap.algo_data = &dev->i2c_bit; | ||
1055 | dev->i2c_bit.data = dev; | ||
1056 | dev->i2c_bit.setsda = dm1105_setsda; | ||
1057 | dev->i2c_bit.setscl = dm1105_setscl; | ||
1058 | dev->i2c_bit.getsda = dm1105_getsda; | ||
1059 | dev->i2c_bit.getscl = dm1105_getscl; | ||
1060 | dev->i2c_bit.udelay = 10; | ||
1061 | dev->i2c_bit.timeout = 10; | ||
1062 | |||
1063 | /* Raise SCL and SDA */ | ||
1064 | dm1105_setsda(dev, 1); | ||
1065 | dm1105_setscl(dev, 1); | ||
1066 | |||
1067 | ret = i2c_bit_add_bus(&dev->i2c_bb_adap); | ||
1068 | if (ret < 0) | ||
1069 | goto err_i2c_del_adapter; | ||
1070 | |||
873 | /* dvb */ | 1071 | /* dvb */ |
874 | ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME, | 1072 | ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME, |
875 | THIS_MODULE, &pdev->dev, adapter_nr); | 1073 | THIS_MODULE, &pdev->dev, adapter_nr); |
876 | if (ret < 0) | 1074 | if (ret < 0) |
877 | goto err_i2c_del_adapter; | 1075 | goto err_i2c_del_adapters; |
878 | 1076 | ||
879 | dvb_adapter = &dev->dvb_adapter; | 1077 | dvb_adapter = &dev->dvb_adapter; |
880 | 1078 | ||
@@ -952,6 +1150,8 @@ err_dvb_dmx_release: | |||
952 | dvb_dmx_release(dvbdemux); | 1150 | dvb_dmx_release(dvbdemux); |
953 | err_dvb_unregister_adapter: | 1151 | err_dvb_unregister_adapter: |
954 | dvb_unregister_adapter(dvb_adapter); | 1152 | dvb_unregister_adapter(dvb_adapter); |
1153 | err_i2c_del_adapters: | ||
1154 | i2c_del_adapter(&dev->i2c_bb_adap); | ||
955 | err_i2c_del_adapter: | 1155 | err_i2c_del_adapter: |
956 | i2c_del_adapter(&dev->i2c_adap); | 1156 | i2c_del_adapter(&dev->i2c_adap); |
957 | err_dm1105_hw_exit: | 1157 | err_dm1105_hw_exit: |
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index f36f471deae2..37b146961ae2 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c | |||
@@ -207,17 +207,6 @@ static int lme2510_stream_restart(struct dvb_usb_device *d) | |||
207 | rbuff, sizeof(rbuff)); | 207 | rbuff, sizeof(rbuff)); |
208 | return ret; | 208 | return ret; |
209 | } | 209 | } |
210 | static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u32 keypress) | ||
211 | { | ||
212 | struct dvb_usb_device *d = adap->dev; | ||
213 | |||
214 | deb_info(1, "INT Key Keypress =%04x", keypress); | ||
215 | |||
216 | if (keypress > 0) | ||
217 | rc_keydown(d->rc_dev, keypress, 0); | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | 210 | ||
222 | static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out) | 211 | static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out) |
223 | { | 212 | { |
@@ -256,6 +245,7 @@ static void lme2510_int_response(struct urb *lme_urb) | |||
256 | struct lme2510_state *st = adap->dev->priv; | 245 | struct lme2510_state *st = adap->dev->priv; |
257 | static u8 *ibuf, *rbuf; | 246 | static u8 *ibuf, *rbuf; |
258 | int i = 0, offset; | 247 | int i = 0, offset; |
248 | u32 key; | ||
259 | 249 | ||
260 | switch (lme_urb->status) { | 250 | switch (lme_urb->status) { |
261 | case 0: | 251 | case 0: |
@@ -282,10 +272,16 @@ static void lme2510_int_response(struct urb *lme_urb) | |||
282 | 272 | ||
283 | switch (ibuf[0]) { | 273 | switch (ibuf[0]) { |
284 | case 0xaa: | 274 | case 0xaa: |
285 | debug_data_snipet(1, "INT Remote data snipet in", ibuf); | 275 | debug_data_snipet(1, "INT Remote data snipet", ibuf); |
286 | lme2510_remote_keypress(adap, | 276 | if ((ibuf[4] + ibuf[5]) == 0xff) { |
287 | (u32)(ibuf[2] << 24) + (ibuf[3] << 16) + | 277 | key = ibuf[5]; |
288 | (ibuf[4] << 8) + ibuf[5]); | 278 | key += (ibuf[3] > 0) |
279 | ? (ibuf[3] ^ 0xff) << 8 : 0; | ||
280 | key += (ibuf[2] ^ 0xff) << 16; | ||
281 | deb_info(1, "INT Key =%08x", key); | ||
282 | if (adap->dev->rc_dev != NULL) | ||
283 | rc_keydown(adap->dev->rc_dev, key, 0); | ||
284 | } | ||
289 | break; | 285 | break; |
290 | case 0xbb: | 286 | case 0xbb: |
291 | switch (st->tuner_config) { | 287 | switch (st->tuner_config) { |
@@ -691,45 +687,6 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
691 | return (ret < 0) ? -ENODEV : 0; | 687 | return (ret < 0) ? -ENODEV : 0; |
692 | } | 688 | } |
693 | 689 | ||
694 | static int lme2510_int_service(struct dvb_usb_adapter *adap) | ||
695 | { | ||
696 | struct dvb_usb_device *d = adap->dev; | ||
697 | struct rc_dev *rc; | ||
698 | int ret; | ||
699 | |||
700 | info("STA Configuring Remote"); | ||
701 | |||
702 | rc = rc_allocate_device(); | ||
703 | if (!rc) | ||
704 | return -ENOMEM; | ||
705 | |||
706 | usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); | ||
707 | strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); | ||
708 | |||
709 | rc->input_name = "LME2510 Remote Control"; | ||
710 | rc->input_phys = d->rc_phys; | ||
711 | rc->map_name = RC_MAP_LME2510; | ||
712 | rc->driver_name = "LME 2510"; | ||
713 | usb_to_input_id(d->udev, &rc->input_id); | ||
714 | |||
715 | ret = rc_register_device(rc); | ||
716 | if (ret) { | ||
717 | rc_free_device(rc); | ||
718 | return ret; | ||
719 | } | ||
720 | d->rc_dev = rc; | ||
721 | |||
722 | /* Start the Interrupt */ | ||
723 | ret = lme2510_int_read(adap); | ||
724 | if (ret < 0) { | ||
725 | rc_unregister_device(rc); | ||
726 | info("INT Unable to start Interrupt Service"); | ||
727 | return -ENODEV; | ||
728 | } | ||
729 | |||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | static u8 check_sum(u8 *p, u8 len) | 690 | static u8 check_sum(u8 *p, u8 len) |
734 | { | 691 | { |
735 | u8 sum = 0; | 692 | u8 sum = 0; |
@@ -831,7 +788,7 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) | |||
831 | 788 | ||
832 | cold_fw = !cold; | 789 | cold_fw = !cold; |
833 | 790 | ||
834 | if (udev->descriptor.idProduct == 0x1122) { | 791 | if (le16_to_cpu(udev->descriptor.idProduct) == 0x1122) { |
835 | switch (dvb_usb_lme2510_firmware) { | 792 | switch (dvb_usb_lme2510_firmware) { |
836 | default: | 793 | default: |
837 | dvb_usb_lme2510_firmware = TUNER_S0194; | 794 | dvb_usb_lme2510_firmware = TUNER_S0194; |
@@ -1053,8 +1010,11 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) | |||
1053 | 1010 | ||
1054 | 1011 | ||
1055 | end: if (ret) { | 1012 | end: if (ret) { |
1056 | kfree(adap->fe); | 1013 | if (adap->fe) { |
1057 | adap->fe = NULL; | 1014 | dvb_frontend_detach(adap->fe); |
1015 | adap->fe = NULL; | ||
1016 | } | ||
1017 | adap->dev->props.rc.core.rc_codes = NULL; | ||
1058 | return -ENODEV; | 1018 | return -ENODEV; |
1059 | } | 1019 | } |
1060 | 1020 | ||
@@ -1097,8 +1057,12 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) | |||
1097 | return -ENODEV; | 1057 | return -ENODEV; |
1098 | } | 1058 | } |
1099 | 1059 | ||
1100 | /* Start the Interrupt & Remote*/ | 1060 | /* Start the Interrupt*/ |
1101 | ret = lme2510_int_service(adap); | 1061 | ret = lme2510_int_read(adap); |
1062 | if (ret < 0) { | ||
1063 | info("INT Unable to start Interrupt Service"); | ||
1064 | return -ENODEV; | ||
1065 | } | ||
1102 | 1066 | ||
1103 | return ret; | 1067 | return ret; |
1104 | } | 1068 | } |
@@ -1204,6 +1168,12 @@ static struct dvb_usb_device_properties lme2510_properties = { | |||
1204 | } | 1168 | } |
1205 | } | 1169 | } |
1206 | }, | 1170 | }, |
1171 | .rc.core = { | ||
1172 | .protocol = RC_TYPE_NEC, | ||
1173 | .module_name = "LME2510 Remote Control", | ||
1174 | .allowed_protos = RC_TYPE_NEC, | ||
1175 | .rc_codes = RC_MAP_LME2510, | ||
1176 | }, | ||
1207 | .power_ctrl = lme2510_powerup, | 1177 | .power_ctrl = lme2510_powerup, |
1208 | .identify_state = lme2510_identify_state, | 1178 | .identify_state = lme2510_identify_state, |
1209 | .i2c_algo = &lme2510_i2c_algo, | 1179 | .i2c_algo = &lme2510_i2c_algo, |
@@ -1246,6 +1216,12 @@ static struct dvb_usb_device_properties lme2510c_properties = { | |||
1246 | } | 1216 | } |
1247 | } | 1217 | } |
1248 | }, | 1218 | }, |
1219 | .rc.core = { | ||
1220 | .protocol = RC_TYPE_NEC, | ||
1221 | .module_name = "LME2510 Remote Control", | ||
1222 | .allowed_protos = RC_TYPE_NEC, | ||
1223 | .rc_codes = RC_MAP_LME2510, | ||
1224 | }, | ||
1249 | .power_ctrl = lme2510_powerup, | 1225 | .power_ctrl = lme2510_powerup, |
1250 | .identify_state = lme2510_identify_state, | 1226 | .identify_state = lme2510_identify_state, |
1251 | .i2c_algo = &lme2510_i2c_algo, | 1227 | .i2c_algo = &lme2510_i2c_algo, |
@@ -1269,19 +1245,21 @@ static void *lme2510_exit_int(struct dvb_usb_device *d) | |||
1269 | adap->feedcount = 0; | 1245 | adap->feedcount = 0; |
1270 | } | 1246 | } |
1271 | 1247 | ||
1272 | if (st->lme_urb != NULL) { | 1248 | if (st->usb_buffer != NULL) { |
1273 | st->i2c_talk_onoff = 1; | 1249 | st->i2c_talk_onoff = 1; |
1274 | st->signal_lock = 0; | 1250 | st->signal_lock = 0; |
1275 | st->signal_level = 0; | 1251 | st->signal_level = 0; |
1276 | st->signal_sn = 0; | 1252 | st->signal_sn = 0; |
1277 | buffer = st->usb_buffer; | 1253 | buffer = st->usb_buffer; |
1254 | } | ||
1255 | |||
1256 | if (st->lme_urb != NULL) { | ||
1278 | usb_kill_urb(st->lme_urb); | 1257 | usb_kill_urb(st->lme_urb); |
1279 | usb_free_coherent(d->udev, 5000, st->buffer, | 1258 | usb_free_coherent(d->udev, 5000, st->buffer, |
1280 | st->lme_urb->transfer_dma); | 1259 | st->lme_urb->transfer_dma); |
1281 | info("Interrupt Service Stopped"); | 1260 | info("Interrupt Service Stopped"); |
1282 | rc_unregister_device(d->rc_dev); | ||
1283 | info("Remote Stopped"); | ||
1284 | } | 1261 | } |
1262 | |||
1285 | return buffer; | 1263 | return buffer; |
1286 | } | 1264 | } |
1287 | 1265 | ||
@@ -1293,7 +1271,8 @@ static void lme2510_exit(struct usb_interface *intf) | |||
1293 | if (d != NULL) { | 1271 | if (d != NULL) { |
1294 | usb_buffer = lme2510_exit_int(d); | 1272 | usb_buffer = lme2510_exit_int(d); |
1295 | dvb_usb_device_exit(intf); | 1273 | dvb_usb_device_exit(intf); |
1296 | kfree(usb_buffer); | 1274 | if (usb_buffer != NULL) |
1275 | kfree(usb_buffer); | ||
1297 | } | 1276 | } |
1298 | } | 1277 | } |
1299 | 1278 | ||
@@ -1327,5 +1306,5 @@ module_exit(lme2510_module_exit); | |||
1327 | 1306 | ||
1328 | MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); | 1307 | MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); |
1329 | MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); | 1308 | MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); |
1330 | MODULE_VERSION("1.86"); | 1309 | MODULE_VERSION("1.88"); |
1331 | MODULE_LICENSE("GPL"); | 1310 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c index 2da55ec20392..d70eee00f33a 100644 --- a/drivers/media/dvb/frontends/stb0899_algo.c +++ b/drivers/media/dvb/frontends/stb0899_algo.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include "stb0899_priv.h" | 23 | #include "stb0899_priv.h" |
24 | #include "stb0899_reg.h" | 24 | #include "stb0899_reg.h" |
25 | 25 | ||
26 | inline u32 stb0899_do_div(u64 n, u32 d) | 26 | static inline u32 stb0899_do_div(u64 n, u32 d) |
27 | { | 27 | { |
28 | /* wrap do_div() for ease of use */ | 28 | /* wrap do_div() for ease of use */ |
29 | 29 | ||
diff --git a/drivers/media/dvb/frontends/tda8261.c b/drivers/media/dvb/frontends/tda8261.c index 1742056a34e8..53c7d8f1df28 100644 --- a/drivers/media/dvb/frontends/tda8261.c +++ b/drivers/media/dvb/frontends/tda8261.c | |||
@@ -224,7 +224,6 @@ exit: | |||
224 | } | 224 | } |
225 | 225 | ||
226 | EXPORT_SYMBOL(tda8261_attach); | 226 | EXPORT_SYMBOL(tda8261_attach); |
227 | MODULE_PARM_DESC(verbose, "Set verbosity level"); | ||
228 | 227 | ||
229 | MODULE_AUTHOR("Manu Abraham"); | 228 | MODULE_AUTHOR("Manu Abraham"); |
230 | MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner"); | 229 | MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner"); |
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 5c2a9058c09f..e83e84003025 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c | |||
@@ -412,8 +412,7 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d | |||
412 | goto err_out_free_region; | 412 | goto err_out_free_region; |
413 | } | 413 | } |
414 | 414 | ||
415 | v4l2_info(v4l2_dev, "version " DRIVER_VERSION | 415 | v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n"); |
416 | " time " __TIME__ " " __DATE__ "\n"); | ||
417 | 416 | ||
418 | v4l2_info(v4l2_dev, "found Guillemot MAXI Radio device (io = 0x%x)\n", | 417 | v4l2_info(v4l2_dev, "found Guillemot MAXI Radio device (io = 0x%x)\n", |
419 | dev->io); | 418 | dev->io); |
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index 46cacf845049..459f7272d326 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c | |||
@@ -1382,7 +1382,7 @@ static int wl1273_fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | |||
1382 | 1382 | ||
1383 | switch (ctrl->id) { | 1383 | switch (ctrl->id) { |
1384 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: | 1384 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: |
1385 | ctrl->val = wl1273_fm_get_tx_ctune(radio); | 1385 | ctrl->cur.val = wl1273_fm_get_tx_ctune(radio); |
1386 | break; | 1386 | break; |
1387 | 1387 | ||
1388 | default: | 1388 | default: |
diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c index d50e5ac75ab6..87010724f914 100644 --- a/drivers/media/radio/wl128x/fmdrv_v4l2.c +++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c | |||
@@ -191,7 +191,7 @@ static int fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | |||
191 | 191 | ||
192 | switch (ctrl->id) { | 192 | switch (ctrl->id) { |
193 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: | 193 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: |
194 | ctrl->val = fm_tx_get_tune_cap_val(fmdev); | 194 | ctrl->cur.val = fm_tx_get_tune_cap_val(fmdev); |
195 | break; | 195 | break; |
196 | default: | 196 | default: |
197 | fmwarn("%s: Unknown IOCTL: %d\n", __func__, ctrl->id); | 197 | fmwarn("%s: Unknown IOCTL: %d\n", __func__, ctrl->id); |
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 154c337f00fd..7d4bbc226d06 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig | |||
@@ -148,6 +148,18 @@ config IR_ITE_CIR | |||
148 | To compile this driver as a module, choose M here: the | 148 | To compile this driver as a module, choose M here: the |
149 | module will be called ite-cir. | 149 | module will be called ite-cir. |
150 | 150 | ||
151 | config IR_FINTEK | ||
152 | tristate "Fintek Consumer Infrared Transceiver" | ||
153 | depends on PNP | ||
154 | depends on RC_CORE | ||
155 | ---help--- | ||
156 | Say Y here to enable support for integrated infrared receiver | ||
157 | /transciever made by Fintek. This chip is found on assorted | ||
158 | Jetway motherboards (and of course, possibly others). | ||
159 | |||
160 | To compile this driver as a module, choose M here: the | ||
161 | module will be called fintek-cir. | ||
162 | |||
151 | config IR_NUVOTON | 163 | config IR_NUVOTON |
152 | tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" | 164 | tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" |
153 | depends on PNP | 165 | depends on PNP |
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 1f90a219a162..52830e5f4eaa 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o | |||
16 | obj-$(CONFIG_IR_IMON) += imon.o | 16 | obj-$(CONFIG_IR_IMON) += imon.o |
17 | obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o | 17 | obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o |
18 | obj-$(CONFIG_IR_MCEUSB) += mceusb.o | 18 | obj-$(CONFIG_IR_MCEUSB) += mceusb.o |
19 | obj-$(CONFIG_IR_FINTEK) += fintek-cir.o | ||
19 | obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o | 20 | obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o |
20 | obj-$(CONFIG_IR_ENE) += ene_ir.o | 21 | obj-$(CONFIG_IR_ENE) += ene_ir.o |
21 | obj-$(CONFIG_IR_REDRAT3) += redrat3.o | 22 | obj-$(CONFIG_IR_REDRAT3) += redrat3.o |
diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c new file mode 100644 index 000000000000..8fa539dde1b4 --- /dev/null +++ b/drivers/media/rc/fintek-cir.c | |||
@@ -0,0 +1,684 @@ | |||
1 | /* | ||
2 | * Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR | ||
3 | * | ||
4 | * Copyright (C) 2011 Jarod Wilson <jarod@redhat.com> | ||
5 | * | ||
6 | * Special thanks to Fintek for providing hardware and spec sheets. | ||
7 | * This driver is based upon the nuvoton, ite and ene drivers for | ||
8 | * similar hardware. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License as | ||
12 | * published by the Free Software Foundation; either version 2 of the | ||
13 | * License, or (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
23 | * USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/pnp.h> | ||
29 | #include <linux/io.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <media/rc-core.h> | ||
34 | #include <linux/pci_ids.h> | ||
35 | |||
36 | #include "fintek-cir.h" | ||
37 | |||
38 | /* write val to config reg */ | ||
39 | static inline void fintek_cr_write(struct fintek_dev *fintek, u8 val, u8 reg) | ||
40 | { | ||
41 | fit_dbg("%s: reg 0x%02x, val 0x%02x (ip/dp: %02x/%02x)", | ||
42 | __func__, reg, val, fintek->cr_ip, fintek->cr_dp); | ||
43 | outb(reg, fintek->cr_ip); | ||
44 | outb(val, fintek->cr_dp); | ||
45 | } | ||
46 | |||
47 | /* read val from config reg */ | ||
48 | static inline u8 fintek_cr_read(struct fintek_dev *fintek, u8 reg) | ||
49 | { | ||
50 | u8 val; | ||
51 | |||
52 | outb(reg, fintek->cr_ip); | ||
53 | val = inb(fintek->cr_dp); | ||
54 | |||
55 | fit_dbg("%s: reg 0x%02x, val 0x%02x (ip/dp: %02x/%02x)", | ||
56 | __func__, reg, val, fintek->cr_ip, fintek->cr_dp); | ||
57 | return val; | ||
58 | } | ||
59 | |||
60 | /* update config register bit without changing other bits */ | ||
61 | static inline void fintek_set_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg) | ||
62 | { | ||
63 | u8 tmp = fintek_cr_read(fintek, reg) | val; | ||
64 | fintek_cr_write(fintek, tmp, reg); | ||
65 | } | ||
66 | |||
67 | /* clear config register bit without changing other bits */ | ||
68 | static inline void fintek_clear_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg) | ||
69 | { | ||
70 | u8 tmp = fintek_cr_read(fintek, reg) & ~val; | ||
71 | fintek_cr_write(fintek, tmp, reg); | ||
72 | } | ||
73 | |||
74 | /* enter config mode */ | ||
75 | static inline void fintek_config_mode_enable(struct fintek_dev *fintek) | ||
76 | { | ||
77 | /* Enabling Config Mode explicitly requires writing 2x */ | ||
78 | outb(CONFIG_REG_ENABLE, fintek->cr_ip); | ||
79 | outb(CONFIG_REG_ENABLE, fintek->cr_ip); | ||
80 | } | ||
81 | |||
82 | /* exit config mode */ | ||
83 | static inline void fintek_config_mode_disable(struct fintek_dev *fintek) | ||
84 | { | ||
85 | outb(CONFIG_REG_DISABLE, fintek->cr_ip); | ||
86 | } | ||
87 | |||
88 | /* | ||
89 | * When you want to address a specific logical device, write its logical | ||
90 | * device number to GCR_LOGICAL_DEV_NO | ||
91 | */ | ||
92 | static inline void fintek_select_logical_dev(struct fintek_dev *fintek, u8 ldev) | ||
93 | { | ||
94 | fintek_cr_write(fintek, ldev, GCR_LOGICAL_DEV_NO); | ||
95 | } | ||
96 | |||
97 | /* write val to cir config register */ | ||
98 | static inline void fintek_cir_reg_write(struct fintek_dev *fintek, u8 val, u8 offset) | ||
99 | { | ||
100 | outb(val, fintek->cir_addr + offset); | ||
101 | } | ||
102 | |||
103 | /* read val from cir config register */ | ||
104 | static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset) | ||
105 | { | ||
106 | u8 val; | ||
107 | |||
108 | val = inb(fintek->cir_addr + offset); | ||
109 | |||
110 | return val; | ||
111 | } | ||
112 | |||
113 | #define pr_reg(text, ...) \ | ||
114 | printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__) | ||
115 | |||
116 | /* dump current cir register contents */ | ||
117 | static void cir_dump_regs(struct fintek_dev *fintek) | ||
118 | { | ||
119 | fintek_config_mode_enable(fintek); | ||
120 | fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); | ||
121 | |||
122 | pr_reg("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME); | ||
123 | pr_reg(" * CR CIR BASE ADDR: 0x%x\n", | ||
124 | (fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) | | ||
125 | fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO)); | ||
126 | pr_reg(" * CR CIR IRQ NUM: 0x%x\n", | ||
127 | fintek_cr_read(fintek, CIR_CR_IRQ_SEL)); | ||
128 | |||
129 | fintek_config_mode_disable(fintek); | ||
130 | |||
131 | pr_reg("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME); | ||
132 | pr_reg(" * STATUS: 0x%x\n", fintek_cir_reg_read(fintek, CIR_STATUS)); | ||
133 | pr_reg(" * CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_CONTROL)); | ||
134 | pr_reg(" * RX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_RX_DATA)); | ||
135 | pr_reg(" * TX_CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_CONTROL)); | ||
136 | pr_reg(" * TX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_DATA)); | ||
137 | } | ||
138 | |||
139 | /* detect hardware features */ | ||
140 | static int fintek_hw_detect(struct fintek_dev *fintek) | ||
141 | { | ||
142 | unsigned long flags; | ||
143 | u8 chip_major, chip_minor; | ||
144 | u8 vendor_major, vendor_minor; | ||
145 | u8 portsel, ir_class; | ||
146 | u16 vendor; | ||
147 | int ret = 0; | ||
148 | |||
149 | fintek_config_mode_enable(fintek); | ||
150 | |||
151 | /* Check if we're using config port 0x4e or 0x2e */ | ||
152 | portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL); | ||
153 | if (portsel == 0xff) { | ||
154 | fit_pr(KERN_INFO, "first portsel read was bunk, trying alt"); | ||
155 | fintek_config_mode_disable(fintek); | ||
156 | fintek->cr_ip = CR_INDEX_PORT2; | ||
157 | fintek->cr_dp = CR_DATA_PORT2; | ||
158 | fintek_config_mode_enable(fintek); | ||
159 | portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL); | ||
160 | } | ||
161 | fit_dbg("portsel reg: 0x%02x", portsel); | ||
162 | |||
163 | ir_class = fintek_cir_reg_read(fintek, CIR_CR_CLASS); | ||
164 | fit_dbg("ir_class reg: 0x%02x", ir_class); | ||
165 | |||
166 | switch (ir_class) { | ||
167 | case CLASS_RX_2TX: | ||
168 | case CLASS_RX_1TX: | ||
169 | fintek->hw_tx_capable = true; | ||
170 | break; | ||
171 | case CLASS_RX_ONLY: | ||
172 | default: | ||
173 | fintek->hw_tx_capable = false; | ||
174 | break; | ||
175 | } | ||
176 | |||
177 | chip_major = fintek_cr_read(fintek, GCR_CHIP_ID_HI); | ||
178 | chip_minor = fintek_cr_read(fintek, GCR_CHIP_ID_LO); | ||
179 | |||
180 | vendor_major = fintek_cr_read(fintek, GCR_VENDOR_ID_HI); | ||
181 | vendor_minor = fintek_cr_read(fintek, GCR_VENDOR_ID_LO); | ||
182 | vendor = vendor_major << 8 | vendor_minor; | ||
183 | |||
184 | if (vendor != VENDOR_ID_FINTEK) | ||
185 | fit_pr(KERN_WARNING, "Unknown vendor ID: 0x%04x", vendor); | ||
186 | else | ||
187 | fit_dbg("Read Fintek vendor ID from chip"); | ||
188 | |||
189 | fintek_config_mode_disable(fintek); | ||
190 | |||
191 | spin_lock_irqsave(&fintek->fintek_lock, flags); | ||
192 | fintek->chip_major = chip_major; | ||
193 | fintek->chip_minor = chip_minor; | ||
194 | fintek->chip_vendor = vendor; | ||
195 | spin_unlock_irqrestore(&fintek->fintek_lock, flags); | ||
196 | |||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | static void fintek_cir_ldev_init(struct fintek_dev *fintek) | ||
201 | { | ||
202 | /* Select CIR logical device and enable */ | ||
203 | fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); | ||
204 | fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); | ||
205 | |||
206 | /* Write allocated CIR address and IRQ information to hardware */ | ||
207 | fintek_cr_write(fintek, fintek->cir_addr >> 8, CIR_CR_BASE_ADDR_HI); | ||
208 | fintek_cr_write(fintek, fintek->cir_addr & 0xff, CIR_CR_BASE_ADDR_LO); | ||
209 | |||
210 | fintek_cr_write(fintek, fintek->cir_irq, CIR_CR_IRQ_SEL); | ||
211 | |||
212 | fit_dbg("CIR initialized, base io address: 0x%lx, irq: %d (len: %d)", | ||
213 | fintek->cir_addr, fintek->cir_irq, fintek->cir_port_len); | ||
214 | } | ||
215 | |||
216 | /* enable CIR interrupts */ | ||
217 | static void fintek_enable_cir_irq(struct fintek_dev *fintek) | ||
218 | { | ||
219 | fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS); | ||
220 | } | ||
221 | |||
222 | static void fintek_cir_regs_init(struct fintek_dev *fintek) | ||
223 | { | ||
224 | /* clear any and all stray interrupts */ | ||
225 | fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); | ||
226 | |||
227 | /* and finally, enable interrupts */ | ||
228 | fintek_enable_cir_irq(fintek); | ||
229 | } | ||
230 | |||
231 | static void fintek_enable_wake(struct fintek_dev *fintek) | ||
232 | { | ||
233 | fintek_config_mode_enable(fintek); | ||
234 | fintek_select_logical_dev(fintek, LOGICAL_DEV_ACPI); | ||
235 | |||
236 | /* Allow CIR PME's to wake system */ | ||
237 | fintek_set_reg_bit(fintek, ACPI_WAKE_EN_CIR_BIT, LDEV_ACPI_WAKE_EN_REG); | ||
238 | /* Enable CIR PME's */ | ||
239 | fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_EN_REG); | ||
240 | /* Clear CIR PME status register */ | ||
241 | fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_CLR_REG); | ||
242 | /* Save state */ | ||
243 | fintek_set_reg_bit(fintek, ACPI_STATE_CIR_BIT, LDEV_ACPI_STATE_REG); | ||
244 | |||
245 | fintek_config_mode_disable(fintek); | ||
246 | } | ||
247 | |||
248 | static int fintek_cmdsize(u8 cmd, u8 subcmd) | ||
249 | { | ||
250 | int datasize = 0; | ||
251 | |||
252 | switch (cmd) { | ||
253 | case BUF_COMMAND_NULL: | ||
254 | if (subcmd == BUF_HW_CMD_HEADER) | ||
255 | datasize = 1; | ||
256 | break; | ||
257 | case BUF_HW_CMD_HEADER: | ||
258 | if (subcmd == BUF_CMD_G_REVISION) | ||
259 | datasize = 2; | ||
260 | break; | ||
261 | case BUF_COMMAND_HEADER: | ||
262 | switch (subcmd) { | ||
263 | case BUF_CMD_S_CARRIER: | ||
264 | case BUF_CMD_S_TIMEOUT: | ||
265 | case BUF_RSP_PULSE_COUNT: | ||
266 | datasize = 2; | ||
267 | break; | ||
268 | case BUF_CMD_SIG_END: | ||
269 | case BUF_CMD_S_TXMASK: | ||
270 | case BUF_CMD_S_RXSENSOR: | ||
271 | datasize = 1; | ||
272 | break; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | return datasize; | ||
277 | } | ||
278 | |||
279 | /* process ir data stored in driver buffer */ | ||
280 | static void fintek_process_rx_ir_data(struct fintek_dev *fintek) | ||
281 | { | ||
282 | DEFINE_IR_RAW_EVENT(rawir); | ||
283 | u8 sample; | ||
284 | int i; | ||
285 | |||
286 | for (i = 0; i < fintek->pkts; i++) { | ||
287 | sample = fintek->buf[i]; | ||
288 | switch (fintek->parser_state) { | ||
289 | case CMD_HEADER: | ||
290 | fintek->cmd = sample; | ||
291 | if ((fintek->cmd == BUF_COMMAND_HEADER) || | ||
292 | ((fintek->cmd & BUF_COMMAND_MASK) != | ||
293 | BUF_PULSE_BIT)) { | ||
294 | fintek->parser_state = SUBCMD; | ||
295 | continue; | ||
296 | } | ||
297 | fintek->rem = (fintek->cmd & BUF_LEN_MASK); | ||
298 | fit_dbg("%s: rem: 0x%02x", __func__, fintek->rem); | ||
299 | if (fintek->rem) | ||
300 | fintek->parser_state = PARSE_IRDATA; | ||
301 | else | ||
302 | ir_raw_event_reset(fintek->rdev); | ||
303 | break; | ||
304 | case SUBCMD: | ||
305 | fintek->rem = fintek_cmdsize(fintek->cmd, sample); | ||
306 | fintek->parser_state = CMD_DATA; | ||
307 | break; | ||
308 | case CMD_DATA: | ||
309 | fintek->rem--; | ||
310 | break; | ||
311 | case PARSE_IRDATA: | ||
312 | fintek->rem--; | ||
313 | init_ir_raw_event(&rawir); | ||
314 | rawir.pulse = ((sample & BUF_PULSE_BIT) != 0); | ||
315 | rawir.duration = US_TO_NS((sample & BUF_SAMPLE_MASK) | ||
316 | * CIR_SAMPLE_PERIOD); | ||
317 | |||
318 | fit_dbg("Storing %s with duration %d", | ||
319 | rawir.pulse ? "pulse" : "space", | ||
320 | rawir.duration); | ||
321 | ir_raw_event_store_with_filter(fintek->rdev, &rawir); | ||
322 | break; | ||
323 | } | ||
324 | |||
325 | if ((fintek->parser_state != CMD_HEADER) && !fintek->rem) | ||
326 | fintek->parser_state = CMD_HEADER; | ||
327 | } | ||
328 | |||
329 | fintek->pkts = 0; | ||
330 | |||
331 | fit_dbg("Calling ir_raw_event_handle"); | ||
332 | ir_raw_event_handle(fintek->rdev); | ||
333 | } | ||
334 | |||
335 | /* copy data from hardware rx register into driver buffer */ | ||
336 | static void fintek_get_rx_ir_data(struct fintek_dev *fintek, u8 rx_irqs) | ||
337 | { | ||
338 | unsigned long flags; | ||
339 | u8 sample, status; | ||
340 | |||
341 | spin_lock_irqsave(&fintek->fintek_lock, flags); | ||
342 | |||
343 | /* | ||
344 | * We must read data from CIR_RX_DATA until the hardware IR buffer | ||
345 | * is empty and clears the RX_TIMEOUT and/or RX_RECEIVE flags in | ||
346 | * the CIR_STATUS register | ||
347 | */ | ||
348 | do { | ||
349 | sample = fintek_cir_reg_read(fintek, CIR_RX_DATA); | ||
350 | fit_dbg("%s: sample: 0x%02x", __func__, sample); | ||
351 | |||
352 | fintek->buf[fintek->pkts] = sample; | ||
353 | fintek->pkts++; | ||
354 | |||
355 | status = fintek_cir_reg_read(fintek, CIR_STATUS); | ||
356 | if (!(status & CIR_STATUS_IRQ_EN)) | ||
357 | break; | ||
358 | } while (status & rx_irqs); | ||
359 | |||
360 | fintek_process_rx_ir_data(fintek); | ||
361 | |||
362 | spin_unlock_irqrestore(&fintek->fintek_lock, flags); | ||
363 | } | ||
364 | |||
365 | static void fintek_cir_log_irqs(u8 status) | ||
366 | { | ||
367 | fit_pr(KERN_INFO, "IRQ 0x%02x:%s%s%s%s%s", status, | ||
368 | status & CIR_STATUS_IRQ_EN ? " IRQEN" : "", | ||
369 | status & CIR_STATUS_TX_FINISH ? " TXF" : "", | ||
370 | status & CIR_STATUS_TX_UNDERRUN ? " TXU" : "", | ||
371 | status & CIR_STATUS_RX_TIMEOUT ? " RXTO" : "", | ||
372 | status & CIR_STATUS_RX_RECEIVE ? " RXOK" : ""); | ||
373 | } | ||
374 | |||
375 | /* interrupt service routine for incoming and outgoing CIR data */ | ||
376 | static irqreturn_t fintek_cir_isr(int irq, void *data) | ||
377 | { | ||
378 | struct fintek_dev *fintek = data; | ||
379 | u8 status, rx_irqs; | ||
380 | |||
381 | fit_dbg_verbose("%s firing", __func__); | ||
382 | |||
383 | fintek_config_mode_enable(fintek); | ||
384 | fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); | ||
385 | fintek_config_mode_disable(fintek); | ||
386 | |||
387 | /* | ||
388 | * Get IR Status register contents. Write 1 to ack/clear | ||
389 | * | ||
390 | * bit: reg name - description | ||
391 | * 3: TX_FINISH - TX is finished | ||
392 | * 2: TX_UNDERRUN - TX underrun | ||
393 | * 1: RX_TIMEOUT - RX data timeout | ||
394 | * 0: RX_RECEIVE - RX data received | ||
395 | */ | ||
396 | status = fintek_cir_reg_read(fintek, CIR_STATUS); | ||
397 | if (!(status & CIR_STATUS_IRQ_MASK) || status == 0xff) { | ||
398 | fit_dbg_verbose("%s exiting, IRSTS 0x%02x", __func__, status); | ||
399 | fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); | ||
400 | return IRQ_RETVAL(IRQ_NONE); | ||
401 | } | ||
402 | |||
403 | if (debug) | ||
404 | fintek_cir_log_irqs(status); | ||
405 | |||
406 | rx_irqs = status & (CIR_STATUS_RX_RECEIVE | CIR_STATUS_RX_TIMEOUT); | ||
407 | if (rx_irqs) | ||
408 | fintek_get_rx_ir_data(fintek, rx_irqs); | ||
409 | |||
410 | /* ack/clear all irq flags we've got */ | ||
411 | fintek_cir_reg_write(fintek, status, CIR_STATUS); | ||
412 | |||
413 | fit_dbg_verbose("%s done", __func__); | ||
414 | return IRQ_RETVAL(IRQ_HANDLED); | ||
415 | } | ||
416 | |||
417 | static void fintek_enable_cir(struct fintek_dev *fintek) | ||
418 | { | ||
419 | /* set IRQ enabled */ | ||
420 | fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS); | ||
421 | |||
422 | fintek_config_mode_enable(fintek); | ||
423 | |||
424 | /* enable the CIR logical device */ | ||
425 | fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); | ||
426 | fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); | ||
427 | |||
428 | fintek_config_mode_disable(fintek); | ||
429 | |||
430 | /* clear all pending interrupts */ | ||
431 | fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); | ||
432 | |||
433 | /* enable interrupts */ | ||
434 | fintek_enable_cir_irq(fintek); | ||
435 | } | ||
436 | |||
437 | static void fintek_disable_cir(struct fintek_dev *fintek) | ||
438 | { | ||
439 | fintek_config_mode_enable(fintek); | ||
440 | |||
441 | /* disable the CIR logical device */ | ||
442 | fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); | ||
443 | fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); | ||
444 | |||
445 | fintek_config_mode_disable(fintek); | ||
446 | } | ||
447 | |||
448 | static int fintek_open(struct rc_dev *dev) | ||
449 | { | ||
450 | struct fintek_dev *fintek = dev->priv; | ||
451 | unsigned long flags; | ||
452 | |||
453 | spin_lock_irqsave(&fintek->fintek_lock, flags); | ||
454 | fintek_enable_cir(fintek); | ||
455 | spin_unlock_irqrestore(&fintek->fintek_lock, flags); | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static void fintek_close(struct rc_dev *dev) | ||
461 | { | ||
462 | struct fintek_dev *fintek = dev->priv; | ||
463 | unsigned long flags; | ||
464 | |||
465 | spin_lock_irqsave(&fintek->fintek_lock, flags); | ||
466 | fintek_disable_cir(fintek); | ||
467 | spin_unlock_irqrestore(&fintek->fintek_lock, flags); | ||
468 | } | ||
469 | |||
470 | /* Allocate memory, probe hardware, and initialize everything */ | ||
471 | static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) | ||
472 | { | ||
473 | struct fintek_dev *fintek; | ||
474 | struct rc_dev *rdev; | ||
475 | int ret = -ENOMEM; | ||
476 | |||
477 | fintek = kzalloc(sizeof(struct fintek_dev), GFP_KERNEL); | ||
478 | if (!fintek) | ||
479 | return ret; | ||
480 | |||
481 | /* input device for IR remote (and tx) */ | ||
482 | rdev = rc_allocate_device(); | ||
483 | if (!rdev) | ||
484 | goto failure; | ||
485 | |||
486 | ret = -ENODEV; | ||
487 | /* validate pnp resources */ | ||
488 | if (!pnp_port_valid(pdev, 0)) { | ||
489 | dev_err(&pdev->dev, "IR PNP Port not valid!\n"); | ||
490 | goto failure; | ||
491 | } | ||
492 | |||
493 | if (!pnp_irq_valid(pdev, 0)) { | ||
494 | dev_err(&pdev->dev, "IR PNP IRQ not valid!\n"); | ||
495 | goto failure; | ||
496 | } | ||
497 | |||
498 | fintek->cir_addr = pnp_port_start(pdev, 0); | ||
499 | fintek->cir_irq = pnp_irq(pdev, 0); | ||
500 | fintek->cir_port_len = pnp_port_len(pdev, 0); | ||
501 | |||
502 | fintek->cr_ip = CR_INDEX_PORT; | ||
503 | fintek->cr_dp = CR_DATA_PORT; | ||
504 | |||
505 | spin_lock_init(&fintek->fintek_lock); | ||
506 | |||
507 | ret = -EBUSY; | ||
508 | /* now claim resources */ | ||
509 | if (!request_region(fintek->cir_addr, | ||
510 | fintek->cir_port_len, FINTEK_DRIVER_NAME)) | ||
511 | goto failure; | ||
512 | |||
513 | if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED, | ||
514 | FINTEK_DRIVER_NAME, (void *)fintek)) | ||
515 | goto failure; | ||
516 | |||
517 | pnp_set_drvdata(pdev, fintek); | ||
518 | fintek->pdev = pdev; | ||
519 | |||
520 | ret = fintek_hw_detect(fintek); | ||
521 | if (ret) | ||
522 | goto failure; | ||
523 | |||
524 | /* Initialize CIR & CIR Wake Logical Devices */ | ||
525 | fintek_config_mode_enable(fintek); | ||
526 | fintek_cir_ldev_init(fintek); | ||
527 | fintek_config_mode_disable(fintek); | ||
528 | |||
529 | /* Initialize CIR & CIR Wake Config Registers */ | ||
530 | fintek_cir_regs_init(fintek); | ||
531 | |||
532 | /* Set up the rc device */ | ||
533 | rdev->priv = fintek; | ||
534 | rdev->driver_type = RC_DRIVER_IR_RAW; | ||
535 | rdev->allowed_protos = RC_TYPE_ALL; | ||
536 | rdev->open = fintek_open; | ||
537 | rdev->close = fintek_close; | ||
538 | rdev->input_name = FINTEK_DESCRIPTION; | ||
539 | rdev->input_phys = "fintek/cir0"; | ||
540 | rdev->input_id.bustype = BUS_HOST; | ||
541 | rdev->input_id.vendor = VENDOR_ID_FINTEK; | ||
542 | rdev->input_id.product = fintek->chip_major; | ||
543 | rdev->input_id.version = fintek->chip_minor; | ||
544 | rdev->dev.parent = &pdev->dev; | ||
545 | rdev->driver_name = FINTEK_DRIVER_NAME; | ||
546 | rdev->map_name = RC_MAP_RC6_MCE; | ||
547 | rdev->timeout = US_TO_NS(1000); | ||
548 | /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ | ||
549 | rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); | ||
550 | |||
551 | ret = rc_register_device(rdev); | ||
552 | if (ret) | ||
553 | goto failure; | ||
554 | |||
555 | device_init_wakeup(&pdev->dev, true); | ||
556 | fintek->rdev = rdev; | ||
557 | fit_pr(KERN_NOTICE, "driver has been successfully loaded\n"); | ||
558 | if (debug) | ||
559 | cir_dump_regs(fintek); | ||
560 | |||
561 | return 0; | ||
562 | |||
563 | failure: | ||
564 | if (fintek->cir_irq) | ||
565 | free_irq(fintek->cir_irq, fintek); | ||
566 | if (fintek->cir_addr) | ||
567 | release_region(fintek->cir_addr, fintek->cir_port_len); | ||
568 | |||
569 | rc_free_device(rdev); | ||
570 | kfree(fintek); | ||
571 | |||
572 | return ret; | ||
573 | } | ||
574 | |||
575 | static void __devexit fintek_remove(struct pnp_dev *pdev) | ||
576 | { | ||
577 | struct fintek_dev *fintek = pnp_get_drvdata(pdev); | ||
578 | unsigned long flags; | ||
579 | |||
580 | spin_lock_irqsave(&fintek->fintek_lock, flags); | ||
581 | /* disable CIR */ | ||
582 | fintek_disable_cir(fintek); | ||
583 | fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); | ||
584 | /* enable CIR Wake (for IR power-on) */ | ||
585 | fintek_enable_wake(fintek); | ||
586 | spin_unlock_irqrestore(&fintek->fintek_lock, flags); | ||
587 | |||
588 | /* free resources */ | ||
589 | free_irq(fintek->cir_irq, fintek); | ||
590 | release_region(fintek->cir_addr, fintek->cir_port_len); | ||
591 | |||
592 | rc_unregister_device(fintek->rdev); | ||
593 | |||
594 | kfree(fintek); | ||
595 | } | ||
596 | |||
597 | static int fintek_suspend(struct pnp_dev *pdev, pm_message_t state) | ||
598 | { | ||
599 | struct fintek_dev *fintek = pnp_get_drvdata(pdev); | ||
600 | |||
601 | fit_dbg("%s called", __func__); | ||
602 | |||
603 | /* disable all CIR interrupts */ | ||
604 | fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); | ||
605 | |||
606 | fintek_config_mode_enable(fintek); | ||
607 | |||
608 | /* disable cir logical dev */ | ||
609 | fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); | ||
610 | fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); | ||
611 | |||
612 | fintek_config_mode_disable(fintek); | ||
613 | |||
614 | /* make sure wake is enabled */ | ||
615 | fintek_enable_wake(fintek); | ||
616 | |||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | static int fintek_resume(struct pnp_dev *pdev) | ||
621 | { | ||
622 | int ret = 0; | ||
623 | struct fintek_dev *fintek = pnp_get_drvdata(pdev); | ||
624 | |||
625 | fit_dbg("%s called", __func__); | ||
626 | |||
627 | /* open interrupt */ | ||
628 | fintek_enable_cir_irq(fintek); | ||
629 | |||
630 | /* Enable CIR logical device */ | ||
631 | fintek_config_mode_enable(fintek); | ||
632 | fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); | ||
633 | fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); | ||
634 | |||
635 | fintek_config_mode_disable(fintek); | ||
636 | |||
637 | fintek_cir_regs_init(fintek); | ||
638 | |||
639 | return ret; | ||
640 | } | ||
641 | |||
642 | static void fintek_shutdown(struct pnp_dev *pdev) | ||
643 | { | ||
644 | struct fintek_dev *fintek = pnp_get_drvdata(pdev); | ||
645 | fintek_enable_wake(fintek); | ||
646 | } | ||
647 | |||
648 | static const struct pnp_device_id fintek_ids[] = { | ||
649 | { "FIT0002", 0 }, /* CIR */ | ||
650 | { "", 0 }, | ||
651 | }; | ||
652 | |||
653 | static struct pnp_driver fintek_driver = { | ||
654 | .name = FINTEK_DRIVER_NAME, | ||
655 | .id_table = fintek_ids, | ||
656 | .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, | ||
657 | .probe = fintek_probe, | ||
658 | .remove = __devexit_p(fintek_remove), | ||
659 | .suspend = fintek_suspend, | ||
660 | .resume = fintek_resume, | ||
661 | .shutdown = fintek_shutdown, | ||
662 | }; | ||
663 | |||
664 | int fintek_init(void) | ||
665 | { | ||
666 | return pnp_register_driver(&fintek_driver); | ||
667 | } | ||
668 | |||
669 | void fintek_exit(void) | ||
670 | { | ||
671 | pnp_unregister_driver(&fintek_driver); | ||
672 | } | ||
673 | |||
674 | module_param(debug, int, S_IRUGO | S_IWUSR); | ||
675 | MODULE_PARM_DESC(debug, "Enable debugging output"); | ||
676 | |||
677 | MODULE_DEVICE_TABLE(pnp, fintek_ids); | ||
678 | MODULE_DESCRIPTION(FINTEK_DESCRIPTION " driver"); | ||
679 | |||
680 | MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); | ||
681 | MODULE_LICENSE("GPL"); | ||
682 | |||
683 | module_init(fintek_init); | ||
684 | module_exit(fintek_exit); | ||
diff --git a/drivers/media/rc/fintek-cir.h b/drivers/media/rc/fintek-cir.h new file mode 100644 index 000000000000..1b10b2011f5e --- /dev/null +++ b/drivers/media/rc/fintek-cir.h | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | * Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR | ||
3 | * | ||
4 | * Copyright (C) 2011 Jarod Wilson <jarod@redhat.com> | ||
5 | * | ||
6 | * Special thanks to Fintek for providing hardware and spec sheets. | ||
7 | * This driver is based upon the nuvoton, ite and ene drivers for | ||
8 | * similar hardware. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License as | ||
12 | * published by the Free Software Foundation; either version 2 of the | ||
13 | * License, or (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
23 | * USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/ioctl.h> | ||
28 | |||
29 | /* platform driver name to register */ | ||
30 | #define FINTEK_DRIVER_NAME "fintek-cir" | ||
31 | #define FINTEK_DESCRIPTION "Fintek LPC SuperIO Consumer IR Transceiver" | ||
32 | #define VENDOR_ID_FINTEK 0x1934 | ||
33 | |||
34 | |||
35 | /* debugging module parameter */ | ||
36 | static int debug; | ||
37 | |||
38 | #define fit_pr(level, text, ...) \ | ||
39 | printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__) | ||
40 | |||
41 | #define fit_dbg(text, ...) \ | ||
42 | if (debug) \ | ||
43 | printk(KERN_DEBUG \ | ||
44 | KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) | ||
45 | |||
46 | #define fit_dbg_verbose(text, ...) \ | ||
47 | if (debug > 1) \ | ||
48 | printk(KERN_DEBUG \ | ||
49 | KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) | ||
50 | |||
51 | #define fit_dbg_wake(text, ...) \ | ||
52 | if (debug > 2) \ | ||
53 | printk(KERN_DEBUG \ | ||
54 | KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) | ||
55 | |||
56 | |||
57 | #define TX_BUF_LEN 256 | ||
58 | #define RX_BUF_LEN 32 | ||
59 | |||
60 | struct fintek_dev { | ||
61 | struct pnp_dev *pdev; | ||
62 | struct rc_dev *rdev; | ||
63 | |||
64 | spinlock_t fintek_lock; | ||
65 | |||
66 | /* for rx */ | ||
67 | u8 buf[RX_BUF_LEN]; | ||
68 | unsigned int pkts; | ||
69 | |||
70 | struct { | ||
71 | spinlock_t lock; | ||
72 | u8 buf[TX_BUF_LEN]; | ||
73 | unsigned int buf_count; | ||
74 | unsigned int cur_buf_num; | ||
75 | wait_queue_head_t queue; | ||
76 | } tx; | ||
77 | |||
78 | /* Config register index/data port pair */ | ||
79 | u8 cr_ip; | ||
80 | u8 cr_dp; | ||
81 | |||
82 | /* hardware I/O settings */ | ||
83 | unsigned long cir_addr; | ||
84 | int cir_irq; | ||
85 | int cir_port_len; | ||
86 | |||
87 | /* hardware id */ | ||
88 | u8 chip_major; | ||
89 | u8 chip_minor; | ||
90 | u16 chip_vendor; | ||
91 | |||
92 | /* hardware features */ | ||
93 | bool hw_learning_capable; | ||
94 | bool hw_tx_capable; | ||
95 | |||
96 | /* rx settings */ | ||
97 | bool learning_enabled; | ||
98 | bool carrier_detect_enabled; | ||
99 | |||
100 | enum { | ||
101 | CMD_HEADER = 0, | ||
102 | SUBCMD, | ||
103 | CMD_DATA, | ||
104 | PARSE_IRDATA, | ||
105 | } parser_state; | ||
106 | |||
107 | u8 cmd, rem; | ||
108 | |||
109 | /* carrier period = 1 / frequency */ | ||
110 | u32 carrier; | ||
111 | }; | ||
112 | |||
113 | /* buffer packet constants, largely identical to mceusb.c */ | ||
114 | #define BUF_PULSE_BIT 0x80 | ||
115 | #define BUF_LEN_MASK 0x1f | ||
116 | #define BUF_SAMPLE_MASK 0x7f | ||
117 | |||
118 | #define BUF_COMMAND_HEADER 0x9f | ||
119 | #define BUF_COMMAND_MASK 0xe0 | ||
120 | #define BUF_COMMAND_NULL 0x00 | ||
121 | #define BUF_HW_CMD_HEADER 0xff | ||
122 | #define BUF_CMD_G_REVISION 0x0b | ||
123 | #define BUF_CMD_S_CARRIER 0x06 | ||
124 | #define BUF_CMD_S_TIMEOUT 0x0c | ||
125 | #define BUF_CMD_SIG_END 0x01 | ||
126 | #define BUF_CMD_S_TXMASK 0x08 | ||
127 | #define BUF_CMD_S_RXSENSOR 0x14 | ||
128 | #define BUF_RSP_PULSE_COUNT 0x15 | ||
129 | |||
130 | #define CIR_SAMPLE_PERIOD 50 | ||
131 | |||
132 | /* | ||
133 | * Configuration Register: | ||
134 | * Index Port | ||
135 | * Data Port | ||
136 | */ | ||
137 | #define CR_INDEX_PORT 0x2e | ||
138 | #define CR_DATA_PORT 0x2f | ||
139 | |||
140 | /* Possible alternate values, depends on how the chip is wired */ | ||
141 | #define CR_INDEX_PORT2 0x4e | ||
142 | #define CR_DATA_PORT2 0x4f | ||
143 | |||
144 | /* | ||
145 | * GCR_CONFIG_PORT_SEL bit 4 specifies which Index Port value is | ||
146 | * active. 1 = 0x4e, 0 = 0x2e | ||
147 | */ | ||
148 | #define PORT_SEL_PORT_4E_EN 0x10 | ||
149 | |||
150 | /* Extended Function Mode enable/disable magic values */ | ||
151 | #define CONFIG_REG_ENABLE 0x87 | ||
152 | #define CONFIG_REG_DISABLE 0xaa | ||
153 | |||
154 | /* Chip IDs found in CR_CHIP_ID_{HI,LO} */ | ||
155 | #define CHIP_ID_HIGH_F71809U 0x04 | ||
156 | #define CHIP_ID_LOW_F71809U 0x08 | ||
157 | |||
158 | /* | ||
159 | * Global control regs we need to care about: | ||
160 | * Global Control def. | ||
161 | * Register name addr val. */ | ||
162 | #define GCR_SOFTWARE_RESET 0x02 /* 0x00 */ | ||
163 | #define GCR_LOGICAL_DEV_NO 0x07 /* 0x00 */ | ||
164 | #define GCR_CHIP_ID_HI 0x20 /* 0x04 */ | ||
165 | #define GCR_CHIP_ID_LO 0x21 /* 0x08 */ | ||
166 | #define GCR_VENDOR_ID_HI 0x23 /* 0x19 */ | ||
167 | #define GCR_VENDOR_ID_LO 0x24 /* 0x34 */ | ||
168 | #define GCR_CONFIG_PORT_SEL 0x25 /* 0x01 */ | ||
169 | #define GCR_KBMOUSE_WAKEUP 0x27 | ||
170 | |||
171 | #define LOGICAL_DEV_DISABLE 0x00 | ||
172 | #define LOGICAL_DEV_ENABLE 0x01 | ||
173 | |||
174 | /* Logical device number of the CIR function */ | ||
175 | #define LOGICAL_DEV_CIR 0x05 | ||
176 | |||
177 | /* CIR Logical Device (LDN 0x08) config registers */ | ||
178 | #define CIR_CR_COMMAND_INDEX 0x04 | ||
179 | #define CIR_CR_IRCS 0x05 /* Before host writes command to IR, host | ||
180 | must set to 1. When host finshes write | ||
181 | command to IR, host must clear to 0. */ | ||
182 | #define CIR_CR_COMMAND_DATA 0x06 /* Host read or write comand data */ | ||
183 | #define CIR_CR_CLASS 0x07 /* 0xff = rx-only, 0x66 = rx + 2 tx, | ||
184 | 0x33 = rx + 1 tx */ | ||
185 | #define CIR_CR_DEV_EN 0x30 /* bit0 = 1 enables CIR */ | ||
186 | #define CIR_CR_BASE_ADDR_HI 0x60 /* MSB of CIR IO base addr */ | ||
187 | #define CIR_CR_BASE_ADDR_LO 0x61 /* LSB of CIR IO base addr */ | ||
188 | #define CIR_CR_IRQ_SEL 0x70 /* bits3-0 store CIR IRQ */ | ||
189 | #define CIR_CR_PSOUT_STATUS 0xf1 | ||
190 | #define CIR_CR_WAKE_KEY3_ADDR 0xf8 | ||
191 | #define CIR_CR_WAKE_KEY3_CODE 0xf9 | ||
192 | #define CIR_CR_WAKE_KEY3_DC 0xfa | ||
193 | #define CIR_CR_WAKE_CONTROL 0xfb | ||
194 | #define CIR_CR_WAKE_KEY12_ADDR 0xfc | ||
195 | #define CIR_CR_WAKE_KEY4_ADDR 0xfd | ||
196 | #define CIR_CR_WAKE_KEY5_ADDR 0xfe | ||
197 | |||
198 | #define CLASS_RX_ONLY 0xff | ||
199 | #define CLASS_RX_2TX 0x66 | ||
200 | #define CLASS_RX_1TX 0x33 | ||
201 | |||
202 | /* CIR device registers */ | ||
203 | #define CIR_STATUS 0x00 | ||
204 | #define CIR_RX_DATA 0x01 | ||
205 | #define CIR_TX_CONTROL 0x02 | ||
206 | #define CIR_TX_DATA 0x03 | ||
207 | #define CIR_CONTROL 0x04 | ||
208 | |||
209 | /* Bits to enable CIR wake */ | ||
210 | #define LOGICAL_DEV_ACPI 0x01 | ||
211 | #define LDEV_ACPI_WAKE_EN_REG 0xe8 | ||
212 | #define ACPI_WAKE_EN_CIR_BIT 0x04 | ||
213 | |||
214 | #define LDEV_ACPI_PME_EN_REG 0xf0 | ||
215 | #define LDEV_ACPI_PME_CLR_REG 0xf1 | ||
216 | #define ACPI_PME_CIR_BIT 0x02 | ||
217 | |||
218 | #define LDEV_ACPI_STATE_REG 0xf4 | ||
219 | #define ACPI_STATE_CIR_BIT 0x20 | ||
220 | |||
221 | /* | ||
222 | * CIR status register (0x00): | ||
223 | * 7 - CIR_IRQ_EN (1 = enable CIR IRQ, 0 = disable) | ||
224 | * 3 - TX_FINISH (1 when TX finished, write 1 to clear) | ||
225 | * 2 - TX_UNDERRUN (1 on TX underrun, write 1 to clear) | ||
226 | * 1 - RX_TIMEOUT (1 on RX timeout, write 1 to clear) | ||
227 | * 0 - RX_RECEIVE (1 on RX receive, write 1 to clear) | ||
228 | */ | ||
229 | #define CIR_STATUS_IRQ_EN 0x80 | ||
230 | #define CIR_STATUS_TX_FINISH 0x08 | ||
231 | #define CIR_STATUS_TX_UNDERRUN 0x04 | ||
232 | #define CIR_STATUS_RX_TIMEOUT 0x02 | ||
233 | #define CIR_STATUS_RX_RECEIVE 0x01 | ||
234 | #define CIR_STATUS_IRQ_MASK 0x0f | ||
235 | |||
236 | /* | ||
237 | * CIR TX control register (0x02): | ||
238 | * 7 - TX_START (1 to indicate TX start, auto-cleared when done) | ||
239 | * 6 - TX_END (1 to indicate TX data written to TX fifo) | ||
240 | */ | ||
241 | #define CIR_TX_CONTROL_TX_START 0x80 | ||
242 | #define CIR_TX_CONTROL_TX_END 0x40 | ||
243 | |||
diff --git a/drivers/media/rc/keymaps/rc-lme2510.c b/drivers/media/rc/keymaps/rc-lme2510.c index afae14fd152e..129d3f9a461d 100644 --- a/drivers/media/rc/keymaps/rc-lme2510.c +++ b/drivers/media/rc/keymaps/rc-lme2510.c | |||
@@ -14,81 +14,81 @@ | |||
14 | 14 | ||
15 | static struct rc_map_table lme2510_rc[] = { | 15 | static struct rc_map_table lme2510_rc[] = { |
16 | /* Type 1 - 26 buttons */ | 16 | /* Type 1 - 26 buttons */ |
17 | { 0xef12ba45, KEY_0 }, | 17 | { 0x10ed45, KEY_0 }, |
18 | { 0xef12a05f, KEY_1 }, | 18 | { 0x10ed5f, KEY_1 }, |
19 | { 0xef12af50, KEY_2 }, | 19 | { 0x10ed50, KEY_2 }, |
20 | { 0xef12a25d, KEY_3 }, | 20 | { 0x10ed5d, KEY_3 }, |
21 | { 0xef12be41, KEY_4 }, | 21 | { 0x10ed41, KEY_4 }, |
22 | { 0xef12f50a, KEY_5 }, | 22 | { 0x10ed0a, KEY_5 }, |
23 | { 0xef12bd42, KEY_6 }, | 23 | { 0x10ed42, KEY_6 }, |
24 | { 0xef12b847, KEY_7 }, | 24 | { 0x10ed47, KEY_7 }, |
25 | { 0xef12b649, KEY_8 }, | 25 | { 0x10ed49, KEY_8 }, |
26 | { 0xef12fa05, KEY_9 }, | 26 | { 0x10ed05, KEY_9 }, |
27 | { 0xef12bc43, KEY_POWER }, | 27 | { 0x10ed43, KEY_POWER }, |
28 | { 0xef12b946, KEY_SUBTITLE }, | 28 | { 0x10ed46, KEY_SUBTITLE }, |
29 | { 0xef12f906, KEY_PAUSE }, | 29 | { 0x10ed06, KEY_PAUSE }, |
30 | { 0xef12fc03, KEY_MEDIA_REPEAT}, | 30 | { 0x10ed03, KEY_MEDIA_REPEAT}, |
31 | { 0xef12fd02, KEY_PAUSE }, | 31 | { 0x10ed02, KEY_PAUSE }, |
32 | { 0xef12a15e, KEY_VOLUMEUP }, | 32 | { 0x10ed5e, KEY_VOLUMEUP }, |
33 | { 0xef12a35c, KEY_VOLUMEDOWN }, | 33 | { 0x10ed5c, KEY_VOLUMEDOWN }, |
34 | { 0xef12f609, KEY_CHANNELUP }, | 34 | { 0x10ed09, KEY_CHANNELUP }, |
35 | { 0xef12e51a, KEY_CHANNELDOWN }, | 35 | { 0x10ed1a, KEY_CHANNELDOWN }, |
36 | { 0xef12e11e, KEY_PLAY }, | 36 | { 0x10ed1e, KEY_PLAY }, |
37 | { 0xef12e41b, KEY_ZOOM }, | 37 | { 0x10ed1b, KEY_ZOOM }, |
38 | { 0xef12a659, KEY_MUTE }, | 38 | { 0x10ed59, KEY_MUTE }, |
39 | { 0xef12a55a, KEY_TV }, | 39 | { 0x10ed5a, KEY_TV }, |
40 | { 0xef12e718, KEY_RECORD }, | 40 | { 0x10ed18, KEY_RECORD }, |
41 | { 0xef12f807, KEY_EPG }, | 41 | { 0x10ed07, KEY_EPG }, |
42 | { 0xef12fe01, KEY_STOP }, | 42 | { 0x10ed01, KEY_STOP }, |
43 | /* Type 2 - 20 buttons */ | 43 | /* Type 2 - 20 buttons */ |
44 | { 0xff40ea15, KEY_0 }, | 44 | { 0xbf15, KEY_0 }, |
45 | { 0xff40f708, KEY_1 }, | 45 | { 0xbf08, KEY_1 }, |
46 | { 0xff40f609, KEY_2 }, | 46 | { 0xbf09, KEY_2 }, |
47 | { 0xff40f50a, KEY_3 }, | 47 | { 0xbf0a, KEY_3 }, |
48 | { 0xff40f30c, KEY_4 }, | 48 | { 0xbf0c, KEY_4 }, |
49 | { 0xff40f20d, KEY_5 }, | 49 | { 0xbf0d, KEY_5 }, |
50 | { 0xff40f10e, KEY_6 }, | 50 | { 0xbf0e, KEY_6 }, |
51 | { 0xff40ef10, KEY_7 }, | 51 | { 0xbf10, KEY_7 }, |
52 | { 0xff40ee11, KEY_8 }, | 52 | { 0xbf11, KEY_8 }, |
53 | { 0xff40ed12, KEY_9 }, | 53 | { 0xbf12, KEY_9 }, |
54 | { 0xff40ff00, KEY_POWER }, | 54 | { 0xbf00, KEY_POWER }, |
55 | { 0xff40fb04, KEY_MEDIA_REPEAT}, /* Recall */ | 55 | { 0xbf04, KEY_MEDIA_REPEAT}, /* Recall */ |
56 | { 0xff40e51a, KEY_PAUSE }, /* Timeshift */ | 56 | { 0xbf1a, KEY_PAUSE }, /* Timeshift */ |
57 | { 0xff40fd02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ | 57 | { 0xbf02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ |
58 | { 0xff40f906, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ | 58 | { 0xbf06, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ |
59 | { 0xff40fe01, KEY_CHANNELUP }, | 59 | { 0xbf01, KEY_CHANNELUP }, |
60 | { 0xff40fa05, KEY_CHANNELDOWN }, | 60 | { 0xbf05, KEY_CHANNELDOWN }, |
61 | { 0xff40eb14, KEY_ZOOM }, | 61 | { 0xbf14, KEY_ZOOM }, |
62 | { 0xff40e718, KEY_RECORD }, | 62 | { 0xbf18, KEY_RECORD }, |
63 | { 0xff40e916, KEY_STOP }, | 63 | { 0xbf16, KEY_STOP }, |
64 | /* Type 3 - 20 buttons */ | 64 | /* Type 3 - 20 buttons */ |
65 | { 0xff00e31c, KEY_0 }, | 65 | { 0x1c, KEY_0 }, |
66 | { 0xff00f807, KEY_1 }, | 66 | { 0x07, KEY_1 }, |
67 | { 0xff00ea15, KEY_2 }, | 67 | { 0x15, KEY_2 }, |
68 | { 0xff00f609, KEY_3 }, | 68 | { 0x09, KEY_3 }, |
69 | { 0xff00e916, KEY_4 }, | 69 | { 0x16, KEY_4 }, |
70 | { 0xff00e619, KEY_5 }, | 70 | { 0x19, KEY_5 }, |
71 | { 0xff00f20d, KEY_6 }, | 71 | { 0x0d, KEY_6 }, |
72 | { 0xff00f30c, KEY_7 }, | 72 | { 0x0c, KEY_7 }, |
73 | { 0xff00e718, KEY_8 }, | 73 | { 0x18, KEY_8 }, |
74 | { 0xff00a15e, KEY_9 }, | 74 | { 0x5e, KEY_9 }, |
75 | { 0xff00ba45, KEY_POWER }, | 75 | { 0x45, KEY_POWER }, |
76 | { 0xff00bb44, KEY_MEDIA_REPEAT}, /* Recall */ | 76 | { 0x44, KEY_MEDIA_REPEAT}, /* Recall */ |
77 | { 0xff00b54a, KEY_PAUSE }, /* Timeshift */ | 77 | { 0x4a, KEY_PAUSE }, /* Timeshift */ |
78 | { 0xff00b847, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ | 78 | { 0x47, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ |
79 | { 0xff00bc43, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ | 79 | { 0x43, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ |
80 | { 0xff00b946, KEY_CHANNELUP }, | 80 | { 0x46, KEY_CHANNELUP }, |
81 | { 0xff00bf40, KEY_CHANNELDOWN }, | 81 | { 0x40, KEY_CHANNELDOWN }, |
82 | { 0xff00f708, KEY_ZOOM }, | 82 | { 0x08, KEY_ZOOM }, |
83 | { 0xff00bd42, KEY_RECORD }, | 83 | { 0x42, KEY_RECORD }, |
84 | { 0xff00a55a, KEY_STOP }, | 84 | { 0x5a, KEY_STOP }, |
85 | }; | 85 | }; |
86 | 86 | ||
87 | static struct rc_map_list lme2510_map = { | 87 | static struct rc_map_list lme2510_map = { |
88 | .map = { | 88 | .map = { |
89 | .scan = lme2510_rc, | 89 | .scan = lme2510_rc, |
90 | .size = ARRAY_SIZE(lme2510_rc), | 90 | .size = ARRAY_SIZE(lme2510_rc), |
91 | .rc_type = RC_TYPE_UNKNOWN, | 91 | .rc_type = RC_TYPE_NEC, |
92 | .name = RC_MAP_LME2510, | 92 | .name = RC_MAP_LME2510, |
93 | } | 93 | } |
94 | }; | 94 | }; |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 3be180b3ba27..bb53de7fe408 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -687,7 +687,7 @@ config VIDEO_HEXIUM_GEMINI | |||
687 | 687 | ||
688 | config VIDEO_TIMBERDALE | 688 | config VIDEO_TIMBERDALE |
689 | tristate "Support for timberdale Video In/LogiWIN" | 689 | tristate "Support for timberdale Video In/LogiWIN" |
690 | depends on VIDEO_V4L2 && I2C | 690 | depends on VIDEO_V4L2 && I2C && DMADEVICES |
691 | select DMA_ENGINE | 691 | select DMA_ENGINE |
692 | select TIMB_DMA | 692 | select TIMB_DMA |
693 | select VIDEO_ADV7180 | 693 | select VIDEO_ADV7180 |
@@ -757,6 +757,8 @@ config VIDEO_NOON010PC30 | |||
757 | ---help--- | 757 | ---help--- |
758 | This driver supports NOON010PC30 CIF camera from Siliconfile | 758 | This driver supports NOON010PC30 CIF camera from Siliconfile |
759 | 759 | ||
760 | source "drivers/media/video/m5mols/Kconfig" | ||
761 | |||
760 | config VIDEO_OMAP3 | 762 | config VIDEO_OMAP3 |
761 | tristate "OMAP 3 Camera support (EXPERIMENTAL)" | 763 | tristate "OMAP 3 Camera support (EXPERIMENTAL)" |
762 | select OMAP_IOMMU | 764 | select OMAP_IOMMU |
@@ -952,7 +954,7 @@ config VIDEO_SAMSUNG_S5P_FIMC | |||
952 | 954 | ||
953 | config VIDEO_S5P_MIPI_CSIS | 955 | config VIDEO_S5P_MIPI_CSIS |
954 | tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver" | 956 | tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver" |
955 | depends on VIDEO_V4L2 && PM_RUNTIME && VIDEO_V4L2_SUBDEV_API | 957 | depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P && VIDEO_V4L2_SUBDEV_API |
956 | ---help--- | 958 | ---help--- |
957 | This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver. | 959 | This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver. |
958 | 960 | ||
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 9519160c2e01..f0fecd6f6a33 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o | |||
69 | obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o | 69 | obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o |
70 | obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o | 70 | obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o |
71 | obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o | 71 | obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o |
72 | obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ | ||
72 | 73 | ||
73 | obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o | 74 | obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o |
74 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o | 75 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o |
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 0073a8c55336..40eb6326e48a 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c | |||
@@ -438,7 +438,7 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v | |||
438 | strcat(vc->card, " (676/"); | 438 | strcat(vc->card, " (676/"); |
439 | break; | 439 | break; |
440 | default: | 440 | default: |
441 | strcat(vc->card, " (???/"); | 441 | strcat(vc->card, " (XXX/"); |
442 | break; | 442 | break; |
443 | } | 443 | } |
444 | switch (cam->params.version.sensor_flags) { | 444 | switch (cam->params.version.sensor_flags) { |
@@ -458,7 +458,7 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v | |||
458 | strcat(vc->card, "500)"); | 458 | strcat(vc->card, "500)"); |
459 | break; | 459 | break; |
460 | default: | 460 | default: |
461 | strcat(vc->card, "???)"); | 461 | strcat(vc->card, "XXX)"); |
462 | break; | 462 | break; |
463 | } | 463 | } |
464 | 464 | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c index 280df43ca446..8d7813415760 100644 --- a/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/drivers/media/video/cx231xx/cx231xx-avcore.c | |||
@@ -1354,7 +1354,7 @@ void cx231xx_dump_SC_reg(struct cx231xx *dev) | |||
1354 | { | 1354 | { |
1355 | u8 value[4] = { 0, 0, 0, 0 }; | 1355 | u8 value[4] = { 0, 0, 0, 0 }; |
1356 | int status = 0; | 1356 | int status = 0; |
1357 | cx231xx_info("cx231xx_dump_SC_reg %s!\n", __TIME__); | 1357 | cx231xx_info("cx231xx_dump_SC_reg!\n"); |
1358 | 1358 | ||
1359 | status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, | 1359 | status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, |
1360 | value, 4); | 1360 | value, 4); |
diff --git a/drivers/media/video/gspca/kinect.c b/drivers/media/video/gspca/kinect.c index 66671a4092e4..26fc206f095e 100644 --- a/drivers/media/video/gspca/kinect.c +++ b/drivers/media/video/gspca/kinect.c | |||
@@ -34,7 +34,7 @@ MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); | |||
34 | MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver"); | 34 | MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | 36 | ||
37 | #ifdef DEBUG | 37 | #ifdef GSPCA_DEBUG |
38 | int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK | | 38 | int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK | |
39 | D_USBI | D_USBO | D_V4L2; | 39 | D_USBI | D_USBO | D_V4L2; |
40 | #endif | 40 | #endif |
diff --git a/drivers/media/video/m5mols/Kconfig b/drivers/media/video/m5mols/Kconfig new file mode 100644 index 000000000000..302dc3d70193 --- /dev/null +++ b/drivers/media/video/m5mols/Kconfig | |||
@@ -0,0 +1,5 @@ | |||
1 | config VIDEO_M5MOLS | ||
2 | tristate "Fujitsu M-5MOLS 8MP sensor support" | ||
3 | depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API | ||
4 | ---help--- | ||
5 | This driver supports Fujitsu M-5MOLS camera sensor with ISP | ||
diff --git a/drivers/media/video/m5mols/Makefile b/drivers/media/video/m5mols/Makefile new file mode 100644 index 000000000000..0a44e028edc7 --- /dev/null +++ b/drivers/media/video/m5mols/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | m5mols-objs := m5mols_core.o m5mols_controls.o m5mols_capture.o | ||
2 | |||
3 | obj-$(CONFIG_VIDEO_M5MOLS) += m5mols.o | ||
diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h new file mode 100644 index 000000000000..10b55c854487 --- /dev/null +++ b/drivers/media/video/m5mols/m5mols.h | |||
@@ -0,0 +1,296 @@ | |||
1 | /* | ||
2 | * Header for M-5MOLS 8M Pixel camera sensor with ISP | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
5 | * Author: HeungJun Kim, riverful.kim@samsung.com | ||
6 | * | ||
7 | * Copyright (C) 2009 Samsung Electronics Co., Ltd. | ||
8 | * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com | ||
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 as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifndef M5MOLS_H | ||
17 | #define M5MOLS_H | ||
18 | |||
19 | #include <media/v4l2-subdev.h> | ||
20 | #include "m5mols_reg.h" | ||
21 | |||
22 | extern int m5mols_debug; | ||
23 | |||
24 | #define to_m5mols(__sd) container_of(__sd, struct m5mols_info, sd) | ||
25 | |||
26 | #define to_sd(__ctrl) \ | ||
27 | (&container_of(__ctrl->handler, struct m5mols_info, handle)->sd) | ||
28 | |||
29 | enum m5mols_restype { | ||
30 | M5MOLS_RESTYPE_MONITOR, | ||
31 | M5MOLS_RESTYPE_CAPTURE, | ||
32 | M5MOLS_RESTYPE_MAX, | ||
33 | }; | ||
34 | |||
35 | /** | ||
36 | * struct m5mols_resolution - structure for the resolution | ||
37 | * @type: resolution type according to the pixel code | ||
38 | * @width: width of the resolution | ||
39 | * @height: height of the resolution | ||
40 | * @reg: resolution preset register value | ||
41 | */ | ||
42 | struct m5mols_resolution { | ||
43 | u8 reg; | ||
44 | enum m5mols_restype type; | ||
45 | u16 width; | ||
46 | u16 height; | ||
47 | }; | ||
48 | |||
49 | /** | ||
50 | * struct m5mols_exif - structure for the EXIF information of M-5MOLS | ||
51 | * @exposure_time: exposure time register value | ||
52 | * @shutter_speed: speed of the shutter register value | ||
53 | * @aperture: aperture register value | ||
54 | * @exposure_bias: it calls also EV bias | ||
55 | * @iso_speed: ISO register value | ||
56 | * @flash: status register value of the flash | ||
57 | * @sdr: status register value of the Subject Distance Range | ||
58 | * @qval: not written exact meaning in document | ||
59 | */ | ||
60 | struct m5mols_exif { | ||
61 | u32 exposure_time; | ||
62 | u32 shutter_speed; | ||
63 | u32 aperture; | ||
64 | u32 brightness; | ||
65 | u32 exposure_bias; | ||
66 | u16 iso_speed; | ||
67 | u16 flash; | ||
68 | u16 sdr; | ||
69 | u16 qval; | ||
70 | }; | ||
71 | |||
72 | /** | ||
73 | * struct m5mols_capture - Structure for the capture capability | ||
74 | * @exif: EXIF information | ||
75 | * @main: size in bytes of the main image | ||
76 | * @thumb: size in bytes of the thumb image, if it was accompanied | ||
77 | * @total: total size in bytes of the produced image | ||
78 | */ | ||
79 | struct m5mols_capture { | ||
80 | struct m5mols_exif exif; | ||
81 | u32 main; | ||
82 | u32 thumb; | ||
83 | u32 total; | ||
84 | }; | ||
85 | |||
86 | /** | ||
87 | * struct m5mols_scenemode - structure for the scenemode capability | ||
88 | * @metering: metering light register value | ||
89 | * @ev_bias: EV bias register value | ||
90 | * @wb_mode: mode which means the WhiteBalance is Auto or Manual | ||
91 | * @wb_preset: whitebalance preset register value in the Manual mode | ||
92 | * @chroma_en: register value whether the Chroma capability is enabled or not | ||
93 | * @chroma_lvl: chroma's level register value | ||
94 | * @edge_en: register value Whether the Edge capability is enabled or not | ||
95 | * @edge_lvl: edge's level register value | ||
96 | * @af_range: Auto Focus's range | ||
97 | * @fd_mode: Face Detection mode | ||
98 | * @mcc: Multi-axis Color Conversion which means emotion color | ||
99 | * @light: status of the Light | ||
100 | * @flash: status of the Flash | ||
101 | * @tone: Tone color which means Contrast | ||
102 | * @iso: ISO register value | ||
103 | * @capt_mode: Mode of the Image Stabilization while the camera capturing | ||
104 | * @wdr: Wide Dynamic Range register value | ||
105 | * | ||
106 | * The each value according to each scenemode is recommended in the documents. | ||
107 | */ | ||
108 | struct m5mols_scenemode { | ||
109 | u32 metering; | ||
110 | u32 ev_bias; | ||
111 | u32 wb_mode; | ||
112 | u32 wb_preset; | ||
113 | u32 chroma_en; | ||
114 | u32 chroma_lvl; | ||
115 | u32 edge_en; | ||
116 | u32 edge_lvl; | ||
117 | u32 af_range; | ||
118 | u32 fd_mode; | ||
119 | u32 mcc; | ||
120 | u32 light; | ||
121 | u32 flash; | ||
122 | u32 tone; | ||
123 | u32 iso; | ||
124 | u32 capt_mode; | ||
125 | u32 wdr; | ||
126 | }; | ||
127 | |||
128 | /** | ||
129 | * struct m5mols_version - firmware version information | ||
130 | * @customer: customer information | ||
131 | * @project: version of project information according to customer | ||
132 | * @fw: firmware revision | ||
133 | * @hw: hardware revision | ||
134 | * @param: version of the parameter | ||
135 | * @awb: Auto WhiteBalance algorithm version | ||
136 | * @str: information about manufacturer and packaging vendor | ||
137 | * @af: Auto Focus version | ||
138 | * | ||
139 | * The register offset starts the customer version at 0x0, and it ends | ||
140 | * the awb version at 0x09. The customer, project information occupies 1 bytes | ||
141 | * each. And also the fw, hw, param, awb each requires 2 bytes. The str is | ||
142 | * unique string associated with firmware's version. It includes information | ||
143 | * about manufacturer and the vendor of the sensor's packaging. The least | ||
144 | * significant 2 bytes of the string indicate packaging manufacturer. | ||
145 | */ | ||
146 | #define VERSION_STRING_SIZE 22 | ||
147 | struct m5mols_version { | ||
148 | u8 customer; | ||
149 | u8 project; | ||
150 | u16 fw; | ||
151 | u16 hw; | ||
152 | u16 param; | ||
153 | u16 awb; | ||
154 | u8 str[VERSION_STRING_SIZE]; | ||
155 | u8 af; | ||
156 | }; | ||
157 | #define VERSION_SIZE sizeof(struct m5mols_version) | ||
158 | |||
159 | /** | ||
160 | * struct m5mols_info - M-5MOLS driver data structure | ||
161 | * @pdata: platform data | ||
162 | * @sd: v4l-subdev instance | ||
163 | * @pad: media pad | ||
164 | * @ffmt: current fmt according to resolution type | ||
165 | * @res_type: current resolution type | ||
166 | * @code: current code | ||
167 | * @irq_waitq: waitqueue for the capture | ||
168 | * @work_irq: workqueue for the IRQ | ||
169 | * @flags: state variable for the interrupt handler | ||
170 | * @handle: control handler | ||
171 | * @autoexposure: Auto Exposure control | ||
172 | * @exposure: Exposure control | ||
173 | * @autowb: Auto White Balance control | ||
174 | * @colorfx: Color effect control | ||
175 | * @saturation: Saturation control | ||
176 | * @zoom: Zoom control | ||
177 | * @ver: information of the version | ||
178 | * @cap: the capture mode attributes | ||
179 | * @power: current sensor's power status | ||
180 | * @ctrl_sync: true means all controls of the sensor are initialized | ||
181 | * @int_capture: true means the capture interrupt is issued once | ||
182 | * @lock_ae: true means the Auto Exposure is locked | ||
183 | * @lock_awb: true means the Aut WhiteBalance is locked | ||
184 | * @resolution: register value for current resolution | ||
185 | * @interrupt: register value for current interrupt status | ||
186 | * @mode: register value for current operation mode | ||
187 | * @mode_save: register value for current operation mode for saving | ||
188 | * @set_power: optional power callback to the board code | ||
189 | */ | ||
190 | struct m5mols_info { | ||
191 | const struct m5mols_platform_data *pdata; | ||
192 | struct v4l2_subdev sd; | ||
193 | struct media_pad pad; | ||
194 | struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; | ||
195 | int res_type; | ||
196 | enum v4l2_mbus_pixelcode code; | ||
197 | wait_queue_head_t irq_waitq; | ||
198 | struct work_struct work_irq; | ||
199 | unsigned long flags; | ||
200 | |||
201 | struct v4l2_ctrl_handler handle; | ||
202 | /* Autoexposure/exposure control cluster */ | ||
203 | struct { | ||
204 | struct v4l2_ctrl *autoexposure; | ||
205 | struct v4l2_ctrl *exposure; | ||
206 | }; | ||
207 | struct v4l2_ctrl *autowb; | ||
208 | struct v4l2_ctrl *colorfx; | ||
209 | struct v4l2_ctrl *saturation; | ||
210 | struct v4l2_ctrl *zoom; | ||
211 | |||
212 | struct m5mols_version ver; | ||
213 | struct m5mols_capture cap; | ||
214 | bool power; | ||
215 | bool ctrl_sync; | ||
216 | bool lock_ae; | ||
217 | bool lock_awb; | ||
218 | u8 resolution; | ||
219 | u32 interrupt; | ||
220 | u32 mode; | ||
221 | u32 mode_save; | ||
222 | int (*set_power)(struct device *dev, int on); | ||
223 | }; | ||
224 | |||
225 | #define ST_CAPT_IRQ 0 | ||
226 | |||
227 | #define is_powered(__info) (__info->power) | ||
228 | #define is_ctrl_synced(__info) (__info->ctrl_sync) | ||
229 | #define is_available_af(__info) (__info->ver.af) | ||
230 | #define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code) | ||
231 | #define is_manufacturer(__info, __manufacturer) \ | ||
232 | (__info->ver.str[0] == __manufacturer[0] && \ | ||
233 | __info->ver.str[1] == __manufacturer[1]) | ||
234 | /* | ||
235 | * I2C operation of the M-5MOLS | ||
236 | * | ||
237 | * The I2C read operation of the M-5MOLS requires 2 messages. The first | ||
238 | * message sends the information about the command, command category, and total | ||
239 | * message size. The second message is used to retrieve the data specifed in | ||
240 | * the first message | ||
241 | * | ||
242 | * 1st message 2nd message | ||
243 | * +-------+---+----------+-----+-------+ +------+------+------+------+ | ||
244 | * | size1 | R | category | cmd | size2 | | d[0] | d[1] | d[2] | d[3] | | ||
245 | * +-------+---+----------+-----+-------+ +------+------+------+------+ | ||
246 | * - size1: message data size(5 in this case) | ||
247 | * - size2: desired buffer size of the 2nd message | ||
248 | * - d[0..3]: according to size2 | ||
249 | * | ||
250 | * The I2C write operation needs just one message. The message includes | ||
251 | * category, command, total size, and desired data. | ||
252 | * | ||
253 | * 1st message | ||
254 | * +-------+---+----------+-----+------+------+------+------+ | ||
255 | * | size1 | W | category | cmd | d[0] | d[1] | d[2] | d[3] | | ||
256 | * +-------+---+----------+-----+------+------+------+------+ | ||
257 | * - d[0..3]: according to size1 | ||
258 | */ | ||
259 | int m5mols_read(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); | ||
260 | int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); | ||
261 | int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value); | ||
262 | |||
263 | /* | ||
264 | * Mode operation of the M-5MOLS | ||
265 | * | ||
266 | * Changing the mode of the M-5MOLS is needed right executing order. | ||
267 | * There are three modes(PARAMETER, MONITOR, CAPTURE) which can be changed | ||
268 | * by user. There are various categories associated with each mode. | ||
269 | * | ||
270 | * +============================================================+ | ||
271 | * | mode | category | | ||
272 | * +============================================================+ | ||
273 | * | FLASH | FLASH(only after Stand-by or Power-on) | | ||
274 | * | SYSTEM | SYSTEM(only after sensor arm-booting) | | ||
275 | * | PARAMETER | PARAMETER | | ||
276 | * | MONITOR | MONITOR(preview), Auto Focus, Face Detection | | ||
277 | * | CAPTURE | Single CAPTURE, Preview(recording) | | ||
278 | * +============================================================+ | ||
279 | * | ||
280 | * The available executing order between each modes are as follows: | ||
281 | * PARAMETER <---> MONITOR <---> CAPTURE | ||
282 | */ | ||
283 | int m5mols_mode(struct m5mols_info *info, u32 mode); | ||
284 | |||
285 | int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg); | ||
286 | int m5mols_sync_controls(struct m5mols_info *info); | ||
287 | int m5mols_start_capture(struct m5mols_info *info); | ||
288 | int m5mols_do_scenemode(struct m5mols_info *info, u32 mode); | ||
289 | int m5mols_lock_3a(struct m5mols_info *info, bool lock); | ||
290 | int m5mols_set_ctrl(struct v4l2_ctrl *ctrl); | ||
291 | |||
292 | /* The firmware function */ | ||
293 | int m5mols_update_fw(struct v4l2_subdev *sd, | ||
294 | int (*set_power)(struct m5mols_info *, bool)); | ||
295 | |||
296 | #endif /* M5MOLS_H */ | ||
diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/video/m5mols/m5mols_capture.c new file mode 100644 index 000000000000..d71a3903b60f --- /dev/null +++ b/drivers/media/video/m5mols/m5mols_capture.c | |||
@@ -0,0 +1,191 @@ | |||
1 | /* | ||
2 | * The Capture code for Fujitsu M-5MOLS ISP | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
5 | * Author: HeungJun Kim, riverful.kim@samsung.com | ||
6 | * | ||
7 | * Copyright (C) 2009 Samsung Electronics Co., Ltd. | ||
8 | * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com | ||
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 as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/version.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/regulator/consumer.h> | ||
24 | #include <linux/videodev2.h> | ||
25 | #include <linux/version.h> | ||
26 | #include <media/v4l2-ctrls.h> | ||
27 | #include <media/v4l2-device.h> | ||
28 | #include <media/v4l2-subdev.h> | ||
29 | #include <media/m5mols.h> | ||
30 | |||
31 | #include "m5mols.h" | ||
32 | #include "m5mols_reg.h" | ||
33 | |||
34 | static int m5mols_capture_error_handler(struct m5mols_info *info, | ||
35 | int timeout) | ||
36 | { | ||
37 | int ret; | ||
38 | |||
39 | /* Disable all interrupts and clear relevant interrupt staus bits */ | ||
40 | ret = m5mols_write(&info->sd, SYSTEM_INT_ENABLE, | ||
41 | info->interrupt & ~(REG_INT_CAPTURE)); | ||
42 | if (ret) | ||
43 | return ret; | ||
44 | |||
45 | if (timeout == 0) | ||
46 | return -ETIMEDOUT; | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | /** | ||
51 | * m5mols_read_rational - I2C read of a rational number | ||
52 | * | ||
53 | * Read numerator and denominator from registers @addr_num and @addr_den | ||
54 | * respectively and return the division result in @val. | ||
55 | */ | ||
56 | static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num, | ||
57 | u32 addr_den, u32 *val) | ||
58 | { | ||
59 | u32 num, den; | ||
60 | |||
61 | int ret = m5mols_read(sd, addr_num, &num); | ||
62 | if (!ret) | ||
63 | ret = m5mols_read(sd, addr_den, &den); | ||
64 | if (ret) | ||
65 | return ret; | ||
66 | *val = den == 0 ? 0 : num / den; | ||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * m5mols_capture_info - Gather captured image information | ||
72 | * | ||
73 | * For now it gathers only EXIF information and file size. | ||
74 | */ | ||
75 | static int m5mols_capture_info(struct m5mols_info *info) | ||
76 | { | ||
77 | struct m5mols_exif *exif = &info->cap.exif; | ||
78 | struct v4l2_subdev *sd = &info->sd; | ||
79 | int ret; | ||
80 | |||
81 | ret = m5mols_read_rational(sd, EXIF_INFO_EXPTIME_NU, | ||
82 | EXIF_INFO_EXPTIME_DE, &exif->exposure_time); | ||
83 | if (ret) | ||
84 | return ret; | ||
85 | ret = m5mols_read_rational(sd, EXIF_INFO_TV_NU, EXIF_INFO_TV_DE, | ||
86 | &exif->shutter_speed); | ||
87 | if (ret) | ||
88 | return ret; | ||
89 | ret = m5mols_read_rational(sd, EXIF_INFO_AV_NU, EXIF_INFO_AV_DE, | ||
90 | &exif->aperture); | ||
91 | if (ret) | ||
92 | return ret; | ||
93 | ret = m5mols_read_rational(sd, EXIF_INFO_BV_NU, EXIF_INFO_BV_DE, | ||
94 | &exif->brightness); | ||
95 | if (ret) | ||
96 | return ret; | ||
97 | ret = m5mols_read_rational(sd, EXIF_INFO_EBV_NU, EXIF_INFO_EBV_DE, | ||
98 | &exif->exposure_bias); | ||
99 | if (ret) | ||
100 | return ret; | ||
101 | |||
102 | ret = m5mols_read(sd, EXIF_INFO_ISO, (u32 *)&exif->iso_speed); | ||
103 | if (!ret) | ||
104 | ret = m5mols_read(sd, EXIF_INFO_FLASH, (u32 *)&exif->flash); | ||
105 | if (!ret) | ||
106 | ret = m5mols_read(sd, EXIF_INFO_SDR, (u32 *)&exif->sdr); | ||
107 | if (!ret) | ||
108 | ret = m5mols_read(sd, EXIF_INFO_QVAL, (u32 *)&exif->qval); | ||
109 | if (ret) | ||
110 | return ret; | ||
111 | |||
112 | if (!ret) | ||
113 | ret = m5mols_read(sd, CAPC_IMAGE_SIZE, &info->cap.main); | ||
114 | if (!ret) | ||
115 | ret = m5mols_read(sd, CAPC_THUMB_SIZE, &info->cap.thumb); | ||
116 | if (!ret) | ||
117 | info->cap.total = info->cap.main + info->cap.thumb; | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | int m5mols_start_capture(struct m5mols_info *info) | ||
123 | { | ||
124 | struct v4l2_subdev *sd = &info->sd; | ||
125 | u32 resolution = info->resolution; | ||
126 | int timeout; | ||
127 | int ret; | ||
128 | |||
129 | /* | ||
130 | * Preparing capture. Setting control & interrupt before entering | ||
131 | * capture mode | ||
132 | * | ||
133 | * 1) change to MONITOR mode for operating control & interrupt | ||
134 | * 2) set controls (considering v4l2_control value & lock 3A) | ||
135 | * 3) set interrupt | ||
136 | * 4) change to CAPTURE mode | ||
137 | */ | ||
138 | ret = m5mols_mode(info, REG_MONITOR); | ||
139 | if (!ret) | ||
140 | ret = m5mols_sync_controls(info); | ||
141 | if (!ret) | ||
142 | ret = m5mols_lock_3a(info, true); | ||
143 | if (!ret) | ||
144 | ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE); | ||
145 | if (!ret) | ||
146 | ret = m5mols_mode(info, REG_CAPTURE); | ||
147 | if (!ret) { | ||
148 | /* Wait for capture interrupt, after changing capture mode */ | ||
149 | timeout = wait_event_interruptible_timeout(info->irq_waitq, | ||
150 | test_bit(ST_CAPT_IRQ, &info->flags), | ||
151 | msecs_to_jiffies(2000)); | ||
152 | if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) | ||
153 | ret = m5mols_capture_error_handler(info, timeout); | ||
154 | } | ||
155 | if (!ret) | ||
156 | ret = m5mols_lock_3a(info, false); | ||
157 | if (ret) | ||
158 | return ret; | ||
159 | /* | ||
160 | * Starting capture. Setting capture frame count and resolution and | ||
161 | * the format(available format: JPEG, Bayer RAW, YUV). | ||
162 | * | ||
163 | * 1) select single or multi(enable to 25), format, size | ||
164 | * 2) set interrupt | ||
165 | * 3) start capture(for main image, now) | ||
166 | * 4) get information | ||
167 | * 5) notify file size to v4l2 device(e.g, to s5p-fimc v4l2 device) | ||
168 | */ | ||
169 | ret = m5mols_write(sd, CAPC_SEL_FRAME, 1); | ||
170 | if (!ret) | ||
171 | ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); | ||
172 | if (!ret) | ||
173 | ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution); | ||
174 | if (!ret) | ||
175 | ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE); | ||
176 | if (!ret) | ||
177 | ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN); | ||
178 | if (!ret) { | ||
179 | /* Wait for the capture completion interrupt */ | ||
180 | timeout = wait_event_interruptible_timeout(info->irq_waitq, | ||
181 | test_bit(ST_CAPT_IRQ, &info->flags), | ||
182 | msecs_to_jiffies(2000)); | ||
183 | if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) { | ||
184 | ret = m5mols_capture_info(info); | ||
185 | if (!ret) | ||
186 | v4l2_subdev_notify(sd, 0, &info->cap.total); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | return m5mols_capture_error_handler(info, timeout); | ||
191 | } | ||
diff --git a/drivers/media/video/m5mols/m5mols_controls.c b/drivers/media/video/m5mols/m5mols_controls.c new file mode 100644 index 000000000000..817c16fec368 --- /dev/null +++ b/drivers/media/video/m5mols/m5mols_controls.c | |||
@@ -0,0 +1,299 @@ | |||
1 | /* | ||
2 | * Controls for M-5MOLS 8M Pixel camera sensor with ISP | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
5 | * Author: HeungJun Kim, riverful.kim@samsung.com | ||
6 | * | ||
7 | * Copyright (C) 2009 Samsung Electronics Co., Ltd. | ||
8 | * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com | ||
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 as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/videodev2.h> | ||
19 | #include <media/v4l2-ctrls.h> | ||
20 | |||
21 | #include "m5mols.h" | ||
22 | #include "m5mols_reg.h" | ||
23 | |||
24 | static struct m5mols_scenemode m5mols_default_scenemode[] = { | ||
25 | [REG_SCENE_NORMAL] = { | ||
26 | REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, | ||
27 | REG_CHROMA_ON, 3, REG_EDGE_ON, 5, | ||
28 | REG_AF_NORMAL, REG_FD_OFF, | ||
29 | REG_MCC_NORMAL, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
30 | 5, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, | ||
31 | }, | ||
32 | [REG_SCENE_PORTRAIT] = { | ||
33 | REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, | ||
34 | REG_CHROMA_ON, 3, REG_EDGE_ON, 4, | ||
35 | REG_AF_NORMAL, BIT_FD_EN | BIT_FD_DRAW_FACE_FRAME, | ||
36 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
37 | 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, | ||
38 | }, | ||
39 | [REG_SCENE_LANDSCAPE] = { | ||
40 | REG_AE_ALL, REG_AE_INDEX_00, REG_AWB_AUTO, 0, | ||
41 | REG_CHROMA_ON, 4, REG_EDGE_ON, 6, | ||
42 | REG_AF_NORMAL, REG_FD_OFF, | ||
43 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
44 | 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, | ||
45 | }, | ||
46 | [REG_SCENE_SPORTS] = { | ||
47 | REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, | ||
48 | REG_CHROMA_ON, 3, REG_EDGE_ON, 5, | ||
49 | REG_AF_NORMAL, REG_FD_OFF, | ||
50 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
51 | 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, | ||
52 | }, | ||
53 | [REG_SCENE_PARTY_INDOOR] = { | ||
54 | REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, | ||
55 | REG_CHROMA_ON, 4, REG_EDGE_ON, 5, | ||
56 | REG_AF_NORMAL, REG_FD_OFF, | ||
57 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
58 | 6, REG_ISO_200, REG_CAP_NONE, REG_WDR_OFF, | ||
59 | }, | ||
60 | [REG_SCENE_BEACH_SNOW] = { | ||
61 | REG_AE_CENTER, REG_AE_INDEX_10_POS, REG_AWB_AUTO, 0, | ||
62 | REG_CHROMA_ON, 4, REG_EDGE_ON, 5, | ||
63 | REG_AF_NORMAL, REG_FD_OFF, | ||
64 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
65 | 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF, | ||
66 | }, | ||
67 | [REG_SCENE_SUNSET] = { | ||
68 | REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET, | ||
69 | REG_AWB_DAYLIGHT, | ||
70 | REG_CHROMA_ON, 3, REG_EDGE_ON, 5, | ||
71 | REG_AF_NORMAL, REG_FD_OFF, | ||
72 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
73 | 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, | ||
74 | }, | ||
75 | [REG_SCENE_DAWN_DUSK] = { | ||
76 | REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET, | ||
77 | REG_AWB_FLUORESCENT_1, | ||
78 | REG_CHROMA_ON, 3, REG_EDGE_ON, 5, | ||
79 | REG_AF_NORMAL, REG_FD_OFF, | ||
80 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
81 | 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, | ||
82 | }, | ||
83 | [REG_SCENE_FALL] = { | ||
84 | REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, | ||
85 | REG_CHROMA_ON, 5, REG_EDGE_ON, 5, | ||
86 | REG_AF_NORMAL, REG_FD_OFF, | ||
87 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
88 | 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, | ||
89 | }, | ||
90 | [REG_SCENE_NIGHT] = { | ||
91 | REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, | ||
92 | REG_CHROMA_ON, 3, REG_EDGE_ON, 5, | ||
93 | REG_AF_NORMAL, REG_FD_OFF, | ||
94 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
95 | 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, | ||
96 | }, | ||
97 | [REG_SCENE_AGAINST_LIGHT] = { | ||
98 | REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, | ||
99 | REG_CHROMA_ON, 3, REG_EDGE_ON, 5, | ||
100 | REG_AF_NORMAL, REG_FD_OFF, | ||
101 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
102 | 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, | ||
103 | }, | ||
104 | [REG_SCENE_FIRE] = { | ||
105 | REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, | ||
106 | REG_CHROMA_ON, 3, REG_EDGE_ON, 5, | ||
107 | REG_AF_NORMAL, REG_FD_OFF, | ||
108 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
109 | 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF, | ||
110 | }, | ||
111 | [REG_SCENE_TEXT] = { | ||
112 | REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, | ||
113 | REG_CHROMA_ON, 3, REG_EDGE_ON, 7, | ||
114 | REG_AF_MACRO, REG_FD_OFF, | ||
115 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
116 | 6, REG_ISO_AUTO, REG_CAP_ANTI_SHAKE, REG_WDR_ON, | ||
117 | }, | ||
118 | [REG_SCENE_CANDLE] = { | ||
119 | REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, | ||
120 | REG_CHROMA_ON, 3, REG_EDGE_ON, 5, | ||
121 | REG_AF_NORMAL, REG_FD_OFF, | ||
122 | REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, | ||
123 | 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, | ||
124 | }, | ||
125 | }; | ||
126 | |||
127 | /** | ||
128 | * m5mols_do_scenemode() - Change current scenemode | ||
129 | * @mode: Desired mode of the scenemode | ||
130 | * | ||
131 | * WARNING: The execution order is important. Do not change the order. | ||
132 | */ | ||
133 | int m5mols_do_scenemode(struct m5mols_info *info, u32 mode) | ||
134 | { | ||
135 | struct v4l2_subdev *sd = &info->sd; | ||
136 | struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode]; | ||
137 | int ret; | ||
138 | |||
139 | if (mode > REG_SCENE_CANDLE) | ||
140 | return -EINVAL; | ||
141 | |||
142 | ret = m5mols_lock_3a(info, false); | ||
143 | if (!ret) | ||
144 | ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode); | ||
145 | if (!ret) | ||
146 | ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode); | ||
147 | if (!ret) | ||
148 | ret = m5mols_write(sd, AE_MODE, scenemode.metering); | ||
149 | if (!ret) | ||
150 | ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias); | ||
151 | if (!ret) | ||
152 | ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode); | ||
153 | if (!ret) | ||
154 | ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset); | ||
155 | if (!ret) | ||
156 | ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en); | ||
157 | if (!ret) | ||
158 | ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl); | ||
159 | if (!ret) | ||
160 | ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en); | ||
161 | if (!ret) | ||
162 | ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl); | ||
163 | if (!ret && is_available_af(info)) | ||
164 | ret = m5mols_write(sd, AF_MODE, scenemode.af_range); | ||
165 | if (!ret && is_available_af(info)) | ||
166 | ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode); | ||
167 | if (!ret) | ||
168 | ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone); | ||
169 | if (!ret) | ||
170 | ret = m5mols_write(sd, AE_ISO, scenemode.iso); | ||
171 | if (!ret) | ||
172 | ret = m5mols_mode(info, REG_CAPTURE); | ||
173 | if (!ret) | ||
174 | ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr); | ||
175 | if (!ret) | ||
176 | ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc); | ||
177 | if (!ret) | ||
178 | ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light); | ||
179 | if (!ret) | ||
180 | ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash); | ||
181 | if (!ret) | ||
182 | ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode); | ||
183 | if (!ret) | ||
184 | ret = m5mols_mode(info, REG_MONITOR); | ||
185 | |||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | static int m5mols_lock_ae(struct m5mols_info *info, bool lock) | ||
190 | { | ||
191 | int ret = 0; | ||
192 | |||
193 | if (info->lock_ae != lock) | ||
194 | ret = m5mols_write(&info->sd, AE_LOCK, | ||
195 | lock ? REG_AE_LOCK : REG_AE_UNLOCK); | ||
196 | if (!ret) | ||
197 | info->lock_ae = lock; | ||
198 | |||
199 | return ret; | ||
200 | } | ||
201 | |||
202 | static int m5mols_lock_awb(struct m5mols_info *info, bool lock) | ||
203 | { | ||
204 | int ret = 0; | ||
205 | |||
206 | if (info->lock_awb != lock) | ||
207 | ret = m5mols_write(&info->sd, AWB_LOCK, | ||
208 | lock ? REG_AWB_LOCK : REG_AWB_UNLOCK); | ||
209 | if (!ret) | ||
210 | info->lock_awb = lock; | ||
211 | |||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | /* m5mols_lock_3a() - Lock 3A(Auto Exposure, Auto Whitebalance, Auto Focus) */ | ||
216 | int m5mols_lock_3a(struct m5mols_info *info, bool lock) | ||
217 | { | ||
218 | int ret; | ||
219 | |||
220 | ret = m5mols_lock_ae(info, lock); | ||
221 | if (!ret) | ||
222 | ret = m5mols_lock_awb(info, lock); | ||
223 | /* Don't need to handle unlocking AF */ | ||
224 | if (!ret && is_available_af(info) && lock) | ||
225 | ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP); | ||
226 | |||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | /* m5mols_set_ctrl() - The main s_ctrl function called by m5mols_set_ctrl() */ | ||
231 | int m5mols_set_ctrl(struct v4l2_ctrl *ctrl) | ||
232 | { | ||
233 | struct v4l2_subdev *sd = to_sd(ctrl); | ||
234 | struct m5mols_info *info = to_m5mols(sd); | ||
235 | int ret; | ||
236 | |||
237 | switch (ctrl->id) { | ||
238 | case V4L2_CID_ZOOM_ABSOLUTE: | ||
239 | return m5mols_write(sd, MON_ZOOM, ctrl->val); | ||
240 | |||
241 | case V4L2_CID_EXPOSURE_AUTO: | ||
242 | ret = m5mols_lock_ae(info, | ||
243 | ctrl->val == V4L2_EXPOSURE_AUTO ? false : true); | ||
244 | if (!ret && ctrl->val == V4L2_EXPOSURE_AUTO) | ||
245 | ret = m5mols_write(sd, AE_MODE, REG_AE_ALL); | ||
246 | if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL) { | ||
247 | int val = info->exposure->val; | ||
248 | ret = m5mols_write(sd, AE_MODE, REG_AE_OFF); | ||
249 | if (!ret) | ||
250 | ret = m5mols_write(sd, AE_MAN_GAIN_MON, val); | ||
251 | if (!ret) | ||
252 | ret = m5mols_write(sd, AE_MAN_GAIN_CAP, val); | ||
253 | } | ||
254 | return ret; | ||
255 | |||
256 | case V4L2_CID_AUTO_WHITE_BALANCE: | ||
257 | ret = m5mols_lock_awb(info, ctrl->val ? false : true); | ||
258 | if (!ret) | ||
259 | ret = m5mols_write(sd, AWB_MODE, ctrl->val ? | ||
260 | REG_AWB_AUTO : REG_AWB_PRESET); | ||
261 | return ret; | ||
262 | |||
263 | case V4L2_CID_SATURATION: | ||
264 | ret = m5mols_write(sd, MON_CHROMA_LVL, ctrl->val); | ||
265 | if (!ret) | ||
266 | ret = m5mols_write(sd, MON_CHROMA_EN, REG_CHROMA_ON); | ||
267 | return ret; | ||
268 | |||
269 | case V4L2_CID_COLORFX: | ||
270 | /* | ||
271 | * This control uses two kinds of registers: normal & color. | ||
272 | * The normal effect belongs to category 1, while the color | ||
273 | * one belongs to category 2. | ||
274 | * | ||
275 | * The normal effect uses one register: CAT1_EFFECT. | ||
276 | * The color effect uses three registers: | ||
277 | * CAT2_COLOR_EFFECT, CAT2_CFIXR, CAT2_CFIXB. | ||
278 | */ | ||
279 | ret = m5mols_write(sd, PARM_EFFECT, | ||
280 | ctrl->val == V4L2_COLORFX_NEGATIVE ? REG_EFFECT_NEGA : | ||
281 | ctrl->val == V4L2_COLORFX_EMBOSS ? REG_EFFECT_EMBOSS : | ||
282 | REG_EFFECT_OFF); | ||
283 | if (!ret) | ||
284 | ret = m5mols_write(sd, MON_EFFECT, | ||
285 | ctrl->val == V4L2_COLORFX_SEPIA ? | ||
286 | REG_COLOR_EFFECT_ON : REG_COLOR_EFFECT_OFF); | ||
287 | if (!ret) | ||
288 | ret = m5mols_write(sd, MON_CFIXR, | ||
289 | ctrl->val == V4L2_COLORFX_SEPIA ? | ||
290 | REG_CFIXR_SEPIA : 0); | ||
291 | if (!ret) | ||
292 | ret = m5mols_write(sd, MON_CFIXB, | ||
293 | ctrl->val == V4L2_COLORFX_SEPIA ? | ||
294 | REG_CFIXB_SEPIA : 0); | ||
295 | return ret; | ||
296 | } | ||
297 | |||
298 | return -EINVAL; | ||
299 | } | ||
diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c new file mode 100644 index 000000000000..76eac26e84ae --- /dev/null +++ b/drivers/media/video/m5mols/m5mols_core.c | |||
@@ -0,0 +1,1004 @@ | |||
1 | /* | ||
2 | * Driver for M-5MOLS 8M Pixel camera sensor with ISP | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
5 | * Author: HeungJun Kim, riverful.kim@samsung.com | ||
6 | * | ||
7 | * Copyright (C) 2009 Samsung Electronics Co., Ltd. | ||
8 | * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com | ||
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 as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/version.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/regulator/consumer.h> | ||
24 | #include <linux/videodev2.h> | ||
25 | #include <media/v4l2-ctrls.h> | ||
26 | #include <media/v4l2-device.h> | ||
27 | #include <media/v4l2-subdev.h> | ||
28 | #include <media/m5mols.h> | ||
29 | |||
30 | #include "m5mols.h" | ||
31 | #include "m5mols_reg.h" | ||
32 | |||
33 | int m5mols_debug; | ||
34 | module_param(m5mols_debug, int, 0644); | ||
35 | |||
36 | #define MODULE_NAME "M5MOLS" | ||
37 | #define M5MOLS_I2C_CHECK_RETRY 500 | ||
38 | |||
39 | /* The regulator consumer names for external voltage regulators */ | ||
40 | static struct regulator_bulk_data supplies[] = { | ||
41 | { | ||
42 | .supply = "core", /* ARM core power, 1.2V */ | ||
43 | }, { | ||
44 | .supply = "dig_18", /* digital power 1, 1.8V */ | ||
45 | }, { | ||
46 | .supply = "d_sensor", /* sensor power 1, 1.8V */ | ||
47 | }, { | ||
48 | .supply = "dig_28", /* digital power 2, 2.8V */ | ||
49 | }, { | ||
50 | .supply = "a_sensor", /* analog power */ | ||
51 | }, { | ||
52 | .supply = "dig_12", /* digital power 3, 1.2V */ | ||
53 | }, | ||
54 | }; | ||
55 | |||
56 | static struct v4l2_mbus_framefmt m5mols_default_ffmt[M5MOLS_RESTYPE_MAX] = { | ||
57 | [M5MOLS_RESTYPE_MONITOR] = { | ||
58 | .width = 1920, | ||
59 | .height = 1080, | ||
60 | .code = V4L2_MBUS_FMT_VYUY8_2X8, | ||
61 | .field = V4L2_FIELD_NONE, | ||
62 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
63 | }, | ||
64 | [M5MOLS_RESTYPE_CAPTURE] = { | ||
65 | .width = 1920, | ||
66 | .height = 1080, | ||
67 | .code = V4L2_MBUS_FMT_JPEG_1X8, | ||
68 | .field = V4L2_FIELD_NONE, | ||
69 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
70 | }, | ||
71 | }; | ||
72 | #define SIZE_DEFAULT_FFMT ARRAY_SIZE(m5mols_default_ffmt) | ||
73 | |||
74 | static const struct m5mols_resolution m5mols_reg_res[] = { | ||
75 | { 0x01, M5MOLS_RESTYPE_MONITOR, 128, 96 }, /* SUB-QCIF */ | ||
76 | { 0x03, M5MOLS_RESTYPE_MONITOR, 160, 120 }, /* QQVGA */ | ||
77 | { 0x05, M5MOLS_RESTYPE_MONITOR, 176, 144 }, /* QCIF */ | ||
78 | { 0x06, M5MOLS_RESTYPE_MONITOR, 176, 176 }, | ||
79 | { 0x08, M5MOLS_RESTYPE_MONITOR, 240, 320 }, /* QVGA */ | ||
80 | { 0x09, M5MOLS_RESTYPE_MONITOR, 320, 240 }, /* QVGA */ | ||
81 | { 0x0c, M5MOLS_RESTYPE_MONITOR, 240, 400 }, /* WQVGA */ | ||
82 | { 0x0d, M5MOLS_RESTYPE_MONITOR, 400, 240 }, /* WQVGA */ | ||
83 | { 0x0e, M5MOLS_RESTYPE_MONITOR, 352, 288 }, /* CIF */ | ||
84 | { 0x13, M5MOLS_RESTYPE_MONITOR, 480, 360 }, | ||
85 | { 0x15, M5MOLS_RESTYPE_MONITOR, 640, 360 }, /* qHD */ | ||
86 | { 0x17, M5MOLS_RESTYPE_MONITOR, 640, 480 }, /* VGA */ | ||
87 | { 0x18, M5MOLS_RESTYPE_MONITOR, 720, 480 }, | ||
88 | { 0x1a, M5MOLS_RESTYPE_MONITOR, 800, 480 }, /* WVGA */ | ||
89 | { 0x1f, M5MOLS_RESTYPE_MONITOR, 800, 600 }, /* SVGA */ | ||
90 | { 0x21, M5MOLS_RESTYPE_MONITOR, 1280, 720 }, /* HD */ | ||
91 | { 0x25, M5MOLS_RESTYPE_MONITOR, 1920, 1080 }, /* 1080p */ | ||
92 | { 0x29, M5MOLS_RESTYPE_MONITOR, 3264, 2448 }, /* 2.63fps 8M */ | ||
93 | { 0x39, M5MOLS_RESTYPE_MONITOR, 800, 602 }, /* AHS_MON debug */ | ||
94 | |||
95 | { 0x02, M5MOLS_RESTYPE_CAPTURE, 320, 240 }, /* QVGA */ | ||
96 | { 0x04, M5MOLS_RESTYPE_CAPTURE, 400, 240 }, /* WQVGA */ | ||
97 | { 0x07, M5MOLS_RESTYPE_CAPTURE, 480, 360 }, | ||
98 | { 0x08, M5MOLS_RESTYPE_CAPTURE, 640, 360 }, /* qHD */ | ||
99 | { 0x09, M5MOLS_RESTYPE_CAPTURE, 640, 480 }, /* VGA */ | ||
100 | { 0x0a, M5MOLS_RESTYPE_CAPTURE, 800, 480 }, /* WVGA */ | ||
101 | { 0x10, M5MOLS_RESTYPE_CAPTURE, 1280, 720 }, /* HD */ | ||
102 | { 0x14, M5MOLS_RESTYPE_CAPTURE, 1280, 960 }, /* 1M */ | ||
103 | { 0x17, M5MOLS_RESTYPE_CAPTURE, 1600, 1200 }, /* 2M */ | ||
104 | { 0x19, M5MOLS_RESTYPE_CAPTURE, 1920, 1080 }, /* Full-HD */ | ||
105 | { 0x1a, M5MOLS_RESTYPE_CAPTURE, 2048, 1152 }, /* 3Mega */ | ||
106 | { 0x1b, M5MOLS_RESTYPE_CAPTURE, 2048, 1536 }, | ||
107 | { 0x1c, M5MOLS_RESTYPE_CAPTURE, 2560, 1440 }, /* 4Mega */ | ||
108 | { 0x1d, M5MOLS_RESTYPE_CAPTURE, 2560, 1536 }, | ||
109 | { 0x1f, M5MOLS_RESTYPE_CAPTURE, 2560, 1920 }, /* 5Mega */ | ||
110 | { 0x21, M5MOLS_RESTYPE_CAPTURE, 3264, 1836 }, /* 6Mega */ | ||
111 | { 0x22, M5MOLS_RESTYPE_CAPTURE, 3264, 1960 }, | ||
112 | { 0x25, M5MOLS_RESTYPE_CAPTURE, 3264, 2448 }, /* 8Mega */ | ||
113 | }; | ||
114 | |||
115 | /** | ||
116 | * m5mols_swap_byte - an byte array to integer conversion function | ||
117 | * @size: size in bytes of I2C packet defined in the M-5MOLS datasheet | ||
118 | * | ||
119 | * Convert I2C data byte array with performing any required byte | ||
120 | * reordering to assure proper values for each data type, regardless | ||
121 | * of the architecture endianness. | ||
122 | */ | ||
123 | static u32 m5mols_swap_byte(u8 *data, u8 length) | ||
124 | { | ||
125 | if (length == 1) | ||
126 | return *data; | ||
127 | else if (length == 2) | ||
128 | return be16_to_cpu(*((u16 *)data)); | ||
129 | else | ||
130 | return be32_to_cpu(*((u32 *)data)); | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * m5mols_read - I2C read function | ||
135 | * @reg: combination of size, category and command for the I2C packet | ||
136 | * @val: read value | ||
137 | */ | ||
138 | int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val) | ||
139 | { | ||
140 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
141 | u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1]; | ||
142 | u8 size = I2C_SIZE(reg); | ||
143 | u8 category = I2C_CATEGORY(reg); | ||
144 | u8 cmd = I2C_COMMAND(reg); | ||
145 | struct i2c_msg msg[2]; | ||
146 | u8 wbuf[5]; | ||
147 | int ret; | ||
148 | |||
149 | if (!client->adapter) | ||
150 | return -ENODEV; | ||
151 | |||
152 | if (size != 1 && size != 2 && size != 4) { | ||
153 | v4l2_err(sd, "Wrong data size\n"); | ||
154 | return -EINVAL; | ||
155 | } | ||
156 | |||
157 | msg[0].addr = client->addr; | ||
158 | msg[0].flags = 0; | ||
159 | msg[0].len = 5; | ||
160 | msg[0].buf = wbuf; | ||
161 | wbuf[0] = 5; | ||
162 | wbuf[1] = M5MOLS_BYTE_READ; | ||
163 | wbuf[2] = category; | ||
164 | wbuf[3] = cmd; | ||
165 | wbuf[4] = size; | ||
166 | |||
167 | msg[1].addr = client->addr; | ||
168 | msg[1].flags = I2C_M_RD; | ||
169 | msg[1].len = size + 1; | ||
170 | msg[1].buf = rbuf; | ||
171 | |||
172 | /* minimum stabilization time */ | ||
173 | usleep_range(200, 200); | ||
174 | |||
175 | ret = i2c_transfer(client->adapter, msg, 2); | ||
176 | if (ret < 0) { | ||
177 | v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n", | ||
178 | size, category, cmd, ret); | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | *val = m5mols_swap_byte(&rbuf[1], size); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * m5mols_write - I2C command write function | ||
189 | * @reg: combination of size, category and command for the I2C packet | ||
190 | * @val: value to write | ||
191 | */ | ||
192 | int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) | ||
193 | { | ||
194 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
195 | u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4]; | ||
196 | u8 category = I2C_CATEGORY(reg); | ||
197 | u8 cmd = I2C_COMMAND(reg); | ||
198 | u8 size = I2C_SIZE(reg); | ||
199 | u32 *buf = (u32 *)&wbuf[4]; | ||
200 | struct i2c_msg msg[1]; | ||
201 | int ret; | ||
202 | |||
203 | if (!client->adapter) | ||
204 | return -ENODEV; | ||
205 | |||
206 | if (size != 1 && size != 2 && size != 4) { | ||
207 | v4l2_err(sd, "Wrong data size\n"); | ||
208 | return -EINVAL; | ||
209 | } | ||
210 | |||
211 | msg->addr = client->addr; | ||
212 | msg->flags = 0; | ||
213 | msg->len = (u16)size + 4; | ||
214 | msg->buf = wbuf; | ||
215 | wbuf[0] = size + 4; | ||
216 | wbuf[1] = M5MOLS_BYTE_WRITE; | ||
217 | wbuf[2] = category; | ||
218 | wbuf[3] = cmd; | ||
219 | |||
220 | *buf = m5mols_swap_byte((u8 *)&val, size); | ||
221 | |||
222 | usleep_range(200, 200); | ||
223 | |||
224 | ret = i2c_transfer(client->adapter, msg, 1); | ||
225 | if (ret < 0) { | ||
226 | v4l2_err(sd, "write failed: size:%d cat:%02x cmd:%02x. %d\n", | ||
227 | size, category, cmd, ret); | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 mask) | ||
235 | { | ||
236 | u32 busy, i; | ||
237 | int ret; | ||
238 | |||
239 | for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) { | ||
240 | ret = m5mols_read(sd, I2C_REG(category, cmd, 1), &busy); | ||
241 | if (ret < 0) | ||
242 | return ret; | ||
243 | if ((busy & mask) == mask) | ||
244 | return 0; | ||
245 | } | ||
246 | return -EBUSY; | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts | ||
251 | * | ||
252 | * Before writing desired interrupt value the INT_FACTOR register should | ||
253 | * be read to clear pending interrupts. | ||
254 | */ | ||
255 | int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg) | ||
256 | { | ||
257 | struct m5mols_info *info = to_m5mols(sd); | ||
258 | u32 mask = is_available_af(info) ? REG_INT_AF : 0; | ||
259 | u32 dummy; | ||
260 | int ret; | ||
261 | |||
262 | ret = m5mols_read(sd, SYSTEM_INT_FACTOR, &dummy); | ||
263 | if (!ret) | ||
264 | ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask); | ||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * m5mols_reg_mode - Write the mode and check busy status | ||
270 | * | ||
271 | * It always accompanies a little delay changing the M-5MOLS mode, so it is | ||
272 | * needed checking current busy status to guarantee right mode. | ||
273 | */ | ||
274 | static int m5mols_reg_mode(struct v4l2_subdev *sd, u32 mode) | ||
275 | { | ||
276 | int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode); | ||
277 | |||
278 | return ret ? ret : m5mols_busy(sd, CAT_SYSTEM, CAT0_SYSMODE, mode); | ||
279 | } | ||
280 | |||
281 | /** | ||
282 | * m5mols_mode - manage the M-5MOLS's mode | ||
283 | * @mode: the required operation mode | ||
284 | * | ||
285 | * The commands of M-5MOLS are grouped into specific modes. Each functionality | ||
286 | * can be guaranteed only when the sensor is operating in mode which which | ||
287 | * a command belongs to. | ||
288 | */ | ||
289 | int m5mols_mode(struct m5mols_info *info, u32 mode) | ||
290 | { | ||
291 | struct v4l2_subdev *sd = &info->sd; | ||
292 | int ret = -EINVAL; | ||
293 | u32 reg; | ||
294 | |||
295 | if (mode < REG_PARAMETER && mode > REG_CAPTURE) | ||
296 | return ret; | ||
297 | |||
298 | ret = m5mols_read(sd, SYSTEM_SYSMODE, ®); | ||
299 | if ((!ret && reg == mode) || ret) | ||
300 | return ret; | ||
301 | |||
302 | switch (reg) { | ||
303 | case REG_PARAMETER: | ||
304 | ret = m5mols_reg_mode(sd, REG_MONITOR); | ||
305 | if (!ret && mode == REG_MONITOR) | ||
306 | break; | ||
307 | if (!ret) | ||
308 | ret = m5mols_reg_mode(sd, REG_CAPTURE); | ||
309 | break; | ||
310 | |||
311 | case REG_MONITOR: | ||
312 | if (mode == REG_PARAMETER) { | ||
313 | ret = m5mols_reg_mode(sd, REG_PARAMETER); | ||
314 | break; | ||
315 | } | ||
316 | |||
317 | ret = m5mols_reg_mode(sd, REG_CAPTURE); | ||
318 | break; | ||
319 | |||
320 | case REG_CAPTURE: | ||
321 | ret = m5mols_reg_mode(sd, REG_MONITOR); | ||
322 | if (!ret && mode == REG_MONITOR) | ||
323 | break; | ||
324 | if (!ret) | ||
325 | ret = m5mols_reg_mode(sd, REG_PARAMETER); | ||
326 | break; | ||
327 | |||
328 | default: | ||
329 | v4l2_warn(sd, "Wrong mode: %d\n", mode); | ||
330 | } | ||
331 | |||
332 | if (!ret) | ||
333 | info->mode = mode; | ||
334 | |||
335 | return ret; | ||
336 | } | ||
337 | |||
338 | /** | ||
339 | * m5mols_get_version - retrieve full revisions information of M-5MOLS | ||
340 | * | ||
341 | * The version information includes revisions of hardware and firmware, | ||
342 | * AutoFocus alghorithm version and the version string. | ||
343 | */ | ||
344 | static int m5mols_get_version(struct v4l2_subdev *sd) | ||
345 | { | ||
346 | struct m5mols_info *info = to_m5mols(sd); | ||
347 | union { | ||
348 | struct m5mols_version ver; | ||
349 | u8 bytes[VERSION_SIZE]; | ||
350 | } version; | ||
351 | u32 *value; | ||
352 | u8 cmd = CAT0_VER_CUSTOMER; | ||
353 | int ret; | ||
354 | |||
355 | do { | ||
356 | value = (u32 *)&version.bytes[cmd]; | ||
357 | ret = m5mols_read(sd, SYSTEM_CMD(cmd), value); | ||
358 | if (ret) | ||
359 | return ret; | ||
360 | } while (cmd++ != CAT0_VER_AWB); | ||
361 | |||
362 | do { | ||
363 | value = (u32 *)&version.bytes[cmd]; | ||
364 | ret = m5mols_read(sd, SYSTEM_VER_STRING, value); | ||
365 | if (ret) | ||
366 | return ret; | ||
367 | if (cmd >= VERSION_SIZE - 1) | ||
368 | return -EINVAL; | ||
369 | } while (version.bytes[cmd++]); | ||
370 | |||
371 | value = (u32 *)&version.bytes[cmd]; | ||
372 | ret = m5mols_read(sd, AF_VERSION, value); | ||
373 | if (ret) | ||
374 | return ret; | ||
375 | |||
376 | /* store version information swapped for being readable */ | ||
377 | info->ver = version.ver; | ||
378 | info->ver.fw = be16_to_cpu(info->ver.fw); | ||
379 | info->ver.hw = be16_to_cpu(info->ver.hw); | ||
380 | info->ver.param = be16_to_cpu(info->ver.param); | ||
381 | info->ver.awb = be16_to_cpu(info->ver.awb); | ||
382 | |||
383 | v4l2_info(sd, "Manufacturer\t[%s]\n", | ||
384 | is_manufacturer(info, REG_SAMSUNG_ELECTRO) ? | ||
385 | "Samsung Electro-Machanics" : | ||
386 | is_manufacturer(info, REG_SAMSUNG_OPTICS) ? | ||
387 | "Samsung Fiber-Optics" : | ||
388 | is_manufacturer(info, REG_SAMSUNG_TECHWIN) ? | ||
389 | "Samsung Techwin" : "None"); | ||
390 | v4l2_info(sd, "Customer/Project\t[0x%02x/0x%02x]\n", | ||
391 | info->ver.customer, info->ver.project); | ||
392 | |||
393 | if (!is_available_af(info)) | ||
394 | v4l2_info(sd, "No support Auto Focus on this firmware\n"); | ||
395 | |||
396 | return ret; | ||
397 | } | ||
398 | |||
399 | /** | ||
400 | * __find_restype - Lookup M-5MOLS resolution type according to pixel code | ||
401 | * @code: pixel code | ||
402 | */ | ||
403 | static enum m5mols_restype __find_restype(enum v4l2_mbus_pixelcode code) | ||
404 | { | ||
405 | enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR; | ||
406 | |||
407 | do { | ||
408 | if (code == m5mols_default_ffmt[type].code) | ||
409 | return type; | ||
410 | } while (type++ != SIZE_DEFAULT_FFMT); | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | /** | ||
416 | * __find_resolution - Lookup preset and type of M-5MOLS's resolution | ||
417 | * @mf: pixel format to find/negotiate the resolution preset for | ||
418 | * @type: M-5MOLS resolution type | ||
419 | * @resolution: M-5MOLS resolution preset register value | ||
420 | * | ||
421 | * Find nearest resolution matching resolution preset and adjust mf | ||
422 | * to supported values. | ||
423 | */ | ||
424 | static int __find_resolution(struct v4l2_subdev *sd, | ||
425 | struct v4l2_mbus_framefmt *mf, | ||
426 | enum m5mols_restype *type, | ||
427 | u32 *resolution) | ||
428 | { | ||
429 | const struct m5mols_resolution *fsize = &m5mols_reg_res[0]; | ||
430 | const struct m5mols_resolution *match = NULL; | ||
431 | enum m5mols_restype stype = __find_restype(mf->code); | ||
432 | int i = ARRAY_SIZE(m5mols_reg_res); | ||
433 | unsigned int min_err = ~0; | ||
434 | |||
435 | while (i--) { | ||
436 | int err; | ||
437 | if (stype == fsize->type) { | ||
438 | err = abs(fsize->width - mf->width) | ||
439 | + abs(fsize->height - mf->height); | ||
440 | |||
441 | if (err < min_err) { | ||
442 | min_err = err; | ||
443 | match = fsize; | ||
444 | } | ||
445 | } | ||
446 | fsize++; | ||
447 | } | ||
448 | if (match) { | ||
449 | mf->width = match->width; | ||
450 | mf->height = match->height; | ||
451 | *resolution = match->reg; | ||
452 | *type = stype; | ||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | return -EINVAL; | ||
457 | } | ||
458 | |||
459 | static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info, | ||
460 | struct v4l2_subdev_fh *fh, | ||
461 | enum v4l2_subdev_format_whence which, | ||
462 | enum m5mols_restype type) | ||
463 | { | ||
464 | if (which == V4L2_SUBDEV_FORMAT_TRY) | ||
465 | return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL; | ||
466 | |||
467 | return &info->ffmt[type]; | ||
468 | } | ||
469 | |||
470 | static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | ||
471 | struct v4l2_subdev_format *fmt) | ||
472 | { | ||
473 | struct m5mols_info *info = to_m5mols(sd); | ||
474 | struct v4l2_mbus_framefmt *format; | ||
475 | |||
476 | if (fmt->pad != 0) | ||
477 | return -EINVAL; | ||
478 | |||
479 | format = __find_format(info, fh, fmt->which, info->res_type); | ||
480 | if (!format) | ||
481 | return -EINVAL; | ||
482 | |||
483 | fmt->format = *format; | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | ||
488 | struct v4l2_subdev_format *fmt) | ||
489 | { | ||
490 | struct m5mols_info *info = to_m5mols(sd); | ||
491 | struct v4l2_mbus_framefmt *format = &fmt->format; | ||
492 | struct v4l2_mbus_framefmt *sfmt; | ||
493 | enum m5mols_restype type; | ||
494 | u32 resolution = 0; | ||
495 | int ret; | ||
496 | |||
497 | if (fmt->pad != 0) | ||
498 | return -EINVAL; | ||
499 | |||
500 | ret = __find_resolution(sd, format, &type, &resolution); | ||
501 | if (ret < 0) | ||
502 | return ret; | ||
503 | |||
504 | sfmt = __find_format(info, fh, fmt->which, type); | ||
505 | if (!sfmt) | ||
506 | return 0; | ||
507 | |||
508 | *sfmt = m5mols_default_ffmt[type]; | ||
509 | sfmt->width = format->width; | ||
510 | sfmt->height = format->height; | ||
511 | |||
512 | if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { | ||
513 | info->resolution = resolution; | ||
514 | info->code = format->code; | ||
515 | info->res_type = type; | ||
516 | } | ||
517 | |||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | static int m5mols_enum_mbus_code(struct v4l2_subdev *sd, | ||
522 | struct v4l2_subdev_fh *fh, | ||
523 | struct v4l2_subdev_mbus_code_enum *code) | ||
524 | { | ||
525 | if (!code || code->index >= SIZE_DEFAULT_FFMT) | ||
526 | return -EINVAL; | ||
527 | |||
528 | code->code = m5mols_default_ffmt[code->index].code; | ||
529 | |||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | static struct v4l2_subdev_pad_ops m5mols_pad_ops = { | ||
534 | .enum_mbus_code = m5mols_enum_mbus_code, | ||
535 | .get_fmt = m5mols_get_fmt, | ||
536 | .set_fmt = m5mols_set_fmt, | ||
537 | }; | ||
538 | |||
539 | /** | ||
540 | * m5mols_sync_controls - Apply default scene mode and the current controls | ||
541 | * | ||
542 | * This is used only streaming for syncing between v4l2_ctrl framework and | ||
543 | * m5mols's controls. First, do the scenemode to the sensor, then call | ||
544 | * v4l2_ctrl_handler_setup. It can be same between some commands and | ||
545 | * the scenemode's in the default v4l2_ctrls. But, such commands of control | ||
546 | * should be prior to the scenemode's one. | ||
547 | */ | ||
548 | int m5mols_sync_controls(struct m5mols_info *info) | ||
549 | { | ||
550 | int ret = -EINVAL; | ||
551 | |||
552 | if (!is_ctrl_synced(info)) { | ||
553 | ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL); | ||
554 | if (ret) | ||
555 | return ret; | ||
556 | |||
557 | v4l2_ctrl_handler_setup(&info->handle); | ||
558 | info->ctrl_sync = true; | ||
559 | } | ||
560 | |||
561 | return ret; | ||
562 | } | ||
563 | |||
564 | /** | ||
565 | * m5mols_start_monitor - Start the monitor mode | ||
566 | * | ||
567 | * Before applying the controls setup the resolution and frame rate | ||
568 | * in PARAMETER mode, and then switch over to MONITOR mode. | ||
569 | */ | ||
570 | static int m5mols_start_monitor(struct m5mols_info *info) | ||
571 | { | ||
572 | struct v4l2_subdev *sd = &info->sd; | ||
573 | int ret; | ||
574 | |||
575 | ret = m5mols_mode(info, REG_PARAMETER); | ||
576 | if (!ret) | ||
577 | ret = m5mols_write(sd, PARM_MON_SIZE, info->resolution); | ||
578 | if (!ret) | ||
579 | ret = m5mols_write(sd, PARM_MON_FPS, REG_FPS_30); | ||
580 | if (!ret) | ||
581 | ret = m5mols_mode(info, REG_MONITOR); | ||
582 | if (!ret) | ||
583 | ret = m5mols_sync_controls(info); | ||
584 | |||
585 | return ret; | ||
586 | } | ||
587 | |||
588 | static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) | ||
589 | { | ||
590 | struct m5mols_info *info = to_m5mols(sd); | ||
591 | |||
592 | if (enable) { | ||
593 | int ret = -EINVAL; | ||
594 | |||
595 | if (is_code(info->code, M5MOLS_RESTYPE_MONITOR)) | ||
596 | ret = m5mols_start_monitor(info); | ||
597 | if (is_code(info->code, M5MOLS_RESTYPE_CAPTURE)) | ||
598 | ret = m5mols_start_capture(info); | ||
599 | |||
600 | return ret; | ||
601 | } | ||
602 | |||
603 | return m5mols_mode(info, REG_PARAMETER); | ||
604 | } | ||
605 | |||
606 | static const struct v4l2_subdev_video_ops m5mols_video_ops = { | ||
607 | .s_stream = m5mols_s_stream, | ||
608 | }; | ||
609 | |||
610 | static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl) | ||
611 | { | ||
612 | struct v4l2_subdev *sd = to_sd(ctrl); | ||
613 | struct m5mols_info *info = to_m5mols(sd); | ||
614 | int ret; | ||
615 | |||
616 | info->mode_save = info->mode; | ||
617 | |||
618 | ret = m5mols_mode(info, REG_PARAMETER); | ||
619 | if (!ret) | ||
620 | ret = m5mols_set_ctrl(ctrl); | ||
621 | if (!ret) | ||
622 | ret = m5mols_mode(info, info->mode_save); | ||
623 | |||
624 | return ret; | ||
625 | } | ||
626 | |||
627 | static const struct v4l2_ctrl_ops m5mols_ctrl_ops = { | ||
628 | .s_ctrl = m5mols_s_ctrl, | ||
629 | }; | ||
630 | |||
631 | static int m5mols_sensor_power(struct m5mols_info *info, bool enable) | ||
632 | { | ||
633 | struct v4l2_subdev *sd = &info->sd; | ||
634 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
635 | const struct m5mols_platform_data *pdata = info->pdata; | ||
636 | int ret; | ||
637 | |||
638 | if (enable) { | ||
639 | if (is_powered(info)) | ||
640 | return 0; | ||
641 | |||
642 | if (info->set_power) { | ||
643 | ret = info->set_power(&client->dev, 1); | ||
644 | if (ret) | ||
645 | return ret; | ||
646 | } | ||
647 | |||
648 | ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies); | ||
649 | if (ret) { | ||
650 | info->set_power(&client->dev, 0); | ||
651 | return ret; | ||
652 | } | ||
653 | |||
654 | gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity); | ||
655 | usleep_range(1000, 1000); | ||
656 | info->power = true; | ||
657 | |||
658 | return ret; | ||
659 | } | ||
660 | |||
661 | if (!is_powered(info)) | ||
662 | return 0; | ||
663 | |||
664 | ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies); | ||
665 | if (ret) | ||
666 | return ret; | ||
667 | |||
668 | if (info->set_power) | ||
669 | info->set_power(&client->dev, 0); | ||
670 | |||
671 | gpio_set_value(pdata->gpio_reset, pdata->reset_polarity); | ||
672 | usleep_range(1000, 1000); | ||
673 | info->power = false; | ||
674 | |||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | /* m5mols_update_fw - optional firmware update routine */ | ||
679 | int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd, | ||
680 | int (*set_power)(struct m5mols_info *, bool)) | ||
681 | { | ||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | /** | ||
686 | * m5mols_sensor_armboot - Booting M-5MOLS internal ARM core. | ||
687 | * | ||
688 | * Booting internal ARM core makes the M-5MOLS is ready for getting commands | ||
689 | * with I2C. It's the first thing to be done after it powered up. It must wait | ||
690 | * at least 520ms recommended by M-5MOLS datasheet, after executing arm booting. | ||
691 | */ | ||
692 | static int m5mols_sensor_armboot(struct v4l2_subdev *sd) | ||
693 | { | ||
694 | int ret; | ||
695 | |||
696 | ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT); | ||
697 | if (ret < 0) | ||
698 | return ret; | ||
699 | |||
700 | msleep(520); | ||
701 | |||
702 | ret = m5mols_get_version(sd); | ||
703 | if (!ret) | ||
704 | ret = m5mols_update_fw(sd, m5mols_sensor_power); | ||
705 | if (ret) | ||
706 | return ret; | ||
707 | |||
708 | v4l2_dbg(1, m5mols_debug, sd, "Success ARM Booting\n"); | ||
709 | |||
710 | ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI); | ||
711 | if (!ret) | ||
712 | ret = m5mols_enable_interrupt(sd, REG_INT_AF); | ||
713 | |||
714 | return ret; | ||
715 | } | ||
716 | |||
717 | static int m5mols_init_controls(struct m5mols_info *info) | ||
718 | { | ||
719 | struct v4l2_subdev *sd = &info->sd; | ||
720 | u16 max_exposure; | ||
721 | u16 step_zoom; | ||
722 | int ret; | ||
723 | |||
724 | /* Determine value's range & step of controls for various FW version */ | ||
725 | ret = m5mols_read(sd, AE_MAX_GAIN_MON, (u32 *)&max_exposure); | ||
726 | if (!ret) | ||
727 | step_zoom = is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 31 : 1; | ||
728 | if (ret) | ||
729 | return ret; | ||
730 | |||
731 | v4l2_ctrl_handler_init(&info->handle, 6); | ||
732 | info->autowb = v4l2_ctrl_new_std(&info->handle, | ||
733 | &m5mols_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE, | ||
734 | 0, 1, 1, 0); | ||
735 | info->saturation = v4l2_ctrl_new_std(&info->handle, | ||
736 | &m5mols_ctrl_ops, V4L2_CID_SATURATION, | ||
737 | 1, 5, 1, 3); | ||
738 | info->zoom = v4l2_ctrl_new_std(&info->handle, | ||
739 | &m5mols_ctrl_ops, V4L2_CID_ZOOM_ABSOLUTE, | ||
740 | 1, 70, step_zoom, 1); | ||
741 | info->exposure = v4l2_ctrl_new_std(&info->handle, | ||
742 | &m5mols_ctrl_ops, V4L2_CID_EXPOSURE, | ||
743 | 0, max_exposure, 1, (int)max_exposure/2); | ||
744 | info->colorfx = v4l2_ctrl_new_std_menu(&info->handle, | ||
745 | &m5mols_ctrl_ops, V4L2_CID_COLORFX, | ||
746 | 4, (1 << V4L2_COLORFX_BW), V4L2_COLORFX_NONE); | ||
747 | info->autoexposure = v4l2_ctrl_new_std_menu(&info->handle, | ||
748 | &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, | ||
749 | 1, 0, V4L2_EXPOSURE_MANUAL); | ||
750 | |||
751 | sd->ctrl_handler = &info->handle; | ||
752 | if (info->handle.error) { | ||
753 | v4l2_err(sd, "Failed to initialize controls: %d\n", ret); | ||
754 | v4l2_ctrl_handler_free(&info->handle); | ||
755 | return info->handle.error; | ||
756 | } | ||
757 | |||
758 | v4l2_ctrl_cluster(2, &info->autoexposure); | ||
759 | |||
760 | return 0; | ||
761 | } | ||
762 | |||
763 | /** | ||
764 | * m5mols_s_power - Main sensor power control function | ||
765 | * | ||
766 | * To prevent breaking the lens when the sensor is powered off the Soft-Landing | ||
767 | * algorithm is called where available. The Soft-Landing algorithm availability | ||
768 | * dependends on the firmware provider. | ||
769 | */ | ||
770 | static int m5mols_s_power(struct v4l2_subdev *sd, int on) | ||
771 | { | ||
772 | struct m5mols_info *info = to_m5mols(sd); | ||
773 | int ret; | ||
774 | |||
775 | if (on) { | ||
776 | ret = m5mols_sensor_power(info, true); | ||
777 | if (!ret) | ||
778 | ret = m5mols_sensor_armboot(sd); | ||
779 | if (!ret) | ||
780 | ret = m5mols_init_controls(info); | ||
781 | if (ret) | ||
782 | return ret; | ||
783 | |||
784 | info->ffmt[M5MOLS_RESTYPE_MONITOR] = | ||
785 | m5mols_default_ffmt[M5MOLS_RESTYPE_MONITOR]; | ||
786 | info->ffmt[M5MOLS_RESTYPE_CAPTURE] = | ||
787 | m5mols_default_ffmt[M5MOLS_RESTYPE_CAPTURE]; | ||
788 | return ret; | ||
789 | } | ||
790 | |||
791 | if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) { | ||
792 | ret = m5mols_mode(info, REG_MONITOR); | ||
793 | if (!ret) | ||
794 | ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP); | ||
795 | if (!ret) | ||
796 | ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); | ||
797 | if (!ret) | ||
798 | ret = m5mols_busy(sd, CAT_SYSTEM, CAT0_STATUS, | ||
799 | REG_AF_IDLE); | ||
800 | if (!ret) | ||
801 | v4l2_info(sd, "Success soft-landing lens\n"); | ||
802 | } | ||
803 | |||
804 | ret = m5mols_sensor_power(info, false); | ||
805 | if (!ret) { | ||
806 | v4l2_ctrl_handler_free(&info->handle); | ||
807 | info->ctrl_sync = false; | ||
808 | } | ||
809 | |||
810 | return ret; | ||
811 | } | ||
812 | |||
813 | static int m5mols_log_status(struct v4l2_subdev *sd) | ||
814 | { | ||
815 | struct m5mols_info *info = to_m5mols(sd); | ||
816 | |||
817 | v4l2_ctrl_handler_log_status(&info->handle, sd->name); | ||
818 | |||
819 | return 0; | ||
820 | } | ||
821 | |||
822 | static const struct v4l2_subdev_core_ops m5mols_core_ops = { | ||
823 | .s_power = m5mols_s_power, | ||
824 | .g_ctrl = v4l2_subdev_g_ctrl, | ||
825 | .s_ctrl = v4l2_subdev_s_ctrl, | ||
826 | .queryctrl = v4l2_subdev_queryctrl, | ||
827 | .querymenu = v4l2_subdev_querymenu, | ||
828 | .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, | ||
829 | .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, | ||
830 | .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, | ||
831 | .log_status = m5mols_log_status, | ||
832 | }; | ||
833 | |||
834 | static const struct v4l2_subdev_ops m5mols_ops = { | ||
835 | .core = &m5mols_core_ops, | ||
836 | .pad = &m5mols_pad_ops, | ||
837 | .video = &m5mols_video_ops, | ||
838 | }; | ||
839 | |||
840 | static void m5mols_irq_work(struct work_struct *work) | ||
841 | { | ||
842 | struct m5mols_info *info = | ||
843 | container_of(work, struct m5mols_info, work_irq); | ||
844 | struct v4l2_subdev *sd = &info->sd; | ||
845 | u32 reg; | ||
846 | int ret; | ||
847 | |||
848 | if (!is_powered(info) || | ||
849 | m5mols_read(sd, SYSTEM_INT_FACTOR, &info->interrupt)) | ||
850 | return; | ||
851 | |||
852 | switch (info->interrupt & REG_INT_MASK) { | ||
853 | case REG_INT_AF: | ||
854 | if (!is_available_af(info)) | ||
855 | break; | ||
856 | ret = m5mols_read(sd, AF_STATUS, ®); | ||
857 | v4l2_dbg(2, m5mols_debug, sd, "AF %s\n", | ||
858 | reg == REG_AF_FAIL ? "Failed" : | ||
859 | reg == REG_AF_SUCCESS ? "Success" : | ||
860 | reg == REG_AF_IDLE ? "Idle" : "Busy"); | ||
861 | break; | ||
862 | case REG_INT_CAPTURE: | ||
863 | if (!test_and_set_bit(ST_CAPT_IRQ, &info->flags)) | ||
864 | wake_up_interruptible(&info->irq_waitq); | ||
865 | |||
866 | v4l2_dbg(2, m5mols_debug, sd, "CAPTURE\n"); | ||
867 | break; | ||
868 | default: | ||
869 | v4l2_dbg(2, m5mols_debug, sd, "Undefined: %02x\n", reg); | ||
870 | break; | ||
871 | }; | ||
872 | } | ||
873 | |||
874 | static irqreturn_t m5mols_irq_handler(int irq, void *data) | ||
875 | { | ||
876 | struct v4l2_subdev *sd = data; | ||
877 | struct m5mols_info *info = to_m5mols(sd); | ||
878 | |||
879 | schedule_work(&info->work_irq); | ||
880 | |||
881 | return IRQ_HANDLED; | ||
882 | } | ||
883 | |||
884 | static int __devinit m5mols_probe(struct i2c_client *client, | ||
885 | const struct i2c_device_id *id) | ||
886 | { | ||
887 | const struct m5mols_platform_data *pdata = client->dev.platform_data; | ||
888 | struct m5mols_info *info; | ||
889 | struct v4l2_subdev *sd; | ||
890 | int ret; | ||
891 | |||
892 | if (pdata == NULL) { | ||
893 | dev_err(&client->dev, "No platform data\n"); | ||
894 | return -EINVAL; | ||
895 | } | ||
896 | |||
897 | if (!gpio_is_valid(pdata->gpio_reset)) { | ||
898 | dev_err(&client->dev, "No valid RESET GPIO specified\n"); | ||
899 | return -EINVAL; | ||
900 | } | ||
901 | |||
902 | if (!pdata->irq) { | ||
903 | dev_err(&client->dev, "Interrupt not assigned\n"); | ||
904 | return -EINVAL; | ||
905 | } | ||
906 | |||
907 | info = kzalloc(sizeof(struct m5mols_info), GFP_KERNEL); | ||
908 | if (!info) | ||
909 | return -ENOMEM; | ||
910 | |||
911 | info->pdata = pdata; | ||
912 | info->set_power = pdata->set_power; | ||
913 | |||
914 | ret = gpio_request(pdata->gpio_reset, "M5MOLS_NRST"); | ||
915 | if (ret) { | ||
916 | dev_err(&client->dev, "Failed to request gpio: %d\n", ret); | ||
917 | goto out_free; | ||
918 | } | ||
919 | gpio_direction_output(pdata->gpio_reset, pdata->reset_polarity); | ||
920 | |||
921 | ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), supplies); | ||
922 | if (ret) { | ||
923 | dev_err(&client->dev, "Failed to get regulators: %d\n", ret); | ||
924 | goto out_gpio; | ||
925 | } | ||
926 | |||
927 | sd = &info->sd; | ||
928 | strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); | ||
929 | v4l2_i2c_subdev_init(sd, client, &m5mols_ops); | ||
930 | |||
931 | info->pad.flags = MEDIA_PAD_FL_SOURCE; | ||
932 | ret = media_entity_init(&sd->entity, 1, &info->pad, 0); | ||
933 | if (ret < 0) | ||
934 | goto out_reg; | ||
935 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; | ||
936 | |||
937 | init_waitqueue_head(&info->irq_waitq); | ||
938 | INIT_WORK(&info->work_irq, m5mols_irq_work); | ||
939 | ret = request_irq(pdata->irq, m5mols_irq_handler, | ||
940 | IRQF_TRIGGER_RISING, MODULE_NAME, sd); | ||
941 | if (ret) { | ||
942 | dev_err(&client->dev, "Interrupt request failed: %d\n", ret); | ||
943 | goto out_me; | ||
944 | } | ||
945 | info->res_type = M5MOLS_RESTYPE_MONITOR; | ||
946 | return 0; | ||
947 | out_me: | ||
948 | media_entity_cleanup(&sd->entity); | ||
949 | out_reg: | ||
950 | regulator_bulk_free(ARRAY_SIZE(supplies), supplies); | ||
951 | out_gpio: | ||
952 | gpio_free(pdata->gpio_reset); | ||
953 | out_free: | ||
954 | kfree(info); | ||
955 | return ret; | ||
956 | } | ||
957 | |||
958 | static int __devexit m5mols_remove(struct i2c_client *client) | ||
959 | { | ||
960 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
961 | struct m5mols_info *info = to_m5mols(sd); | ||
962 | |||
963 | v4l2_device_unregister_subdev(sd); | ||
964 | free_irq(info->pdata->irq, sd); | ||
965 | |||
966 | regulator_bulk_free(ARRAY_SIZE(supplies), supplies); | ||
967 | gpio_free(info->pdata->gpio_reset); | ||
968 | media_entity_cleanup(&sd->entity); | ||
969 | kfree(info); | ||
970 | return 0; | ||
971 | } | ||
972 | |||
973 | static const struct i2c_device_id m5mols_id[] = { | ||
974 | { MODULE_NAME, 0 }, | ||
975 | { }, | ||
976 | }; | ||
977 | MODULE_DEVICE_TABLE(i2c, m5mols_id); | ||
978 | |||
979 | static struct i2c_driver m5mols_i2c_driver = { | ||
980 | .driver = { | ||
981 | .name = MODULE_NAME, | ||
982 | }, | ||
983 | .probe = m5mols_probe, | ||
984 | .remove = __devexit_p(m5mols_remove), | ||
985 | .id_table = m5mols_id, | ||
986 | }; | ||
987 | |||
988 | static int __init m5mols_mod_init(void) | ||
989 | { | ||
990 | return i2c_add_driver(&m5mols_i2c_driver); | ||
991 | } | ||
992 | |||
993 | static void __exit m5mols_mod_exit(void) | ||
994 | { | ||
995 | i2c_del_driver(&m5mols_i2c_driver); | ||
996 | } | ||
997 | |||
998 | module_init(m5mols_mod_init); | ||
999 | module_exit(m5mols_mod_exit); | ||
1000 | |||
1001 | MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>"); | ||
1002 | MODULE_AUTHOR("Dongsoo Kim <dongsoo45.kim@samsung.com>"); | ||
1003 | MODULE_DESCRIPTION("Fujitsu M-5MOLS 8M Pixel camera driver"); | ||
1004 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/m5mols/m5mols_reg.h b/drivers/media/video/m5mols/m5mols_reg.h new file mode 100644 index 000000000000..b83e36fc6ac6 --- /dev/null +++ b/drivers/media/video/m5mols/m5mols_reg.h | |||
@@ -0,0 +1,399 @@ | |||
1 | /* | ||
2 | * Register map for M-5MOLS 8M Pixel camera sensor with ISP | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
5 | * Author: HeungJun Kim, riverful.kim@samsung.com | ||
6 | * | ||
7 | * Copyright (C) 2009 Samsung Electronics Co., Ltd. | ||
8 | * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com | ||
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 as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifndef M5MOLS_REG_H | ||
17 | #define M5MOLS_REG_H | ||
18 | |||
19 | #define M5MOLS_I2C_MAX_SIZE 4 | ||
20 | #define M5MOLS_BYTE_READ 0x01 | ||
21 | #define M5MOLS_BYTE_WRITE 0x02 | ||
22 | |||
23 | #define I2C_CATEGORY(__cat) ((__cat >> 16) & 0xff) | ||
24 | #define I2C_COMMAND(__comm) ((__comm >> 8) & 0xff) | ||
25 | #define I2C_SIZE(__reg_s) ((__reg_s) & 0xff) | ||
26 | #define I2C_REG(__cat, __cmd, __reg_s) ((__cat << 16) | (__cmd << 8) | __reg_s) | ||
27 | |||
28 | /* | ||
29 | * Category section register | ||
30 | * | ||
31 | * The category means set including relevant command of M-5MOLS. | ||
32 | */ | ||
33 | #define CAT_SYSTEM 0x00 | ||
34 | #define CAT_PARAM 0x01 | ||
35 | #define CAT_MONITOR 0x02 | ||
36 | #define CAT_AE 0x03 | ||
37 | #define CAT_WB 0x06 | ||
38 | #define CAT_EXIF 0x07 | ||
39 | #define CAT_FD 0x09 | ||
40 | #define CAT_LENS 0x0a | ||
41 | #define CAT_CAPT_PARM 0x0b | ||
42 | #define CAT_CAPT_CTRL 0x0c | ||
43 | #define CAT_FLASH 0x0f /* related to FW, revisions, booting */ | ||
44 | |||
45 | /* | ||
46 | * Category 0 - SYSTEM mode | ||
47 | * | ||
48 | * The SYSTEM mode in the M-5MOLS means area available to handle with the whole | ||
49 | * & all-round system of sensor. It deals with version/interrupt/setting mode & | ||
50 | * even sensor's status. Especially, the M-5MOLS sensor with ISP varies by | ||
51 | * packaging & manufacturer, even the customer and project code. And the | ||
52 | * function details may vary among them. The version information helps to | ||
53 | * determine what methods shall be used in the driver. | ||
54 | * | ||
55 | * There is many registers between customer version address and awb one. For | ||
56 | * more specific contents, see definition if file m5mols.h. | ||
57 | */ | ||
58 | #define CAT0_VER_CUSTOMER 0x00 /* customer version */ | ||
59 | #define CAT0_VER_AWB 0x09 /* Auto WB version */ | ||
60 | #define CAT0_VER_STRING 0x0a /* string including M-5MOLS */ | ||
61 | #define CAT0_SYSMODE 0x0b /* SYSTEM mode register */ | ||
62 | #define CAT0_STATUS 0x0c /* SYSTEM mode status register */ | ||
63 | #define CAT0_INT_FACTOR 0x10 /* interrupt pending register */ | ||
64 | #define CAT0_INT_ENABLE 0x11 /* interrupt enable register */ | ||
65 | |||
66 | #define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, CAT0_SYSMODE, 1) | ||
67 | #define REG_SYSINIT 0x00 /* SYSTEM mode */ | ||
68 | #define REG_PARAMETER 0x01 /* PARAMETER mode */ | ||
69 | #define REG_MONITOR 0x02 /* MONITOR mode */ | ||
70 | #define REG_CAPTURE 0x03 /* CAPTURE mode */ | ||
71 | |||
72 | #define SYSTEM_CMD(__cmd) I2C_REG(CAT_SYSTEM, cmd, 1) | ||
73 | #define SYSTEM_VER_STRING I2C_REG(CAT_SYSTEM, CAT0_VER_STRING, 1) | ||
74 | #define REG_SAMSUNG_ELECTRO "SE" /* Samsung Electro-Mechanics */ | ||
75 | #define REG_SAMSUNG_OPTICS "OP" /* Samsung Fiber-Optics */ | ||
76 | #define REG_SAMSUNG_TECHWIN "TB" /* Samsung Techwin */ | ||
77 | |||
78 | #define SYSTEM_INT_FACTOR I2C_REG(CAT_SYSTEM, CAT0_INT_FACTOR, 1) | ||
79 | #define SYSTEM_INT_ENABLE I2C_REG(CAT_SYSTEM, CAT0_INT_ENABLE, 1) | ||
80 | #define REG_INT_MODE (1 << 0) | ||
81 | #define REG_INT_AF (1 << 1) | ||
82 | #define REG_INT_ZOOM (1 << 2) | ||
83 | #define REG_INT_CAPTURE (1 << 3) | ||
84 | #define REG_INT_FRAMESYNC (1 << 4) | ||
85 | #define REG_INT_FD (1 << 5) | ||
86 | #define REG_INT_LENS_INIT (1 << 6) | ||
87 | #define REG_INT_SOUND (1 << 7) | ||
88 | #define REG_INT_MASK 0x0f | ||
89 | |||
90 | /* | ||
91 | * category 1 - PARAMETER mode | ||
92 | * | ||
93 | * This category supports function of camera features of M-5MOLS. It means we | ||
94 | * can handle with preview(MONITOR) resolution size/frame per second/interface | ||
95 | * between the sensor and the Application Processor/even the image effect. | ||
96 | */ | ||
97 | #define CAT1_DATA_INTERFACE 0x00 /* interface between sensor and AP */ | ||
98 | #define CAT1_MONITOR_SIZE 0x01 /* resolution at the MONITOR mode */ | ||
99 | #define CAT1_MONITOR_FPS 0x02 /* frame per second at this mode */ | ||
100 | #define CAT1_EFFECT 0x0b /* image effects */ | ||
101 | |||
102 | #define PARM_MON_SIZE I2C_REG(CAT_PARAM, CAT1_MONITOR_SIZE, 1) | ||
103 | |||
104 | #define PARM_MON_FPS I2C_REG(CAT_PARAM, CAT1_MONITOR_FPS, 1) | ||
105 | #define REG_FPS_30 0x02 | ||
106 | |||
107 | #define PARM_INTERFACE I2C_REG(CAT_PARAM, CAT1_DATA_INTERFACE, 1) | ||
108 | #define REG_INTERFACE_MIPI 0x02 | ||
109 | |||
110 | #define PARM_EFFECT I2C_REG(CAT_PARAM, CAT1_EFFECT, 1) | ||
111 | #define REG_EFFECT_OFF 0x00 | ||
112 | #define REG_EFFECT_NEGA 0x01 | ||
113 | #define REG_EFFECT_EMBOSS 0x06 | ||
114 | #define REG_EFFECT_OUTLINE 0x07 | ||
115 | #define REG_EFFECT_WATERCOLOR 0x08 | ||
116 | |||
117 | /* | ||
118 | * Category 2 - MONITOR mode | ||
119 | * | ||
120 | * The MONITOR mode is same as preview mode as we said. The M-5MOLS has another | ||
121 | * mode named "Preview", but this preview mode is used at the case specific | ||
122 | * vider-recording mode. This mmode supports only YUYV format. On the other | ||
123 | * hand, the JPEG & RAW formats is supports by CAPTURE mode. And, there are | ||
124 | * another options like zoom/color effect(different with effect in PARAMETER | ||
125 | * mode)/anti hand shaking algorithm. | ||
126 | */ | ||
127 | #define CAT2_ZOOM 0x01 /* set the zoom position & execute */ | ||
128 | #define CAT2_ZOOM_STEP 0x03 /* set the zoom step */ | ||
129 | #define CAT2_CFIXB 0x09 /* CB value for color effect */ | ||
130 | #define CAT2_CFIXR 0x0a /* CR value for color effect */ | ||
131 | #define CAT2_COLOR_EFFECT 0x0b /* set on/off of color effect */ | ||
132 | #define CAT2_CHROMA_LVL 0x0f /* set chroma level */ | ||
133 | #define CAT2_CHROMA_EN 0x10 /* set on/off of choroma */ | ||
134 | #define CAT2_EDGE_LVL 0x11 /* set sharpness level */ | ||
135 | #define CAT2_EDGE_EN 0x12 /* set on/off sharpness */ | ||
136 | #define CAT2_TONE_CTL 0x25 /* set tone color(contrast) */ | ||
137 | |||
138 | #define MON_ZOOM I2C_REG(CAT_MONITOR, CAT2_ZOOM, 1) | ||
139 | |||
140 | #define MON_CFIXR I2C_REG(CAT_MONITOR, CAT2_CFIXR, 1) | ||
141 | #define MON_CFIXB I2C_REG(CAT_MONITOR, CAT2_CFIXB, 1) | ||
142 | #define REG_CFIXB_SEPIA 0xd8 | ||
143 | #define REG_CFIXR_SEPIA 0x18 | ||
144 | |||
145 | #define MON_EFFECT I2C_REG(CAT_MONITOR, CAT2_COLOR_EFFECT, 1) | ||
146 | #define REG_COLOR_EFFECT_OFF 0x00 | ||
147 | #define REG_COLOR_EFFECT_ON 0x01 | ||
148 | |||
149 | #define MON_CHROMA_EN I2C_REG(CAT_MONITOR, CAT2_CHROMA_EN, 1) | ||
150 | #define MON_CHROMA_LVL I2C_REG(CAT_MONITOR, CAT2_CHROMA_LVL, 1) | ||
151 | #define REG_CHROMA_OFF 0x00 | ||
152 | #define REG_CHROMA_ON 0x01 | ||
153 | |||
154 | #define MON_EDGE_EN I2C_REG(CAT_MONITOR, CAT2_EDGE_EN, 1) | ||
155 | #define MON_EDGE_LVL I2C_REG(CAT_MONITOR, CAT2_EDGE_LVL, 1) | ||
156 | #define REG_EDGE_OFF 0x00 | ||
157 | #define REG_EDGE_ON 0x01 | ||
158 | |||
159 | #define MON_TONE_CTL I2C_REG(CAT_MONITOR, CAT2_TONE_CTL, 1) | ||
160 | |||
161 | /* | ||
162 | * Category 3 - Auto Exposure | ||
163 | * | ||
164 | * The M-5MOLS exposure capbility is detailed as which is similar to digital | ||
165 | * camera. This category supports AE locking/various AE mode(range of exposure) | ||
166 | * /ISO/flickering/EV bias/shutter/meteoring, and anything else. And the | ||
167 | * maximum/minimum exposure gain value depending on M-5MOLS firmware, may be | ||
168 | * different. So, this category also provide getting the max/min values. And, | ||
169 | * each MONITOR and CAPTURE mode has each gain/shutter/max exposure values. | ||
170 | */ | ||
171 | #define CAT3_AE_LOCK 0x00 /* locking Auto exposure */ | ||
172 | #define CAT3_AE_MODE 0x01 /* set AE mode, mode means range */ | ||
173 | #define CAT3_ISO 0x05 /* set ISO */ | ||
174 | #define CAT3_EV_PRESET_MONITOR 0x0a /* EV(scenemode) preset for MONITOR */ | ||
175 | #define CAT3_EV_PRESET_CAPTURE 0x0b /* EV(scenemode) preset for CAPTURE */ | ||
176 | #define CAT3_MANUAL_GAIN_MON 0x12 /* meteoring value for the MONITOR */ | ||
177 | #define CAT3_MAX_GAIN_MON 0x1a /* max gain value for the MONITOR */ | ||
178 | #define CAT3_MANUAL_GAIN_CAP 0x26 /* meteoring value for the CAPTURE */ | ||
179 | #define CAT3_AE_INDEX 0x38 /* AE index */ | ||
180 | |||
181 | #define AE_LOCK I2C_REG(CAT_AE, CAT3_AE_LOCK, 1) | ||
182 | #define REG_AE_UNLOCK 0x00 | ||
183 | #define REG_AE_LOCK 0x01 | ||
184 | |||
185 | #define AE_MODE I2C_REG(CAT_AE, CAT3_AE_MODE, 1) | ||
186 | #define REG_AE_OFF 0x00 /* AE off */ | ||
187 | #define REG_AE_ALL 0x01 /* calc AE in all block integral */ | ||
188 | #define REG_AE_CENTER 0x03 /* calc AE in center weighted */ | ||
189 | #define REG_AE_SPOT 0x06 /* calc AE in specific spot */ | ||
190 | |||
191 | #define AE_ISO I2C_REG(CAT_AE, CAT3_ISO, 1) | ||
192 | #define REG_ISO_AUTO 0x00 | ||
193 | #define REG_ISO_50 0x01 | ||
194 | #define REG_ISO_100 0x02 | ||
195 | #define REG_ISO_200 0x03 | ||
196 | #define REG_ISO_400 0x04 | ||
197 | #define REG_ISO_800 0x05 | ||
198 | |||
199 | #define AE_EV_PRESET_MONITOR I2C_REG(CAT_AE, CAT3_EV_PRESET_MONITOR, 1) | ||
200 | #define AE_EV_PRESET_CAPTURE I2C_REG(CAT_AE, CAT3_EV_PRESET_CAPTURE, 1) | ||
201 | #define REG_SCENE_NORMAL 0x00 | ||
202 | #define REG_SCENE_PORTRAIT 0x01 | ||
203 | #define REG_SCENE_LANDSCAPE 0x02 | ||
204 | #define REG_SCENE_SPORTS 0x03 | ||
205 | #define REG_SCENE_PARTY_INDOOR 0x04 | ||
206 | #define REG_SCENE_BEACH_SNOW 0x05 | ||
207 | #define REG_SCENE_SUNSET 0x06 | ||
208 | #define REG_SCENE_DAWN_DUSK 0x07 | ||
209 | #define REG_SCENE_FALL 0x08 | ||
210 | #define REG_SCENE_NIGHT 0x09 | ||
211 | #define REG_SCENE_AGAINST_LIGHT 0x0a | ||
212 | #define REG_SCENE_FIRE 0x0b | ||
213 | #define REG_SCENE_TEXT 0x0c | ||
214 | #define REG_SCENE_CANDLE 0x0d | ||
215 | |||
216 | #define AE_MAN_GAIN_MON I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_MON, 2) | ||
217 | #define AE_MAX_GAIN_MON I2C_REG(CAT_AE, CAT3_MAX_GAIN_MON, 2) | ||
218 | #define AE_MAN_GAIN_CAP I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_CAP, 2) | ||
219 | |||
220 | #define AE_INDEX I2C_REG(CAT_AE, CAT3_AE_INDEX, 1) | ||
221 | #define REG_AE_INDEX_20_NEG 0x00 | ||
222 | #define REG_AE_INDEX_15_NEG 0x01 | ||
223 | #define REG_AE_INDEX_10_NEG 0x02 | ||
224 | #define REG_AE_INDEX_05_NEG 0x03 | ||
225 | #define REG_AE_INDEX_00 0x04 | ||
226 | #define REG_AE_INDEX_05_POS 0x05 | ||
227 | #define REG_AE_INDEX_10_POS 0x06 | ||
228 | #define REG_AE_INDEX_15_POS 0x07 | ||
229 | #define REG_AE_INDEX_20_POS 0x08 | ||
230 | |||
231 | /* | ||
232 | * Category 6 - White Balance | ||
233 | * | ||
234 | * This category provide AWB locking/mode/preset/speed/gain bias, etc. | ||
235 | */ | ||
236 | #define CAT6_AWB_LOCK 0x00 /* locking Auto Whitebalance */ | ||
237 | #define CAT6_AWB_MODE 0x02 /* set Auto or Manual */ | ||
238 | #define CAT6_AWB_MANUAL 0x03 /* set Manual(preset) value */ | ||
239 | |||
240 | #define AWB_LOCK I2C_REG(CAT_WB, CAT6_AWB_LOCK, 1) | ||
241 | #define REG_AWB_UNLOCK 0x00 | ||
242 | #define REG_AWB_LOCK 0x01 | ||
243 | |||
244 | #define AWB_MODE I2C_REG(CAT_WB, CAT6_AWB_MODE, 1) | ||
245 | #define REG_AWB_AUTO 0x01 /* AWB off */ | ||
246 | #define REG_AWB_PRESET 0x02 /* AWB preset */ | ||
247 | |||
248 | #define AWB_MANUAL I2C_REG(CAT_WB, CAT6_AWB_MANUAL, 1) | ||
249 | #define REG_AWB_INCANDESCENT 0x01 | ||
250 | #define REG_AWB_FLUORESCENT_1 0x02 | ||
251 | #define REG_AWB_FLUORESCENT_2 0x03 | ||
252 | #define REG_AWB_DAYLIGHT 0x04 | ||
253 | #define REG_AWB_CLOUDY 0x05 | ||
254 | #define REG_AWB_SHADE 0x06 | ||
255 | #define REG_AWB_HORIZON 0x07 | ||
256 | #define REG_AWB_LEDLIGHT 0x09 | ||
257 | |||
258 | /* | ||
259 | * Category 7 - EXIF information | ||
260 | */ | ||
261 | #define CAT7_INFO_EXPTIME_NU 0x00 | ||
262 | #define CAT7_INFO_EXPTIME_DE 0x04 | ||
263 | #define CAT7_INFO_TV_NU 0x08 | ||
264 | #define CAT7_INFO_TV_DE 0x0c | ||
265 | #define CAT7_INFO_AV_NU 0x10 | ||
266 | #define CAT7_INFO_AV_DE 0x14 | ||
267 | #define CAT7_INFO_BV_NU 0x18 | ||
268 | #define CAT7_INFO_BV_DE 0x1c | ||
269 | #define CAT7_INFO_EBV_NU 0x20 | ||
270 | #define CAT7_INFO_EBV_DE 0x24 | ||
271 | #define CAT7_INFO_ISO 0x28 | ||
272 | #define CAT7_INFO_FLASH 0x2a | ||
273 | #define CAT7_INFO_SDR 0x2c | ||
274 | #define CAT7_INFO_QVAL 0x2e | ||
275 | |||
276 | #define EXIF_INFO_EXPTIME_NU I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_NU, 4) | ||
277 | #define EXIF_INFO_EXPTIME_DE I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_DE, 4) | ||
278 | #define EXIF_INFO_TV_NU I2C_REG(CAT_EXIF, CAT7_INFO_TV_NU, 4) | ||
279 | #define EXIF_INFO_TV_DE I2C_REG(CAT_EXIF, CAT7_INFO_TV_DE, 4) | ||
280 | #define EXIF_INFO_AV_NU I2C_REG(CAT_EXIF, CAT7_INFO_AV_NU, 4) | ||
281 | #define EXIF_INFO_AV_DE I2C_REG(CAT_EXIF, CAT7_INFO_AV_DE, 4) | ||
282 | #define EXIF_INFO_BV_NU I2C_REG(CAT_EXIF, CAT7_INFO_BV_NU, 4) | ||
283 | #define EXIF_INFO_BV_DE I2C_REG(CAT_EXIF, CAT7_INFO_BV_DE, 4) | ||
284 | #define EXIF_INFO_EBV_NU I2C_REG(CAT_EXIF, CAT7_INFO_EBV_NU, 4) | ||
285 | #define EXIF_INFO_EBV_DE I2C_REG(CAT_EXIF, CAT7_INFO_EBV_DE, 4) | ||
286 | #define EXIF_INFO_ISO I2C_REG(CAT_EXIF, CAT7_INFO_ISO, 2) | ||
287 | #define EXIF_INFO_FLASH I2C_REG(CAT_EXIF, CAT7_INFO_FLASH, 2) | ||
288 | #define EXIF_INFO_SDR I2C_REG(CAT_EXIF, CAT7_INFO_SDR, 2) | ||
289 | #define EXIF_INFO_QVAL I2C_REG(CAT_EXIF, CAT7_INFO_QVAL, 2) | ||
290 | |||
291 | /* | ||
292 | * Category 9 - Face Detection | ||
293 | */ | ||
294 | #define CAT9_FD_CTL 0x00 | ||
295 | |||
296 | #define FD_CTL I2C_REG(CAT_FD, CAT9_FD_CTL, 1) | ||
297 | #define BIT_FD_EN 0 | ||
298 | #define BIT_FD_DRAW_FACE_FRAME 4 | ||
299 | #define BIT_FD_DRAW_SMILE_LVL 6 | ||
300 | #define REG_FD(shift) (1 << shift) | ||
301 | #define REG_FD_OFF 0x0 | ||
302 | |||
303 | /* | ||
304 | * Category A - Lens Parameter | ||
305 | */ | ||
306 | #define CATA_AF_MODE 0x01 | ||
307 | #define CATA_AF_EXECUTE 0x02 | ||
308 | #define CATA_AF_STATUS 0x03 | ||
309 | #define CATA_AF_VERSION 0x0a | ||
310 | |||
311 | #define AF_MODE I2C_REG(CAT_LENS, CATA_AF_MODE, 1) | ||
312 | #define REG_AF_NORMAL 0x00 /* Normal AF, one time */ | ||
313 | #define REG_AF_MACRO 0x01 /* Macro AF, one time */ | ||
314 | #define REG_AF_POWEROFF 0x07 | ||
315 | |||
316 | #define AF_EXECUTE I2C_REG(CAT_LENS, CATA_AF_EXECUTE, 1) | ||
317 | #define REG_AF_STOP 0x00 | ||
318 | #define REG_AF_EXE_AUTO 0x01 | ||
319 | #define REG_AF_EXE_CAF 0x02 | ||
320 | |||
321 | #define AF_STATUS I2C_REG(CAT_LENS, CATA_AF_STATUS, 1) | ||
322 | #define REG_AF_FAIL 0x00 | ||
323 | #define REG_AF_SUCCESS 0x02 | ||
324 | #define REG_AF_IDLE 0x04 | ||
325 | #define REG_AF_BUSY 0x05 | ||
326 | |||
327 | #define AF_VERSION I2C_REG(CAT_LENS, CATA_AF_VERSION, 1) | ||
328 | |||
329 | /* | ||
330 | * Category B - CAPTURE Parameter | ||
331 | */ | ||
332 | #define CATB_YUVOUT_MAIN 0x00 | ||
333 | #define CATB_MAIN_IMAGE_SIZE 0x01 | ||
334 | #define CATB_MCC_MODE 0x1d | ||
335 | #define CATB_WDR_EN 0x2c | ||
336 | #define CATB_LIGHT_CTRL 0x40 | ||
337 | #define CATB_FLASH_CTRL 0x41 | ||
338 | |||
339 | #define CAPP_YUVOUT_MAIN I2C_REG(CAT_CAPT_PARM, CATB_YUVOUT_MAIN, 1) | ||
340 | #define REG_YUV422 0x00 | ||
341 | #define REG_BAYER10 0x05 | ||
342 | #define REG_BAYER8 0x06 | ||
343 | #define REG_JPEG 0x10 | ||
344 | |||
345 | #define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, CATB_MAIN_IMAGE_SIZE, 1) | ||
346 | |||
347 | #define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, CATB_MCC_MODE, 1) | ||
348 | #define REG_MCC_OFF 0x00 | ||
349 | #define REG_MCC_NORMAL 0x01 | ||
350 | |||
351 | #define CAPP_WDR_EN I2C_REG(CAT_CAPT_PARM, CATB_WDR_EN, 1) | ||
352 | #define REG_WDR_OFF 0x00 | ||
353 | #define REG_WDR_ON 0x01 | ||
354 | #define REG_WDR_AUTO 0x02 | ||
355 | |||
356 | #define CAPP_LIGHT_CTRL I2C_REG(CAT_CAPT_PARM, CATB_LIGHT_CTRL, 1) | ||
357 | #define REG_LIGHT_OFF 0x00 | ||
358 | #define REG_LIGHT_ON 0x01 | ||
359 | #define REG_LIGHT_AUTO 0x02 | ||
360 | |||
361 | #define CAPP_FLASH_CTRL I2C_REG(CAT_CAPT_PARM, CATB_FLASH_CTRL, 1) | ||
362 | #define REG_FLASH_OFF 0x00 | ||
363 | #define REG_FLASH_ON 0x01 | ||
364 | #define REG_FLASH_AUTO 0x02 | ||
365 | |||
366 | /* | ||
367 | * Category C - CAPTURE Control | ||
368 | */ | ||
369 | #define CATC_CAP_MODE 0x00 | ||
370 | #define CATC_CAP_SEL_FRAME 0x06 /* It determines Single or Multi */ | ||
371 | #define CATC_CAP_START 0x09 | ||
372 | #define CATC_CAP_IMAGE_SIZE 0x0d | ||
373 | #define CATC_CAP_THUMB_SIZE 0x11 | ||
374 | |||
375 | #define CAPC_MODE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_MODE, 1) | ||
376 | #define REG_CAP_NONE 0x00 | ||
377 | #define REG_CAP_ANTI_SHAKE 0x02 | ||
378 | |||
379 | #define CAPC_SEL_FRAME I2C_REG(CAT_CAPT_CTRL, CATC_CAP_SEL_FRAME, 1) | ||
380 | |||
381 | #define CAPC_START I2C_REG(CAT_CAPT_CTRL, CATC_CAP_START, 1) | ||
382 | #define REG_CAP_START_MAIN 0x01 | ||
383 | #define REG_CAP_START_THUMB 0x03 | ||
384 | |||
385 | #define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 1) | ||
386 | #define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 1) | ||
387 | |||
388 | /* | ||
389 | * Category F - Flash | ||
390 | * | ||
391 | * This mode provides functions about internal flash stuff and system startup. | ||
392 | */ | ||
393 | #define CATF_CAM_START 0x12 /* It starts internal ARM core booting | ||
394 | * after power-up */ | ||
395 | |||
396 | #define FLASH_CAM_START I2C_REG(CAT_FLASH, CATF_CAM_START, 1) | ||
397 | #define REG_START_ARM_BOOT 0x01 | ||
398 | |||
399 | #endif /* M5MOLS_REG_H */ | ||
diff --git a/drivers/media/video/uvc/Makefile b/drivers/media/video/uvc/Makefile index 968c1994eda0..2071ca8a2f03 100644 --- a/drivers/media/video/uvc/Makefile +++ b/drivers/media/video/uvc/Makefile | |||
@@ -1,3 +1,6 @@ | |||
1 | uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ | 1 | uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ |
2 | uvc_status.o uvc_isight.o | 2 | uvc_status.o uvc_isight.o |
3 | ifeq ($(CONFIG_MEDIA_CONTROLLER),y) | ||
4 | uvcvideo-objs += uvc_entity.o | ||
5 | endif | ||
3 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o | 6 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o |
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 823f4b389745..b6eae48d7fb8 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -248,7 +248,7 @@ uint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator) | |||
248 | * Terminal and unit management | 248 | * Terminal and unit management |
249 | */ | 249 | */ |
250 | 250 | ||
251 | static struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) | 251 | struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) |
252 | { | 252 | { |
253 | struct uvc_entity *entity; | 253 | struct uvc_entity *entity; |
254 | 254 | ||
@@ -795,9 +795,12 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, | |||
795 | struct uvc_entity *entity; | 795 | struct uvc_entity *entity; |
796 | unsigned int num_inputs; | 796 | unsigned int num_inputs; |
797 | unsigned int size; | 797 | unsigned int size; |
798 | unsigned int i; | ||
798 | 799 | ||
800 | extra_size = ALIGN(extra_size, sizeof(*entity->pads)); | ||
799 | num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; | 801 | num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; |
800 | size = sizeof(*entity) + extra_size + num_inputs; | 802 | size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads |
803 | + num_inputs; | ||
801 | entity = kzalloc(size, GFP_KERNEL); | 804 | entity = kzalloc(size, GFP_KERNEL); |
802 | if (entity == NULL) | 805 | if (entity == NULL) |
803 | return NULL; | 806 | return NULL; |
@@ -805,8 +808,17 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, | |||
805 | entity->id = id; | 808 | entity->id = id; |
806 | entity->type = type; | 809 | entity->type = type; |
807 | 810 | ||
811 | entity->num_links = 0; | ||
812 | entity->num_pads = num_pads; | ||
813 | entity->pads = ((void *)(entity + 1)) + extra_size; | ||
814 | |||
815 | for (i = 0; i < num_inputs; ++i) | ||
816 | entity->pads[i].flags = MEDIA_PAD_FL_SINK; | ||
817 | if (!UVC_ENTITY_IS_OTERM(entity)) | ||
818 | entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE; | ||
819 | |||
808 | entity->bNrInPins = num_inputs; | 820 | entity->bNrInPins = num_inputs; |
809 | entity->baSourceID = ((__u8 *)entity) + sizeof(*entity) + extra_size; | 821 | entity->baSourceID = (__u8 *)(&entity->pads[num_pads]); |
810 | 822 | ||
811 | return entity; | 823 | return entity; |
812 | } | 824 | } |
@@ -1585,6 +1597,13 @@ static void uvc_delete(struct uvc_device *dev) | |||
1585 | uvc_status_cleanup(dev); | 1597 | uvc_status_cleanup(dev); |
1586 | uvc_ctrl_cleanup_device(dev); | 1598 | uvc_ctrl_cleanup_device(dev); |
1587 | 1599 | ||
1600 | if (dev->vdev.dev) | ||
1601 | v4l2_device_unregister(&dev->vdev); | ||
1602 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
1603 | if (media_devnode_is_registered(&dev->mdev.devnode)) | ||
1604 | media_device_unregister(&dev->mdev); | ||
1605 | #endif | ||
1606 | |||
1588 | list_for_each_safe(p, n, &dev->chains) { | 1607 | list_for_each_safe(p, n, &dev->chains) { |
1589 | struct uvc_video_chain *chain; | 1608 | struct uvc_video_chain *chain; |
1590 | chain = list_entry(p, struct uvc_video_chain, list); | 1609 | chain = list_entry(p, struct uvc_video_chain, list); |
@@ -1594,6 +1613,13 @@ static void uvc_delete(struct uvc_device *dev) | |||
1594 | list_for_each_safe(p, n, &dev->entities) { | 1613 | list_for_each_safe(p, n, &dev->entities) { |
1595 | struct uvc_entity *entity; | 1614 | struct uvc_entity *entity; |
1596 | entity = list_entry(p, struct uvc_entity, list); | 1615 | entity = list_entry(p, struct uvc_entity, list); |
1616 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
1617 | uvc_mc_cleanup_entity(entity); | ||
1618 | #endif | ||
1619 | if (entity->vdev) { | ||
1620 | video_device_release(entity->vdev); | ||
1621 | entity->vdev = NULL; | ||
1622 | } | ||
1597 | kfree(entity); | 1623 | kfree(entity); |
1598 | } | 1624 | } |
1599 | 1625 | ||
@@ -1616,8 +1642,6 @@ static void uvc_release(struct video_device *vdev) | |||
1616 | struct uvc_streaming *stream = video_get_drvdata(vdev); | 1642 | struct uvc_streaming *stream = video_get_drvdata(vdev); |
1617 | struct uvc_device *dev = stream->dev; | 1643 | struct uvc_device *dev = stream->dev; |
1618 | 1644 | ||
1619 | video_device_release(vdev); | ||
1620 | |||
1621 | /* Decrement the registered streams count and delete the device when it | 1645 | /* Decrement the registered streams count and delete the device when it |
1622 | * reaches zero. | 1646 | * reaches zero. |
1623 | */ | 1647 | */ |
@@ -1682,7 +1706,7 @@ static int uvc_register_video(struct uvc_device *dev, | |||
1682 | * unregistered before the reference is released, so we don't need to | 1706 | * unregistered before the reference is released, so we don't need to |
1683 | * get another one. | 1707 | * get another one. |
1684 | */ | 1708 | */ |
1685 | vdev->parent = &dev->intf->dev; | 1709 | vdev->v4l2_dev = &dev->vdev; |
1686 | vdev->fops = &uvc_fops; | 1710 | vdev->fops = &uvc_fops; |
1687 | vdev->release = uvc_release; | 1711 | vdev->release = uvc_release; |
1688 | strlcpy(vdev->name, dev->name, sizeof vdev->name); | 1712 | strlcpy(vdev->name, dev->name, sizeof vdev->name); |
@@ -1731,6 +1755,8 @@ static int uvc_register_terms(struct uvc_device *dev, | |||
1731 | ret = uvc_register_video(dev, stream); | 1755 | ret = uvc_register_video(dev, stream); |
1732 | if (ret < 0) | 1756 | if (ret < 0) |
1733 | return ret; | 1757 | return ret; |
1758 | |||
1759 | term->vdev = stream->vdev; | ||
1734 | } | 1760 | } |
1735 | 1761 | ||
1736 | return 0; | 1762 | return 0; |
@@ -1745,6 +1771,14 @@ static int uvc_register_chains(struct uvc_device *dev) | |||
1745 | ret = uvc_register_terms(dev, chain); | 1771 | ret = uvc_register_terms(dev, chain); |
1746 | if (ret < 0) | 1772 | if (ret < 0) |
1747 | return ret; | 1773 | return ret; |
1774 | |||
1775 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
1776 | ret = uvc_mc_register_entities(chain); | ||
1777 | if (ret < 0) { | ||
1778 | uvc_printk(KERN_INFO, "Failed to register entites " | ||
1779 | "(%d).\n", ret); | ||
1780 | } | ||
1781 | #endif | ||
1748 | } | 1782 | } |
1749 | 1783 | ||
1750 | return 0; | 1784 | return 0; |
@@ -1814,6 +1848,24 @@ static int uvc_probe(struct usb_interface *intf, | |||
1814 | "linux-uvc-devel mailing list.\n"); | 1848 | "linux-uvc-devel mailing list.\n"); |
1815 | } | 1849 | } |
1816 | 1850 | ||
1851 | /* Register the media and V4L2 devices. */ | ||
1852 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
1853 | dev->mdev.dev = &intf->dev; | ||
1854 | strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); | ||
1855 | if (udev->serial) | ||
1856 | strlcpy(dev->mdev.serial, udev->serial, | ||
1857 | sizeof(dev->mdev.serial)); | ||
1858 | strcpy(dev->mdev.bus_info, udev->devpath); | ||
1859 | dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); | ||
1860 | dev->mdev.driver_version = DRIVER_VERSION_NUMBER; | ||
1861 | if (media_device_register(&dev->mdev) < 0) | ||
1862 | goto error; | ||
1863 | |||
1864 | dev->vdev.mdev = &dev->mdev; | ||
1865 | #endif | ||
1866 | if (v4l2_device_register(&intf->dev, &dev->vdev) < 0) | ||
1867 | goto error; | ||
1868 | |||
1817 | /* Initialize controls. */ | 1869 | /* Initialize controls. */ |
1818 | if (uvc_ctrl_init_device(dev) < 0) | 1870 | if (uvc_ctrl_init_device(dev) < 0) |
1819 | goto error; | 1871 | goto error; |
@@ -1822,7 +1874,7 @@ static int uvc_probe(struct usb_interface *intf, | |||
1822 | if (uvc_scan_device(dev) < 0) | 1874 | if (uvc_scan_device(dev) < 0) |
1823 | goto error; | 1875 | goto error; |
1824 | 1876 | ||
1825 | /* Register video devices. */ | 1877 | /* Register video device nodes. */ |
1826 | if (uvc_register_chains(dev) < 0) | 1878 | if (uvc_register_chains(dev) < 0) |
1827 | goto error; | 1879 | goto error; |
1828 | 1880 | ||
diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c new file mode 100644 index 000000000000..ede7852bb1df --- /dev/null +++ b/drivers/media/video/uvc/uvc_entity.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * uvc_entity.c -- USB Video Class driver | ||
3 | * | ||
4 | * Copyright (C) 2005-2011 | ||
5 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/videodev2.h> | ||
17 | |||
18 | #include <media/v4l2-common.h> | ||
19 | |||
20 | #include "uvcvideo.h" | ||
21 | |||
22 | /* ------------------------------------------------------------------------ | ||
23 | * Video subdevices registration and unregistration | ||
24 | */ | ||
25 | |||
26 | static int uvc_mc_register_entity(struct uvc_video_chain *chain, | ||
27 | struct uvc_entity *entity) | ||
28 | { | ||
29 | const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; | ||
30 | struct uvc_entity *remote; | ||
31 | unsigned int i; | ||
32 | u8 remote_pad; | ||
33 | int ret; | ||
34 | |||
35 | for (i = 0; i < entity->num_pads; ++i) { | ||
36 | struct media_entity *source; | ||
37 | struct media_entity *sink; | ||
38 | |||
39 | if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK)) | ||
40 | continue; | ||
41 | |||
42 | remote = uvc_entity_by_id(chain->dev, entity->baSourceID[i]); | ||
43 | if (remote == NULL) | ||
44 | return -EINVAL; | ||
45 | |||
46 | source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING) | ||
47 | ? &remote->vdev->entity : &remote->subdev.entity; | ||
48 | sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) | ||
49 | ? &entity->vdev->entity : &entity->subdev.entity; | ||
50 | |||
51 | remote_pad = remote->num_pads - 1; | ||
52 | ret = media_entity_create_link(source, remote_pad, | ||
53 | sink, i, flags); | ||
54 | if (ret < 0) | ||
55 | return ret; | ||
56 | } | ||
57 | |||
58 | if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) | ||
59 | ret = v4l2_device_register_subdev(&chain->dev->vdev, | ||
60 | &entity->subdev); | ||
61 | |||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | static struct v4l2_subdev_ops uvc_subdev_ops = { | ||
66 | }; | ||
67 | |||
68 | void uvc_mc_cleanup_entity(struct uvc_entity *entity) | ||
69 | { | ||
70 | if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) | ||
71 | media_entity_cleanup(&entity->subdev.entity); | ||
72 | else if (entity->vdev != NULL) | ||
73 | media_entity_cleanup(&entity->vdev->entity); | ||
74 | } | ||
75 | |||
76 | static int uvc_mc_init_entity(struct uvc_entity *entity) | ||
77 | { | ||
78 | int ret; | ||
79 | |||
80 | if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) { | ||
81 | v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops); | ||
82 | strlcpy(entity->subdev.name, entity->name, | ||
83 | sizeof(entity->subdev.name)); | ||
84 | |||
85 | ret = media_entity_init(&entity->subdev.entity, | ||
86 | entity->num_pads, entity->pads, 0); | ||
87 | } else | ||
88 | ret = media_entity_init(&entity->vdev->entity, | ||
89 | entity->num_pads, entity->pads, 0); | ||
90 | |||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | int uvc_mc_register_entities(struct uvc_video_chain *chain) | ||
95 | { | ||
96 | struct uvc_entity *entity; | ||
97 | int ret; | ||
98 | |||
99 | list_for_each_entry(entity, &chain->entities, chain) { | ||
100 | ret = uvc_mc_init_entity(entity); | ||
101 | if (ret < 0) { | ||
102 | uvc_printk(KERN_INFO, "Failed to initialize entity for " | ||
103 | "entity %u\n", entity->id); | ||
104 | return ret; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | list_for_each_entry(entity, &chain->entities, chain) { | ||
109 | ret = uvc_mc_register_entity(chain, entity); | ||
110 | if (ret < 0) { | ||
111 | uvc_printk(KERN_INFO, "Failed to register entity for " | ||
112 | "entity %u\n", entity->id); | ||
113 | return ret; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | return 0; | ||
118 | } | ||
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 7cf224bae2e5..20107fd3574d 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -98,8 +98,11 @@ struct uvc_xu_control { | |||
98 | #ifdef __KERNEL__ | 98 | #ifdef __KERNEL__ |
99 | 99 | ||
100 | #include <linux/poll.h> | 100 | #include <linux/poll.h> |
101 | #include <linux/usb.h> | ||
101 | #include <linux/usb/video.h> | 102 | #include <linux/usb/video.h> |
102 | #include <linux/uvcvideo.h> | 103 | #include <linux/uvcvideo.h> |
104 | #include <media/media-device.h> | ||
105 | #include <media/v4l2-device.h> | ||
103 | 106 | ||
104 | /* -------------------------------------------------------------------------- | 107 | /* -------------------------------------------------------------------------- |
105 | * UVC constants | 108 | * UVC constants |
@@ -301,6 +304,13 @@ struct uvc_entity { | |||
301 | __u16 type; | 304 | __u16 type; |
302 | char name[64]; | 305 | char name[64]; |
303 | 306 | ||
307 | /* Media controller-related fields. */ | ||
308 | struct video_device *vdev; | ||
309 | struct v4l2_subdev subdev; | ||
310 | unsigned int num_pads; | ||
311 | unsigned int num_links; | ||
312 | struct media_pad *pads; | ||
313 | |||
304 | union { | 314 | union { |
305 | struct { | 315 | struct { |
306 | __u16 wObjectiveFocalLengthMin; | 316 | __u16 wObjectiveFocalLengthMin; |
@@ -504,6 +514,10 @@ struct uvc_device { | |||
504 | atomic_t nmappings; | 514 | atomic_t nmappings; |
505 | 515 | ||
506 | /* Video control interface */ | 516 | /* Video control interface */ |
517 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
518 | struct media_device mdev; | ||
519 | #endif | ||
520 | struct v4l2_device vdev; | ||
507 | __u16 uvc_version; | 521 | __u16 uvc_version; |
508 | __u32 clock_frequency; | 522 | __u32 clock_frequency; |
509 | 523 | ||
@@ -583,6 +597,8 @@ extern unsigned int uvc_timeout_param; | |||
583 | /* Core driver */ | 597 | /* Core driver */ |
584 | extern struct uvc_driver uvc_driver; | 598 | extern struct uvc_driver uvc_driver; |
585 | 599 | ||
600 | extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id); | ||
601 | |||
586 | /* Video buffers queue management. */ | 602 | /* Video buffers queue management. */ |
587 | extern void uvc_queue_init(struct uvc_video_queue *queue, | 603 | extern void uvc_queue_init(struct uvc_video_queue *queue, |
588 | enum v4l2_buf_type type, int drop_corrupted); | 604 | enum v4l2_buf_type type, int drop_corrupted); |
@@ -616,6 +632,10 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue) | |||
616 | /* V4L2 interface */ | 632 | /* V4L2 interface */ |
617 | extern const struct v4l2_file_operations uvc_fops; | 633 | extern const struct v4l2_file_operations uvc_fops; |
618 | 634 | ||
635 | /* Media controller */ | ||
636 | extern int uvc_mc_register_entities(struct uvc_video_chain *chain); | ||
637 | extern void uvc_mc_cleanup_entity(struct uvc_entity *entity); | ||
638 | |||
619 | /* Video */ | 639 | /* Video */ |
620 | extern int uvc_video_init(struct uvc_streaming *stream); | 640 | extern int uvc_video_init(struct uvc_streaming *stream); |
621 | extern int uvc_video_suspend(struct uvc_streaming *stream); | 641 | extern int uvc_video_suspend(struct uvc_streaming *stream); |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 8344fc0ab858..b6c267724e14 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -719,6 +719,15 @@ config MFD_PM8XXX_IRQ | |||
719 | This is required to use certain other PM 8xxx features, such as GPIO | 719 | This is required to use certain other PM 8xxx features, such as GPIO |
720 | and MPP. | 720 | and MPP. |
721 | 721 | ||
722 | config MFD_TPS65910 | ||
723 | bool "TPS65910 Power Management chip" | ||
724 | depends on I2C=y | ||
725 | select MFD_CORE | ||
726 | select GPIO_TPS65910 | ||
727 | help | ||
728 | if you say yes here you get support for the TPS65910 series of | ||
729 | Power Management chips. | ||
730 | |||
722 | endif # MFD_SUPPORT | 731 | endif # MFD_SUPPORT |
723 | 732 | ||
724 | menu "Multimedia Capabilities Port drivers" | 733 | menu "Multimedia Capabilities Port drivers" |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 1acb8f29a96c..efe3cc33ed92 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -93,3 +93,4 @@ obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o | |||
93 | obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o | 93 | obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o |
94 | obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o | 94 | obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o |
95 | obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o | 95 | obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o |
96 | obj-$(CONFIG_MFD_TPS65910) += tps65910.o tps65910-irq.o | ||
diff --git a/drivers/mfd/tps65910-irq.c b/drivers/mfd/tps65910-irq.c new file mode 100644 index 000000000000..2bfad5c86cc7 --- /dev/null +++ b/drivers/mfd/tps65910-irq.c | |||
@@ -0,0 +1,218 @@ | |||
1 | /* | ||
2 | * tps65910-irq.c -- TI TPS6591x | ||
3 | * | ||
4 | * Copyright 2010 Texas Instruments Inc. | ||
5 | * | ||
6 | * Author: Graeme Gregory <gg@slimlogic.co.uk> | ||
7 | * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/bug.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/irq.h> | ||
23 | #include <linux/gpio.h> | ||
24 | #include <linux/mfd/tps65910.h> | ||
25 | |||
26 | static inline int irq_to_tps65910_irq(struct tps65910 *tps65910, | ||
27 | int irq) | ||
28 | { | ||
29 | return (irq - tps65910->irq_base); | ||
30 | } | ||
31 | |||
32 | /* | ||
33 | * This is a threaded IRQ handler so can access I2C/SPI. Since all | ||
34 | * interrupts are clear on read the IRQ line will be reasserted and | ||
35 | * the physical IRQ will be handled again if another interrupt is | ||
36 | * asserted while we run - in the normal course of events this is a | ||
37 | * rare occurrence so we save I2C/SPI reads. We're also assuming that | ||
38 | * it's rare to get lots of interrupts firing simultaneously so try to | ||
39 | * minimise I/O. | ||
40 | */ | ||
41 | static irqreturn_t tps65910_irq(int irq, void *irq_data) | ||
42 | { | ||
43 | struct tps65910 *tps65910 = irq_data; | ||
44 | u32 irq_sts; | ||
45 | u32 irq_mask; | ||
46 | u8 reg; | ||
47 | int i; | ||
48 | |||
49 | tps65910->read(tps65910, TPS65910_INT_STS, 1, ®); | ||
50 | irq_sts = reg; | ||
51 | tps65910->read(tps65910, TPS65910_INT_STS2, 1, ®); | ||
52 | irq_sts |= reg << 8; | ||
53 | switch (tps65910_chip_id(tps65910)) { | ||
54 | case TPS65911: | ||
55 | tps65910->read(tps65910, TPS65910_INT_STS3, 1, ®); | ||
56 | irq_sts |= reg << 16; | ||
57 | } | ||
58 | |||
59 | tps65910->read(tps65910, TPS65910_INT_MSK, 1, ®); | ||
60 | irq_mask = reg; | ||
61 | tps65910->read(tps65910, TPS65910_INT_MSK2, 1, ®); | ||
62 | irq_mask |= reg << 8; | ||
63 | switch (tps65910_chip_id(tps65910)) { | ||
64 | case TPS65911: | ||
65 | tps65910->read(tps65910, TPS65910_INT_MSK3, 1, ®); | ||
66 | irq_mask |= reg << 16; | ||
67 | } | ||
68 | |||
69 | irq_sts &= ~irq_mask; | ||
70 | |||
71 | if (!irq_sts) | ||
72 | return IRQ_NONE; | ||
73 | |||
74 | for (i = 0; i < tps65910->irq_num; i++) { | ||
75 | |||
76 | if (!(irq_sts & (1 << i))) | ||
77 | continue; | ||
78 | |||
79 | handle_nested_irq(tps65910->irq_base + i); | ||
80 | } | ||
81 | |||
82 | /* Write the STS register back to clear IRQs we handled */ | ||
83 | reg = irq_sts & 0xFF; | ||
84 | irq_sts >>= 8; | ||
85 | tps65910->write(tps65910, TPS65910_INT_STS, 1, ®); | ||
86 | reg = irq_sts & 0xFF; | ||
87 | tps65910->write(tps65910, TPS65910_INT_STS2, 1, ®); | ||
88 | switch (tps65910_chip_id(tps65910)) { | ||
89 | case TPS65911: | ||
90 | reg = irq_sts >> 8; | ||
91 | tps65910->write(tps65910, TPS65910_INT_STS3, 1, ®); | ||
92 | } | ||
93 | |||
94 | return IRQ_HANDLED; | ||
95 | } | ||
96 | |||
97 | static void tps65910_irq_lock(struct irq_data *data) | ||
98 | { | ||
99 | struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); | ||
100 | |||
101 | mutex_lock(&tps65910->irq_lock); | ||
102 | } | ||
103 | |||
104 | static void tps65910_irq_sync_unlock(struct irq_data *data) | ||
105 | { | ||
106 | struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); | ||
107 | u32 reg_mask; | ||
108 | u8 reg; | ||
109 | |||
110 | tps65910->read(tps65910, TPS65910_INT_MSK, 1, ®); | ||
111 | reg_mask = reg; | ||
112 | tps65910->read(tps65910, TPS65910_INT_MSK2, 1, ®); | ||
113 | reg_mask |= reg << 8; | ||
114 | switch (tps65910_chip_id(tps65910)) { | ||
115 | case TPS65911: | ||
116 | tps65910->read(tps65910, TPS65910_INT_MSK3, 1, ®); | ||
117 | reg_mask |= reg << 16; | ||
118 | } | ||
119 | |||
120 | if (tps65910->irq_mask != reg_mask) { | ||
121 | reg = tps65910->irq_mask & 0xFF; | ||
122 | tps65910->write(tps65910, TPS65910_INT_MSK, 1, ®); | ||
123 | reg = tps65910->irq_mask >> 8 & 0xFF; | ||
124 | tps65910->write(tps65910, TPS65910_INT_MSK2, 1, ®); | ||
125 | switch (tps65910_chip_id(tps65910)) { | ||
126 | case TPS65911: | ||
127 | reg = tps65910->irq_mask >> 16; | ||
128 | tps65910->write(tps65910, TPS65910_INT_MSK3, 1, ®); | ||
129 | } | ||
130 | } | ||
131 | mutex_unlock(&tps65910->irq_lock); | ||
132 | } | ||
133 | |||
134 | static void tps65910_irq_enable(struct irq_data *data) | ||
135 | { | ||
136 | struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); | ||
137 | |||
138 | tps65910->irq_mask &= ~( 1 << irq_to_tps65910_irq(tps65910, data->irq)); | ||
139 | } | ||
140 | |||
141 | static void tps65910_irq_disable(struct irq_data *data) | ||
142 | { | ||
143 | struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); | ||
144 | |||
145 | tps65910->irq_mask |= ( 1 << irq_to_tps65910_irq(tps65910, data->irq)); | ||
146 | } | ||
147 | |||
148 | static struct irq_chip tps65910_irq_chip = { | ||
149 | .name = "tps65910", | ||
150 | .irq_bus_lock = tps65910_irq_lock, | ||
151 | .irq_bus_sync_unlock = tps65910_irq_sync_unlock, | ||
152 | .irq_disable = tps65910_irq_disable, | ||
153 | .irq_enable = tps65910_irq_enable, | ||
154 | }; | ||
155 | |||
156 | int tps65910_irq_init(struct tps65910 *tps65910, int irq, | ||
157 | struct tps65910_platform_data *pdata) | ||
158 | { | ||
159 | int ret, cur_irq; | ||
160 | int flags = IRQF_ONESHOT; | ||
161 | |||
162 | if (!irq) { | ||
163 | dev_warn(tps65910->dev, "No interrupt support, no core IRQ\n"); | ||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
167 | if (!pdata || !pdata->irq_base) { | ||
168 | dev_warn(tps65910->dev, "No interrupt support, no IRQ base\n"); | ||
169 | return -EINVAL; | ||
170 | } | ||
171 | |||
172 | tps65910->irq_mask = 0xFFFFFF; | ||
173 | |||
174 | mutex_init(&tps65910->irq_lock); | ||
175 | tps65910->chip_irq = irq; | ||
176 | tps65910->irq_base = pdata->irq_base; | ||
177 | |||
178 | switch (tps65910_chip_id(tps65910)) { | ||
179 | case TPS65910: | ||
180 | tps65910->irq_num = TPS65910_NUM_IRQ; | ||
181 | case TPS65911: | ||
182 | tps65910->irq_num = TPS65911_NUM_IRQ; | ||
183 | } | ||
184 | |||
185 | /* Register with genirq */ | ||
186 | for (cur_irq = tps65910->irq_base; | ||
187 | cur_irq < tps65910->irq_num + tps65910->irq_base; | ||
188 | cur_irq++) { | ||
189 | irq_set_chip_data(cur_irq, tps65910); | ||
190 | irq_set_chip_and_handler(cur_irq, &tps65910_irq_chip, | ||
191 | handle_edge_irq); | ||
192 | irq_set_nested_thread(cur_irq, 1); | ||
193 | |||
194 | /* ARM needs us to explicitly flag the IRQ as valid | ||
195 | * and will set them noprobe when we do so. */ | ||
196 | #ifdef CONFIG_ARM | ||
197 | set_irq_flags(cur_irq, IRQF_VALID); | ||
198 | #else | ||
199 | irq_set_noprobe(cur_irq); | ||
200 | #endif | ||
201 | } | ||
202 | |||
203 | ret = request_threaded_irq(irq, NULL, tps65910_irq, flags, | ||
204 | "tps65910", tps65910); | ||
205 | |||
206 | irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW); | ||
207 | |||
208 | if (ret != 0) | ||
209 | dev_err(tps65910->dev, "Failed to request IRQ: %d\n", ret); | ||
210 | |||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | int tps65910_irq_exit(struct tps65910 *tps65910) | ||
215 | { | ||
216 | free_irq(tps65910->chip_irq, tps65910); | ||
217 | return 0; | ||
218 | } | ||
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c new file mode 100644 index 000000000000..2229e66d80db --- /dev/null +++ b/drivers/mfd/tps65910.c | |||
@@ -0,0 +1,229 @@ | |||
1 | /* | ||
2 | * tps65910.c -- TI TPS6591x | ||
3 | * | ||
4 | * Copyright 2010 Texas Instruments Inc. | ||
5 | * | ||
6 | * Author: Graeme Gregory <gg@slimlogic.co.uk> | ||
7 | * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/moduleparam.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/gpio.h> | ||
22 | #include <linux/mfd/core.h> | ||
23 | #include <linux/mfd/tps65910.h> | ||
24 | |||
25 | static struct mfd_cell tps65910s[] = { | ||
26 | { | ||
27 | .name = "tps65910-pmic", | ||
28 | }, | ||
29 | { | ||
30 | .name = "tps65910-rtc", | ||
31 | }, | ||
32 | { | ||
33 | .name = "tps65910-power", | ||
34 | }, | ||
35 | }; | ||
36 | |||
37 | |||
38 | static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg, | ||
39 | int bytes, void *dest) | ||
40 | { | ||
41 | struct i2c_client *i2c = tps65910->i2c_client; | ||
42 | struct i2c_msg xfer[2]; | ||
43 | int ret; | ||
44 | |||
45 | /* Write register */ | ||
46 | xfer[0].addr = i2c->addr; | ||
47 | xfer[0].flags = 0; | ||
48 | xfer[0].len = 1; | ||
49 | xfer[0].buf = ® | ||
50 | |||
51 | /* Read data */ | ||
52 | xfer[1].addr = i2c->addr; | ||
53 | xfer[1].flags = I2C_M_RD; | ||
54 | xfer[1].len = bytes; | ||
55 | xfer[1].buf = dest; | ||
56 | |||
57 | ret = i2c_transfer(i2c->adapter, xfer, 2); | ||
58 | if (ret == 2) | ||
59 | ret = 0; | ||
60 | else if (ret >= 0) | ||
61 | ret = -EIO; | ||
62 | |||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg, | ||
67 | int bytes, void *src) | ||
68 | { | ||
69 | struct i2c_client *i2c = tps65910->i2c_client; | ||
70 | /* we add 1 byte for device register */ | ||
71 | u8 msg[TPS65910_MAX_REGISTER + 1]; | ||
72 | int ret; | ||
73 | |||
74 | if (bytes > TPS65910_MAX_REGISTER) | ||
75 | return -EINVAL; | ||
76 | |||
77 | msg[0] = reg; | ||
78 | memcpy(&msg[1], src, bytes); | ||
79 | |||
80 | ret = i2c_master_send(i2c, msg, bytes + 1); | ||
81 | if (ret < 0) | ||
82 | return ret; | ||
83 | if (ret != bytes + 1) | ||
84 | return -EIO; | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask) | ||
89 | { | ||
90 | u8 data; | ||
91 | int err; | ||
92 | |||
93 | mutex_lock(&tps65910->io_mutex); | ||
94 | err = tps65910_i2c_read(tps65910, reg, 1, &data); | ||
95 | if (err) { | ||
96 | dev_err(tps65910->dev, "read from reg %x failed\n", reg); | ||
97 | goto out; | ||
98 | } | ||
99 | |||
100 | data |= mask; | ||
101 | err = tps65910_i2c_write(tps65910, reg, 1, &data); | ||
102 | if (err) | ||
103 | dev_err(tps65910->dev, "write to reg %x failed\n", reg); | ||
104 | |||
105 | out: | ||
106 | mutex_unlock(&tps65910->io_mutex); | ||
107 | return err; | ||
108 | } | ||
109 | EXPORT_SYMBOL_GPL(tps65910_set_bits); | ||
110 | |||
111 | int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask) | ||
112 | { | ||
113 | u8 data; | ||
114 | int err; | ||
115 | |||
116 | mutex_lock(&tps65910->io_mutex); | ||
117 | err = tps65910_i2c_read(tps65910, reg, 1, &data); | ||
118 | if (err) { | ||
119 | dev_err(tps65910->dev, "read from reg %x failed\n", reg); | ||
120 | goto out; | ||
121 | } | ||
122 | |||
123 | data &= mask; | ||
124 | err = tps65910_i2c_write(tps65910, reg, 1, &data); | ||
125 | if (err) | ||
126 | dev_err(tps65910->dev, "write to reg %x failed\n", reg); | ||
127 | |||
128 | out: | ||
129 | mutex_unlock(&tps65910->io_mutex); | ||
130 | return err; | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(tps65910_clear_bits); | ||
133 | |||
134 | static int tps65910_i2c_probe(struct i2c_client *i2c, | ||
135 | const struct i2c_device_id *id) | ||
136 | { | ||
137 | struct tps65910 *tps65910; | ||
138 | struct tps65910_board *pmic_plat_data; | ||
139 | struct tps65910_platform_data *init_data; | ||
140 | int ret = 0; | ||
141 | |||
142 | pmic_plat_data = dev_get_platdata(&i2c->dev); | ||
143 | if (!pmic_plat_data) | ||
144 | return -EINVAL; | ||
145 | |||
146 | init_data = kzalloc(sizeof(struct tps65910_platform_data), GFP_KERNEL); | ||
147 | if (init_data == NULL) | ||
148 | return -ENOMEM; | ||
149 | |||
150 | init_data->irq = pmic_plat_data->irq; | ||
151 | init_data->irq_base = pmic_plat_data->irq; | ||
152 | |||
153 | tps65910 = kzalloc(sizeof(struct tps65910), GFP_KERNEL); | ||
154 | if (tps65910 == NULL) | ||
155 | return -ENOMEM; | ||
156 | |||
157 | i2c_set_clientdata(i2c, tps65910); | ||
158 | tps65910->dev = &i2c->dev; | ||
159 | tps65910->i2c_client = i2c; | ||
160 | tps65910->id = id->driver_data; | ||
161 | tps65910->read = tps65910_i2c_read; | ||
162 | tps65910->write = tps65910_i2c_write; | ||
163 | mutex_init(&tps65910->io_mutex); | ||
164 | |||
165 | ret = mfd_add_devices(tps65910->dev, -1, | ||
166 | tps65910s, ARRAY_SIZE(tps65910s), | ||
167 | NULL, 0); | ||
168 | if (ret < 0) | ||
169 | goto err; | ||
170 | |||
171 | tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base); | ||
172 | |||
173 | ret = tps65910_irq_init(tps65910, init_data->irq, init_data); | ||
174 | if (ret < 0) | ||
175 | goto err; | ||
176 | |||
177 | return ret; | ||
178 | |||
179 | err: | ||
180 | mfd_remove_devices(tps65910->dev); | ||
181 | kfree(tps65910); | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | static int tps65910_i2c_remove(struct i2c_client *i2c) | ||
186 | { | ||
187 | struct tps65910 *tps65910 = i2c_get_clientdata(i2c); | ||
188 | |||
189 | mfd_remove_devices(tps65910->dev); | ||
190 | kfree(tps65910); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static const struct i2c_device_id tps65910_i2c_id[] = { | ||
196 | { "tps65910", TPS65910 }, | ||
197 | { "tps65911", TPS65911 }, | ||
198 | { } | ||
199 | }; | ||
200 | MODULE_DEVICE_TABLE(i2c, tps65910_i2c_id); | ||
201 | |||
202 | |||
203 | static struct i2c_driver tps65910_i2c_driver = { | ||
204 | .driver = { | ||
205 | .name = "tps65910", | ||
206 | .owner = THIS_MODULE, | ||
207 | }, | ||
208 | .probe = tps65910_i2c_probe, | ||
209 | .remove = tps65910_i2c_remove, | ||
210 | .id_table = tps65910_i2c_id, | ||
211 | }; | ||
212 | |||
213 | static int __init tps65910_i2c_init(void) | ||
214 | { | ||
215 | return i2c_add_driver(&tps65910_i2c_driver); | ||
216 | } | ||
217 | /* init early so consumer devices can complete system boot */ | ||
218 | subsys_initcall(tps65910_i2c_init); | ||
219 | |||
220 | static void __exit tps65910_i2c_exit(void) | ||
221 | { | ||
222 | i2c_del_driver(&tps65910_i2c_driver); | ||
223 | } | ||
224 | module_exit(tps65910_i2c_exit); | ||
225 | |||
226 | MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); | ||
227 | MODULE_AUTHOR("Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>"); | ||
228 | MODULE_DESCRIPTION("TPS6591x chip family multi-function driver"); | ||
229 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/tps65911-comparator.c b/drivers/mfd/tps65911-comparator.c new file mode 100644 index 000000000000..3d2dc56a3d40 --- /dev/null +++ b/drivers/mfd/tps65911-comparator.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * tps65910.c -- TI TPS6591x | ||
3 | * | ||
4 | * Copyright 2010 Texas Instruments Inc. | ||
5 | * | ||
6 | * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/debugfs.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/mfd/tps65910.h> | ||
24 | |||
25 | #define COMP 0 | ||
26 | #define COMP1 1 | ||
27 | #define COMP2 2 | ||
28 | |||
29 | /* Comparator 1 voltage selection table in milivolts */ | ||
30 | static const u16 COMP_VSEL_TABLE[] = { | ||
31 | 0, 2500, 2500, 2500, 2500, 2550, 2600, 2650, | ||
32 | 2700, 2750, 2800, 2850, 2900, 2950, 3000, 3050, | ||
33 | 3100, 3150, 3200, 3250, 3300, 3350, 3400, 3450, | ||
34 | 3500, | ||
35 | }; | ||
36 | |||
37 | struct comparator { | ||
38 | const char *name; | ||
39 | int reg; | ||
40 | int uV_max; | ||
41 | const u16 *vsel_table; | ||
42 | }; | ||
43 | |||
44 | static struct comparator tps_comparators[] = { | ||
45 | { | ||
46 | .name = "COMP1", | ||
47 | .reg = TPS65911_VMBCH, | ||
48 | .uV_max = 3500, | ||
49 | .vsel_table = COMP_VSEL_TABLE, | ||
50 | }, | ||
51 | { | ||
52 | .name = "COMP2", | ||
53 | .reg = TPS65911_VMBCH2, | ||
54 | .uV_max = 3500, | ||
55 | .vsel_table = COMP_VSEL_TABLE, | ||
56 | }, | ||
57 | }; | ||
58 | |||
59 | static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage) | ||
60 | { | ||
61 | struct comparator tps_comp = tps_comparators[id]; | ||
62 | int curr_voltage = 0; | ||
63 | int ret; | ||
64 | u8 index = 0, val; | ||
65 | |||
66 | if (id == COMP) | ||
67 | return 0; | ||
68 | |||
69 | while (curr_voltage < tps_comp.uV_max) { | ||
70 | curr_voltage = tps_comp.vsel_table[index]; | ||
71 | if (curr_voltage >= voltage) | ||
72 | break; | ||
73 | else if (curr_voltage < voltage) | ||
74 | index ++; | ||
75 | } | ||
76 | |||
77 | if (curr_voltage > tps_comp.uV_max) | ||
78 | return -EINVAL; | ||
79 | |||
80 | val = index << 1; | ||
81 | ret = tps65910->write(tps65910, tps_comp.reg, 1, &val); | ||
82 | |||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static int comp_threshold_get(struct tps65910 *tps65910, int id) | ||
87 | { | ||
88 | struct comparator tps_comp = tps_comparators[id]; | ||
89 | int ret; | ||
90 | u8 val; | ||
91 | |||
92 | if (id == COMP) | ||
93 | return 0; | ||
94 | |||
95 | ret = tps65910->read(tps65910, tps_comp.reg, 1, &val); | ||
96 | if (ret < 0) | ||
97 | return ret; | ||
98 | |||
99 | val >>= 1; | ||
100 | return tps_comp.vsel_table[val]; | ||
101 | } | ||
102 | |||
103 | static ssize_t comp_threshold_show(struct device *dev, | ||
104 | struct device_attribute *attr, char *buf) | ||
105 | { | ||
106 | struct tps65910 *tps65910 = dev_get_drvdata(dev->parent); | ||
107 | struct attribute comp_attr = attr->attr; | ||
108 | int id, uVolt; | ||
109 | |||
110 | if (!strcmp(comp_attr.name, "comp1_threshold")) | ||
111 | id = COMP1; | ||
112 | else if (!strcmp(comp_attr.name, "comp2_threshold")) | ||
113 | id = COMP2; | ||
114 | else | ||
115 | return -EINVAL; | ||
116 | |||
117 | uVolt = comp_threshold_get(tps65910, id); | ||
118 | |||
119 | return sprintf(buf, "%d\n", uVolt); | ||
120 | } | ||
121 | |||
122 | static DEVICE_ATTR(comp1_threshold, S_IRUGO, comp_threshold_show, NULL); | ||
123 | static DEVICE_ATTR(comp2_threshold, S_IRUGO, comp_threshold_show, NULL); | ||
124 | |||
125 | static __devinit int tps65911_comparator_probe(struct platform_device *pdev) | ||
126 | { | ||
127 | struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); | ||
128 | struct tps65910_platform_data *pdata = dev_get_platdata(tps65910->dev); | ||
129 | int ret; | ||
130 | |||
131 | ret = comp_threshold_set(tps65910, COMP1, pdata->vmbch_threshold); | ||
132 | if (ret < 0) { | ||
133 | dev_err(&pdev->dev, "cannot set COMP1 threshold\n"); | ||
134 | return ret; | ||
135 | } | ||
136 | |||
137 | ret = comp_threshold_set(tps65910, COMP2, pdata->vmbch2_threshold); | ||
138 | if (ret < 0) { | ||
139 | dev_err(&pdev->dev, "cannot set COMP2 theshold\n"); | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | /* Create sysfs entry */ | ||
144 | ret = device_create_file(&pdev->dev, &dev_attr_comp1_threshold); | ||
145 | if (ret < 0) | ||
146 | dev_err(&pdev->dev, "failed to add COMP1 sysfs file\n"); | ||
147 | |||
148 | ret = device_create_file(&pdev->dev, &dev_attr_comp2_threshold); | ||
149 | if (ret < 0) | ||
150 | dev_err(&pdev->dev, "failed to add COMP2 sysfs file\n"); | ||
151 | |||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | static __devexit int tps65911_comparator_remove(struct platform_device *pdev) | ||
156 | { | ||
157 | struct tps65910 *tps65910; | ||
158 | |||
159 | tps65910 = dev_get_drvdata(pdev->dev.parent); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static struct platform_driver tps65911_comparator_driver = { | ||
165 | .driver = { | ||
166 | .name = "tps65911-comparator", | ||
167 | .owner = THIS_MODULE, | ||
168 | }, | ||
169 | .probe = tps65911_comparator_probe, | ||
170 | .remove = __devexit_p(tps65911_comparator_remove), | ||
171 | }; | ||
172 | |||
173 | static int __init tps65911_comparator_init(void) | ||
174 | { | ||
175 | return platform_driver_register(&tps65911_comparator_driver); | ||
176 | } | ||
177 | subsys_initcall(tps65911_comparator_init); | ||
178 | |||
179 | static void __exit tps65911_comparator_exit(void) | ||
180 | { | ||
181 | platform_driver_unregister(&tps65911_comparator_driver); | ||
182 | } | ||
183 | module_exit(tps65911_comparator_exit); | ||
184 | |||
185 | MODULE_AUTHOR("Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>"); | ||
186 | MODULE_DESCRIPTION("TPS65911 comparator driver"); | ||
187 | MODULE_LICENSE("GPL v2"); | ||
188 | MODULE_ALIAS("platform:tps65911-comparator"); | ||
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 74f16f167b8e..b0c56313dbbb 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c | |||
@@ -285,33 +285,26 @@ static void hw_break_val_write(void) | |||
285 | static int check_and_rewind_pc(char *put_str, char *arg) | 285 | static int check_and_rewind_pc(char *put_str, char *arg) |
286 | { | 286 | { |
287 | unsigned long addr = lookup_addr(arg); | 287 | unsigned long addr = lookup_addr(arg); |
288 | unsigned long ip; | ||
288 | int offset = 0; | 289 | int offset = 0; |
289 | 290 | ||
290 | kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs, | 291 | kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs, |
291 | NUMREGBYTES); | 292 | NUMREGBYTES); |
292 | gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs); | 293 | gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs); |
293 | v2printk("Stopped at IP: %lx\n", instruction_pointer(&kgdbts_regs)); | 294 | ip = instruction_pointer(&kgdbts_regs); |
294 | #ifdef CONFIG_X86 | 295 | v2printk("Stopped at IP: %lx\n", ip); |
295 | /* On x86 a breakpoint stop requires it to be decremented */ | 296 | #ifdef GDB_ADJUSTS_BREAK_OFFSET |
296 | if (addr + 1 == kgdbts_regs.ip) | 297 | /* On some arches, a breakpoint stop requires it to be decremented */ |
297 | offset = -1; | 298 | if (addr + BREAK_INSTR_SIZE == ip) |
298 | #elif defined(CONFIG_SUPERH) | 299 | offset = -BREAK_INSTR_SIZE; |
299 | /* On SUPERH a breakpoint stop requires it to be decremented */ | ||
300 | if (addr + 2 == kgdbts_regs.pc) | ||
301 | offset = -2; | ||
302 | #endif | 300 | #endif |
303 | if (strcmp(arg, "silent") && | 301 | if (strcmp(arg, "silent") && ip + offset != addr) { |
304 | instruction_pointer(&kgdbts_regs) + offset != addr) { | ||
305 | eprintk("kgdbts: BP mismatch %lx expected %lx\n", | 302 | eprintk("kgdbts: BP mismatch %lx expected %lx\n", |
306 | instruction_pointer(&kgdbts_regs) + offset, addr); | 303 | ip + offset, addr); |
307 | return 1; | 304 | return 1; |
308 | } | 305 | } |
309 | #ifdef CONFIG_X86 | 306 | /* Readjust the instruction pointer if needed */ |
310 | /* On x86 adjust the instruction pointer if needed */ | 307 | instruction_pointer_set(&kgdbts_regs, ip + offset); |
311 | kgdbts_regs.ip += offset; | ||
312 | #elif defined(CONFIG_SUPERH) | ||
313 | kgdbts_regs.pc += offset; | ||
314 | #endif | ||
315 | return 0; | 308 | return 0; |
316 | } | 309 | } |
317 | 310 | ||
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 4941e06fe2e1..5da5bea0f9f0 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -51,6 +51,7 @@ static unsigned int fmax = 515633; | |||
51 | * is asserted (likewise for RX) | 51 | * is asserted (likewise for RX) |
52 | * @sdio: variant supports SDIO | 52 | * @sdio: variant supports SDIO |
53 | * @st_clkdiv: true if using a ST-specific clock divider algorithm | 53 | * @st_clkdiv: true if using a ST-specific clock divider algorithm |
54 | * @blksz_datactrl16: true if Block size is at b16..b30 position in datactrl register | ||
54 | */ | 55 | */ |
55 | struct variant_data { | 56 | struct variant_data { |
56 | unsigned int clkreg; | 57 | unsigned int clkreg; |
@@ -60,6 +61,7 @@ struct variant_data { | |||
60 | unsigned int fifohalfsize; | 61 | unsigned int fifohalfsize; |
61 | bool sdio; | 62 | bool sdio; |
62 | bool st_clkdiv; | 63 | bool st_clkdiv; |
64 | bool blksz_datactrl16; | ||
63 | }; | 65 | }; |
64 | 66 | ||
65 | static struct variant_data variant_arm = { | 67 | static struct variant_data variant_arm = { |
@@ -92,6 +94,17 @@ static struct variant_data variant_ux500 = { | |||
92 | .st_clkdiv = true, | 94 | .st_clkdiv = true, |
93 | }; | 95 | }; |
94 | 96 | ||
97 | static struct variant_data variant_ux500v2 = { | ||
98 | .fifosize = 30 * 4, | ||
99 | .fifohalfsize = 8 * 4, | ||
100 | .clkreg = MCI_CLK_ENABLE, | ||
101 | .clkreg_enable = MCI_ST_UX500_HWFCEN, | ||
102 | .datalength_bits = 24, | ||
103 | .sdio = true, | ||
104 | .st_clkdiv = true, | ||
105 | .blksz_datactrl16 = true, | ||
106 | }; | ||
107 | |||
95 | /* | 108 | /* |
96 | * This must be called with host->lock held | 109 | * This must be called with host->lock held |
97 | */ | 110 | */ |
@@ -465,7 +478,10 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | |||
465 | blksz_bits = ffs(data->blksz) - 1; | 478 | blksz_bits = ffs(data->blksz) - 1; |
466 | BUG_ON(1 << blksz_bits != data->blksz); | 479 | BUG_ON(1 << blksz_bits != data->blksz); |
467 | 480 | ||
468 | datactrl = MCI_DPSM_ENABLE | blksz_bits << 4; | 481 | if (variant->blksz_datactrl16) |
482 | datactrl = MCI_DPSM_ENABLE | (data->blksz << 16); | ||
483 | else | ||
484 | datactrl = MCI_DPSM_ENABLE | blksz_bits << 4; | ||
469 | 485 | ||
470 | if (data->flags & MMC_DATA_READ) | 486 | if (data->flags & MMC_DATA_READ) |
471 | datactrl |= MCI_DPSM_DIRECTION; | 487 | datactrl |= MCI_DPSM_DIRECTION; |
@@ -1311,9 +1327,14 @@ static struct amba_id mmci_ids[] = { | |||
1311 | }, | 1327 | }, |
1312 | { | 1328 | { |
1313 | .id = 0x00480180, | 1329 | .id = 0x00480180, |
1314 | .mask = 0x00ffffff, | 1330 | .mask = 0xf0ffffff, |
1315 | .data = &variant_ux500, | 1331 | .data = &variant_ux500, |
1316 | }, | 1332 | }, |
1333 | { | ||
1334 | .id = 0x10480180, | ||
1335 | .mask = 0xf0ffffff, | ||
1336 | .data = &variant_ux500v2, | ||
1337 | }, | ||
1317 | { 0, 0 }, | 1338 | { 0, 0 }, |
1318 | }; | 1339 | }; |
1319 | 1340 | ||
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index bc50d5ea5534..4be8373d43e5 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
@@ -33,20 +33,6 @@ config MTD_TESTS | |||
33 | should normally be compiled as kernel modules. The modules perform | 33 | should normally be compiled as kernel modules. The modules perform |
34 | various checks and verifications when loaded. | 34 | various checks and verifications when loaded. |
35 | 35 | ||
36 | config MTD_PARTITIONS | ||
37 | bool "MTD partitioning support" | ||
38 | help | ||
39 | If you have a device which needs to divide its flash chip(s) up | ||
40 | into multiple 'partitions', each of which appears to the user as | ||
41 | a separate MTD device, you require this option to be enabled. If | ||
42 | unsure, say 'Y'. | ||
43 | |||
44 | Note, however, that you don't need this option for the DiskOnChip | ||
45 | devices. Partitioning on NFTL 'devices' is a different - that's the | ||
46 | 'normal' form of partitioning used on a block device. | ||
47 | |||
48 | if MTD_PARTITIONS | ||
49 | |||
50 | config MTD_REDBOOT_PARTS | 36 | config MTD_REDBOOT_PARTS |
51 | tristate "RedBoot partition table parsing" | 37 | tristate "RedBoot partition table parsing" |
52 | ---help--- | 38 | ---help--- |
@@ -99,7 +85,7 @@ endif # MTD_REDBOOT_PARTS | |||
99 | 85 | ||
100 | config MTD_CMDLINE_PARTS | 86 | config MTD_CMDLINE_PARTS |
101 | bool "Command line partition table parsing" | 87 | bool "Command line partition table parsing" |
102 | depends on MTD_PARTITIONS = "y" && MTD = "y" | 88 | depends on MTD = "y" |
103 | ---help--- | 89 | ---help--- |
104 | Allow generic configuration of the MTD partition tables via the kernel | 90 | Allow generic configuration of the MTD partition tables via the kernel |
105 | command line. Multiple flash resources are supported for hardware where | 91 | command line. Multiple flash resources are supported for hardware where |
@@ -163,8 +149,6 @@ config MTD_AR7_PARTS | |||
163 | ---help--- | 149 | ---help--- |
164 | TI AR7 partitioning support | 150 | TI AR7 partitioning support |
165 | 151 | ||
166 | endif # MTD_PARTITIONS | ||
167 | |||
168 | comment "User Modules And Translation Layers" | 152 | comment "User Modules And Translation Layers" |
169 | 153 | ||
170 | config MTD_CHAR | 154 | config MTD_CHAR |
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index d578095fb255..39664c4229ff 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile | |||
@@ -4,8 +4,7 @@ | |||
4 | 4 | ||
5 | # Core functionality. | 5 | # Core functionality. |
6 | obj-$(CONFIG_MTD) += mtd.o | 6 | obj-$(CONFIG_MTD) += mtd.o |
7 | mtd-y := mtdcore.o mtdsuper.o mtdconcat.o | 7 | mtd-y := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o |
8 | mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o | ||
9 | mtd-$(CONFIG_MTD_OF_PARTS) += ofpart.o | 8 | mtd-$(CONFIG_MTD_OF_PARTS) += ofpart.o |
10 | 9 | ||
11 | obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o | 10 | obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o |
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 09cb7c8d93b4..e1e122f2f929 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -812,12 +812,9 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long | |||
812 | break; | 812 | break; |
813 | 813 | ||
814 | if (time_after(jiffies, timeo)) { | 814 | if (time_after(jiffies, timeo)) { |
815 | /* Urgh. Resume and pretend we weren't here. */ | 815 | /* Urgh. Resume and pretend we weren't here. |
816 | map_write(map, CMD(0xd0), adr); | 816 | * Make sure we're in 'read status' mode if it had finished */ |
817 | /* Make sure we're in 'read status' mode if it had finished */ | 817 | put_chip(map, chip, adr); |
818 | map_write(map, CMD(0x70), adr); | ||
819 | chip->state = FL_ERASING; | ||
820 | chip->oldstate = FL_READY; | ||
821 | printk(KERN_ERR "%s: Chip not ready after erase " | 818 | printk(KERN_ERR "%s: Chip not ready after erase " |
822 | "suspended: status = 0x%lx\n", map->name, status.x[0]); | 819 | "suspended: status = 0x%lx\n", map->name, status.x[0]); |
823 | return -EIO; | 820 | return -EIO; |
@@ -997,7 +994,6 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
997 | 994 | ||
998 | switch(chip->oldstate) { | 995 | switch(chip->oldstate) { |
999 | case FL_ERASING: | 996 | case FL_ERASING: |
1000 | chip->state = chip->oldstate; | ||
1001 | /* What if one interleaved chip has finished and the | 997 | /* What if one interleaved chip has finished and the |
1002 | other hasn't? The old code would leave the finished | 998 | other hasn't? The old code would leave the finished |
1003 | one in READY mode. That's bad, and caused -EROFS | 999 | one in READY mode. That's bad, and caused -EROFS |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 0b49266840b9..23175edd5634 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -462,13 +462,14 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | |||
462 | cfi_fixup_major_minor(cfi, extp); | 462 | cfi_fixup_major_minor(cfi, extp); |
463 | 463 | ||
464 | /* | 464 | /* |
465 | * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4 | 465 | * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5 |
466 | * see: http://cs.ozerki.net/zap/pub/axim-x5/docs/cfi_r20.pdf, page 19 | 466 | * see: http://cs.ozerki.net/zap/pub/axim-x5/docs/cfi_r20.pdf, page 19 |
467 | * http://www.spansion.com/Support/AppNotes/cfi_100_20011201.pdf | 467 | * http://www.spansion.com/Support/AppNotes/cfi_100_20011201.pdf |
468 | * http://www.spansion.com/Support/Datasheets/s29ws-p_00_a12_e.pdf | 468 | * http://www.spansion.com/Support/Datasheets/s29ws-p_00_a12_e.pdf |
469 | * http://www.spansion.com/Support/Datasheets/S29GL_128S_01GS_00_02_e.pdf | ||
469 | */ | 470 | */ |
470 | if (extp->MajorVersion != '1' || | 471 | if (extp->MajorVersion != '1' || |
471 | (extp->MajorVersion == '1' && (extp->MinorVersion < '0' || extp->MinorVersion > '4'))) { | 472 | (extp->MajorVersion == '1' && (extp->MinorVersion < '0' || extp->MinorVersion > '5'))) { |
472 | printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " | 473 | printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " |
473 | "version %c.%c (%#02x/%#02x).\n", | 474 | "version %c.%c (%#02x/%#02x).\n", |
474 | extp->MajorVersion, extp->MinorVersion, | 475 | extp->MajorVersion, extp->MinorVersion, |
@@ -710,9 +711,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
710 | * there was an error (so leave the erase | 711 | * there was an error (so leave the erase |
711 | * routine to recover from it) or we trying to | 712 | * routine to recover from it) or we trying to |
712 | * use the erase-in-progress sector. */ | 713 | * use the erase-in-progress sector. */ |
713 | map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); | 714 | put_chip(map, chip, adr); |
714 | chip->state = FL_ERASING; | ||
715 | chip->oldstate = FL_READY; | ||
716 | printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); | 715 | printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); |
717 | return -EIO; | 716 | return -EIO; |
718 | } | 717 | } |
@@ -762,7 +761,6 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
762 | 761 | ||
763 | switch(chip->oldstate) { | 762 | switch(chip->oldstate) { |
764 | case FL_ERASING: | 763 | case FL_ERASING: |
765 | chip->state = chip->oldstate; | ||
766 | map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); | 764 | map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); |
767 | chip->oldstate = FL_READY; | 765 | chip->oldstate = FL_READY; |
768 | chip->state = FL_ERASING; | 766 | chip->state = FL_ERASING; |
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index ed56ad3884fb..179814a95f3a 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c | |||
@@ -296,6 +296,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof | |||
296 | /* make sure we're in 'read status' mode */ | 296 | /* make sure we're in 'read status' mode */ |
297 | map_write(map, CMD(0x70), cmd_addr); | 297 | map_write(map, CMD(0x70), cmd_addr); |
298 | chip->state = FL_ERASING; | 298 | chip->state = FL_ERASING; |
299 | wake_up(&chip->wq); | ||
299 | mutex_unlock(&chip->mutex); | 300 | mutex_unlock(&chip->mutex); |
300 | printk(KERN_ERR "Chip not ready after erase " | 301 | printk(KERN_ERR "Chip not ready after erase " |
301 | "suspended: status = 0x%lx\n", status.x[0]); | 302 | "suspended: status = 0x%lx\n", status.x[0]); |
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 97183c8c9e33..b78f23169d4e 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -294,7 +294,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
294 | dev->mtd.priv = dev; | 294 | dev->mtd.priv = dev; |
295 | dev->mtd.owner = THIS_MODULE; | 295 | dev->mtd.owner = THIS_MODULE; |
296 | 296 | ||
297 | if (add_mtd_device(&dev->mtd)) { | 297 | if (mtd_device_register(&dev->mtd, NULL, 0)) { |
298 | /* Device didn't get added, so free the entry */ | 298 | /* Device didn't get added, so free the entry */ |
299 | goto devinit_err; | 299 | goto devinit_err; |
300 | } | 300 | } |
@@ -465,7 +465,7 @@ static void __devexit block2mtd_exit(void) | |||
465 | list_for_each_safe(pos, next, &blkmtd_device_list) { | 465 | list_for_each_safe(pos, next, &blkmtd_device_list) { |
466 | struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list); | 466 | struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list); |
467 | block2mtd_sync(&dev->mtd); | 467 | block2mtd_sync(&dev->mtd); |
468 | del_mtd_device(&dev->mtd); | 468 | mtd_device_unregister(&dev->mtd); |
469 | INFO("mtd%d: [%s] removed", dev->mtd.index, | 469 | INFO("mtd%d: [%s] removed", dev->mtd.index, |
470 | dev->mtd.name + strlen("block2mtd: ")); | 470 | dev->mtd.name + strlen("block2mtd: ")); |
471 | list_del(&dev->list); | 471 | list_del(&dev->list); |
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index 5bf5f460e132..f7fbf6025ef2 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c | |||
@@ -597,7 +597,7 @@ void DoC2k_init(struct mtd_info *mtd) | |||
597 | doc2klist = mtd; | 597 | doc2klist = mtd; |
598 | mtd->size = this->totlen; | 598 | mtd->size = this->totlen; |
599 | mtd->erasesize = this->erasesize; | 599 | mtd->erasesize = this->erasesize; |
600 | add_mtd_device(mtd); | 600 | mtd_device_register(mtd, NULL, 0); |
601 | return; | 601 | return; |
602 | } | 602 | } |
603 | } | 603 | } |
@@ -1185,7 +1185,7 @@ static void __exit cleanup_doc2000(void) | |||
1185 | this = mtd->priv; | 1185 | this = mtd->priv; |
1186 | doc2klist = this->nextdoc; | 1186 | doc2klist = this->nextdoc; |
1187 | 1187 | ||
1188 | del_mtd_device(mtd); | 1188 | mtd_device_unregister(mtd); |
1189 | 1189 | ||
1190 | iounmap(this->virtadr); | 1190 | iounmap(this->virtadr); |
1191 | kfree(this->chips); | 1191 | kfree(this->chips); |
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index 0990f7803628..241192f05bc8 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c | |||
@@ -376,7 +376,7 @@ void DoCMil_init(struct mtd_info *mtd) | |||
376 | this->nextdoc = docmillist; | 376 | this->nextdoc = docmillist; |
377 | docmillist = mtd; | 377 | docmillist = mtd; |
378 | mtd->size = this->totlen; | 378 | mtd->size = this->totlen; |
379 | add_mtd_device(mtd); | 379 | mtd_device_register(mtd, NULL, 0); |
380 | return; | 380 | return; |
381 | } | 381 | } |
382 | } | 382 | } |
@@ -826,7 +826,7 @@ static void __exit cleanup_doc2001(void) | |||
826 | this = mtd->priv; | 826 | this = mtd->priv; |
827 | docmillist = this->nextdoc; | 827 | docmillist = this->nextdoc; |
828 | 828 | ||
829 | del_mtd_device(mtd); | 829 | mtd_device_unregister(mtd); |
830 | 830 | ||
831 | iounmap(this->virtadr); | 831 | iounmap(this->virtadr); |
832 | kfree(this->chips); | 832 | kfree(this->chips); |
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index 8b36fa77a195..09ae0adc3ad0 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c | |||
@@ -499,7 +499,7 @@ void DoCMilPlus_init(struct mtd_info *mtd) | |||
499 | docmilpluslist = mtd; | 499 | docmilpluslist = mtd; |
500 | mtd->size = this->totlen; | 500 | mtd->size = this->totlen; |
501 | mtd->erasesize = this->erasesize; | 501 | mtd->erasesize = this->erasesize; |
502 | add_mtd_device(mtd); | 502 | mtd_device_register(mtd, NULL, 0); |
503 | return; | 503 | return; |
504 | } | 504 | } |
505 | } | 505 | } |
@@ -1091,7 +1091,7 @@ static void __exit cleanup_doc2001plus(void) | |||
1091 | this = mtd->priv; | 1091 | this = mtd->priv; |
1092 | docmilpluslist = this->nextdoc; | 1092 | docmilpluslist = this->nextdoc; |
1093 | 1093 | ||
1094 | del_mtd_device(mtd); | 1094 | mtd_device_unregister(mtd); |
1095 | 1095 | ||
1096 | iounmap(this->virtadr); | 1096 | iounmap(this->virtadr); |
1097 | kfree(this->chips); | 1097 | kfree(this->chips); |
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c index 4b829f97d56c..772a0ff89e0f 100644 --- a/drivers/mtd/devices/lart.c +++ b/drivers/mtd/devices/lart.c | |||
@@ -684,9 +684,10 @@ static int __init lart_flash_init (void) | |||
684 | #endif | 684 | #endif |
685 | 685 | ||
686 | #ifndef HAVE_PARTITIONS | 686 | #ifndef HAVE_PARTITIONS |
687 | result = add_mtd_device (&mtd); | 687 | result = mtd_device_register(&mtd, NULL, 0); |
688 | #else | 688 | #else |
689 | result = add_mtd_partitions (&mtd,lart_partitions, ARRAY_SIZE(lart_partitions)); | 689 | result = mtd_device_register(&mtd, lart_partitions, |
690 | ARRAY_SIZE(lart_partitions)); | ||
690 | #endif | 691 | #endif |
691 | 692 | ||
692 | return (result); | 693 | return (result); |
@@ -695,9 +696,9 @@ static int __init lart_flash_init (void) | |||
695 | static void __exit lart_flash_exit (void) | 696 | static void __exit lart_flash_exit (void) |
696 | { | 697 | { |
697 | #ifndef HAVE_PARTITIONS | 698 | #ifndef HAVE_PARTITIONS |
698 | del_mtd_device (&mtd); | 699 | mtd_device_unregister(&mtd); |
699 | #else | 700 | #else |
700 | del_mtd_partitions (&mtd); | 701 | mtd_device_unregister(&mtd); |
701 | #endif | 702 | #endif |
702 | } | 703 | } |
703 | 704 | ||
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 3fb981d4bb51..35180e475c4c 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
28 | #include <linux/mod_devicetable.h> | 28 | #include <linux/mod_devicetable.h> |
29 | 29 | ||
30 | #include <linux/mtd/cfi.h> | ||
30 | #include <linux/mtd/mtd.h> | 31 | #include <linux/mtd/mtd.h> |
31 | #include <linux/mtd/partitions.h> | 32 | #include <linux/mtd/partitions.h> |
32 | 33 | ||
@@ -55,6 +56,9 @@ | |||
55 | #define OPCODE_EN4B 0xb7 /* Enter 4-byte mode */ | 56 | #define OPCODE_EN4B 0xb7 /* Enter 4-byte mode */ |
56 | #define OPCODE_EX4B 0xe9 /* Exit 4-byte mode */ | 57 | #define OPCODE_EX4B 0xe9 /* Exit 4-byte mode */ |
57 | 58 | ||
59 | /* Used for Spansion flashes only. */ | ||
60 | #define OPCODE_BRWR 0x17 /* Bank register write */ | ||
61 | |||
58 | /* Status Register bits. */ | 62 | /* Status Register bits. */ |
59 | #define SR_WIP 1 /* Write in progress */ | 63 | #define SR_WIP 1 /* Write in progress */ |
60 | #define SR_WEL 2 /* Write enable latch */ | 64 | #define SR_WEL 2 /* Write enable latch */ |
@@ -76,6 +80,8 @@ | |||
76 | #define FAST_READ_DUMMY_BYTE 0 | 80 | #define FAST_READ_DUMMY_BYTE 0 |
77 | #endif | 81 | #endif |
78 | 82 | ||
83 | #define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) | ||
84 | |||
79 | /****************************************************************************/ | 85 | /****************************************************************************/ |
80 | 86 | ||
81 | struct m25p { | 87 | struct m25p { |
@@ -158,11 +164,18 @@ static inline int write_disable(struct m25p *flash) | |||
158 | /* | 164 | /* |
159 | * Enable/disable 4-byte addressing mode. | 165 | * Enable/disable 4-byte addressing mode. |
160 | */ | 166 | */ |
161 | static inline int set_4byte(struct m25p *flash, int enable) | 167 | static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable) |
162 | { | 168 | { |
163 | u8 code = enable ? OPCODE_EN4B : OPCODE_EX4B; | 169 | switch (JEDEC_MFR(jedec_id)) { |
164 | 170 | case CFI_MFR_MACRONIX: | |
165 | return spi_write_then_read(flash->spi, &code, 1, NULL, 0); | 171 | flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; |
172 | return spi_write(flash->spi, flash->command, 1); | ||
173 | default: | ||
174 | /* Spansion style */ | ||
175 | flash->command[0] = OPCODE_BRWR; | ||
176 | flash->command[1] = enable << 7; | ||
177 | return spi_write(flash->spi, flash->command, 2); | ||
178 | } | ||
166 | } | 179 | } |
167 | 180 | ||
168 | /* | 181 | /* |
@@ -668,6 +681,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
668 | /* Macronix */ | 681 | /* Macronix */ |
669 | { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, | 682 | { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, |
670 | { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, | 683 | { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, |
684 | { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, | ||
671 | { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, | 685 | { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, |
672 | { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, | 686 | { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, |
673 | { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, | 687 | { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, |
@@ -684,6 +698,10 @@ static const struct spi_device_id m25p_ids[] = { | |||
684 | { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, | 698 | { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, |
685 | { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SECT_4K) }, | 699 | { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SECT_4K) }, |
686 | { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, | 700 | { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, |
701 | { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, | ||
702 | { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, 0) }, | ||
703 | { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) }, | ||
704 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, | ||
687 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, | 705 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, |
688 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, | 706 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, |
689 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, | 707 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, |
@@ -729,7 +747,10 @@ static const struct spi_device_id m25p_ids[] = { | |||
729 | { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) }, | 747 | { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) }, |
730 | { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) }, | 748 | { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) }, |
731 | 749 | ||
732 | { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, | 750 | { "m25px32", INFO(0x207116, 0, 64 * 1024, 64, SECT_4K) }, |
751 | { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K) }, | ||
752 | { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K) }, | ||
753 | { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, | ||
733 | 754 | ||
734 | /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ | 755 | /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ |
735 | { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, | 756 | { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, |
@@ -804,6 +825,8 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
804 | struct m25p *flash; | 825 | struct m25p *flash; |
805 | struct flash_info *info; | 826 | struct flash_info *info; |
806 | unsigned i; | 827 | unsigned i; |
828 | struct mtd_partition *parts = NULL; | ||
829 | int nr_parts = 0; | ||
807 | 830 | ||
808 | /* Platform data helps sort out which chip type we have, as | 831 | /* Platform data helps sort out which chip type we have, as |
809 | * well as how this board partitions it. If we don't have | 832 | * well as how this board partitions it. If we don't have |
@@ -868,9 +891,9 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
868 | * up with the software protection bits set | 891 | * up with the software protection bits set |
869 | */ | 892 | */ |
870 | 893 | ||
871 | if (info->jedec_id >> 16 == 0x1f || | 894 | if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL || |
872 | info->jedec_id >> 16 == 0x89 || | 895 | JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL || |
873 | info->jedec_id >> 16 == 0xbf) { | 896 | JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) { |
874 | write_enable(flash); | 897 | write_enable(flash); |
875 | write_sr(flash, 0); | 898 | write_sr(flash, 0); |
876 | } | 899 | } |
@@ -888,7 +911,7 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
888 | flash->mtd.read = m25p80_read; | 911 | flash->mtd.read = m25p80_read; |
889 | 912 | ||
890 | /* sst flash chips use AAI word program */ | 913 | /* sst flash chips use AAI word program */ |
891 | if (info->jedec_id >> 16 == 0xbf) | 914 | if (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) |
892 | flash->mtd.write = sst_write; | 915 | flash->mtd.write = sst_write; |
893 | else | 916 | else |
894 | flash->mtd.write = m25p80_write; | 917 | flash->mtd.write = m25p80_write; |
@@ -914,7 +937,7 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
914 | /* enable 4-byte addressing if the device exceeds 16MiB */ | 937 | /* enable 4-byte addressing if the device exceeds 16MiB */ |
915 | if (flash->mtd.size > 0x1000000) { | 938 | if (flash->mtd.size > 0x1000000) { |
916 | flash->addr_width = 4; | 939 | flash->addr_width = 4; |
917 | set_4byte(flash, 1); | 940 | set_4byte(flash, info->jedec_id, 1); |
918 | } else | 941 | } else |
919 | flash->addr_width = 3; | 942 | flash->addr_width = 3; |
920 | } | 943 | } |
@@ -945,48 +968,41 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
945 | /* partitions should match sector boundaries; and it may be good to | 968 | /* partitions should match sector boundaries; and it may be good to |
946 | * use readonly partitions for writeprotected sectors (BP2..BP0). | 969 | * use readonly partitions for writeprotected sectors (BP2..BP0). |
947 | */ | 970 | */ |
948 | if (mtd_has_partitions()) { | 971 | if (mtd_has_cmdlinepart()) { |
949 | struct mtd_partition *parts = NULL; | 972 | static const char *part_probes[] |
950 | int nr_parts = 0; | 973 | = { "cmdlinepart", NULL, }; |
951 | |||
952 | if (mtd_has_cmdlinepart()) { | ||
953 | static const char *part_probes[] | ||
954 | = { "cmdlinepart", NULL, }; | ||
955 | 974 | ||
956 | nr_parts = parse_mtd_partitions(&flash->mtd, | 975 | nr_parts = parse_mtd_partitions(&flash->mtd, |
957 | part_probes, &parts, 0); | 976 | part_probes, &parts, 0); |
958 | } | 977 | } |
959 | 978 | ||
960 | if (nr_parts <= 0 && data && data->parts) { | 979 | if (nr_parts <= 0 && data && data->parts) { |
961 | parts = data->parts; | 980 | parts = data->parts; |
962 | nr_parts = data->nr_parts; | 981 | nr_parts = data->nr_parts; |
963 | } | 982 | } |
964 | 983 | ||
965 | #ifdef CONFIG_MTD_OF_PARTS | 984 | #ifdef CONFIG_MTD_OF_PARTS |
966 | if (nr_parts <= 0 && spi->dev.of_node) { | 985 | if (nr_parts <= 0 && spi->dev.of_node) { |
967 | nr_parts = of_mtd_parse_partitions(&spi->dev, | 986 | nr_parts = of_mtd_parse_partitions(&spi->dev, |
968 | spi->dev.of_node, &parts); | 987 | spi->dev.of_node, &parts); |
969 | } | 988 | } |
970 | #endif | 989 | #endif |
971 | 990 | ||
972 | if (nr_parts > 0) { | 991 | if (nr_parts > 0) { |
973 | for (i = 0; i < nr_parts; i++) { | 992 | for (i = 0; i < nr_parts; i++) { |
974 | DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " | 993 | DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " |
975 | "{.name = %s, .offset = 0x%llx, " | 994 | "{.name = %s, .offset = 0x%llx, " |
976 | ".size = 0x%llx (%lldKiB) }\n", | 995 | ".size = 0x%llx (%lldKiB) }\n", |
977 | i, parts[i].name, | 996 | i, parts[i].name, |
978 | (long long)parts[i].offset, | 997 | (long long)parts[i].offset, |
979 | (long long)parts[i].size, | 998 | (long long)parts[i].size, |
980 | (long long)(parts[i].size >> 10)); | 999 | (long long)(parts[i].size >> 10)); |
981 | } | ||
982 | flash->partitioned = 1; | ||
983 | return add_mtd_partitions(&flash->mtd, parts, nr_parts); | ||
984 | } | 1000 | } |
985 | } else if (data && data->nr_parts) | 1001 | flash->partitioned = 1; |
986 | dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", | 1002 | } |
987 | data->nr_parts, data->name); | ||
988 | 1003 | ||
989 | return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0; | 1004 | return mtd_device_register(&flash->mtd, parts, nr_parts) == 1 ? |
1005 | -ENODEV : 0; | ||
990 | } | 1006 | } |
991 | 1007 | ||
992 | 1008 | ||
@@ -996,10 +1012,7 @@ static int __devexit m25p_remove(struct spi_device *spi) | |||
996 | int status; | 1012 | int status; |
997 | 1013 | ||
998 | /* Clean up MTD stuff. */ | 1014 | /* Clean up MTD stuff. */ |
999 | if (mtd_has_partitions() && flash->partitioned) | 1015 | status = mtd_device_unregister(&flash->mtd); |
1000 | status = del_mtd_partitions(&flash->mtd); | ||
1001 | else | ||
1002 | status = del_mtd_device(&flash->mtd); | ||
1003 | if (status == 0) { | 1016 | if (status == 0) { |
1004 | kfree(flash->command); | 1017 | kfree(flash->command); |
1005 | kfree(flash); | 1018 | kfree(flash); |
diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c index 6a9a24a80a6d..8423fb6d4f26 100644 --- a/drivers/mtd/devices/ms02-nv.c +++ b/drivers/mtd/devices/ms02-nv.c | |||
@@ -220,7 +220,7 @@ static int __init ms02nv_init_one(ulong addr) | |||
220 | mtd->writesize = 1; | 220 | mtd->writesize = 1; |
221 | 221 | ||
222 | ret = -EIO; | 222 | ret = -EIO; |
223 | if (add_mtd_device(mtd)) { | 223 | if (mtd_device_register(mtd, NULL, 0)) { |
224 | printk(KERN_ERR | 224 | printk(KERN_ERR |
225 | "ms02-nv: Unable to register MTD device, aborting!\n"); | 225 | "ms02-nv: Unable to register MTD device, aborting!\n"); |
226 | goto err_out_csr_res; | 226 | goto err_out_csr_res; |
@@ -262,7 +262,7 @@ static void __exit ms02nv_remove_one(void) | |||
262 | 262 | ||
263 | root_ms02nv_mtd = mp->next; | 263 | root_ms02nv_mtd = mp->next; |
264 | 264 | ||
265 | del_mtd_device(mtd); | 265 | mtd_device_unregister(mtd); |
266 | 266 | ||
267 | release_resource(mp->resource.csr); | 267 | release_resource(mp->resource.csr); |
268 | kfree(mp->resource.csr); | 268 | kfree(mp->resource.csr); |
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index c5015cc721d5..13749d458a31 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -637,6 +637,8 @@ add_dataflash_otp(struct spi_device *spi, char *name, | |||
637 | struct flash_platform_data *pdata = spi->dev.platform_data; | 637 | struct flash_platform_data *pdata = spi->dev.platform_data; |
638 | char *otp_tag = ""; | 638 | char *otp_tag = ""; |
639 | int err = 0; | 639 | int err = 0; |
640 | struct mtd_partition *parts; | ||
641 | int nr_parts = 0; | ||
640 | 642 | ||
641 | priv = kzalloc(sizeof *priv, GFP_KERNEL); | 643 | priv = kzalloc(sizeof *priv, GFP_KERNEL); |
642 | if (!priv) | 644 | if (!priv) |
@@ -675,33 +677,25 @@ add_dataflash_otp(struct spi_device *spi, char *name, | |||
675 | pagesize, otp_tag); | 677 | pagesize, otp_tag); |
676 | dev_set_drvdata(&spi->dev, priv); | 678 | dev_set_drvdata(&spi->dev, priv); |
677 | 679 | ||
678 | if (mtd_has_partitions()) { | 680 | if (mtd_has_cmdlinepart()) { |
679 | struct mtd_partition *parts; | 681 | static const char *part_probes[] = { "cmdlinepart", NULL, }; |
680 | int nr_parts = 0; | ||
681 | 682 | ||
682 | if (mtd_has_cmdlinepart()) { | 683 | nr_parts = parse_mtd_partitions(device, part_probes, &parts, |
683 | static const char *part_probes[] | 684 | 0); |
684 | = { "cmdlinepart", NULL, }; | 685 | } |
685 | |||
686 | nr_parts = parse_mtd_partitions(device, | ||
687 | part_probes, &parts, 0); | ||
688 | } | ||
689 | 686 | ||
690 | if (nr_parts <= 0 && pdata && pdata->parts) { | 687 | if (nr_parts <= 0 && pdata && pdata->parts) { |
691 | parts = pdata->parts; | 688 | parts = pdata->parts; |
692 | nr_parts = pdata->nr_parts; | 689 | nr_parts = pdata->nr_parts; |
693 | } | 690 | } |
694 | 691 | ||
695 | if (nr_parts > 0) { | 692 | if (nr_parts > 0) { |
696 | priv->partitioned = 1; | 693 | priv->partitioned = 1; |
697 | err = add_mtd_partitions(device, parts, nr_parts); | 694 | err = mtd_device_register(device, parts, nr_parts); |
698 | goto out; | 695 | goto out; |
699 | } | 696 | } |
700 | } else if (pdata && pdata->nr_parts) | ||
701 | dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", | ||
702 | pdata->nr_parts, device->name); | ||
703 | 697 | ||
704 | if (add_mtd_device(device) == 1) | 698 | if (mtd_device_register(device, NULL, 0) == 1) |
705 | err = -ENODEV; | 699 | err = -ENODEV; |
706 | 700 | ||
707 | out: | 701 | out: |
@@ -939,10 +933,7 @@ static int __devexit dataflash_remove(struct spi_device *spi) | |||
939 | 933 | ||
940 | DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", dev_name(&spi->dev)); | 934 | DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", dev_name(&spi->dev)); |
941 | 935 | ||
942 | if (mtd_has_partitions() && flash->partitioned) | 936 | status = mtd_device_unregister(&flash->mtd); |
943 | status = del_mtd_partitions(&flash->mtd); | ||
944 | else | ||
945 | status = del_mtd_device(&flash->mtd); | ||
946 | if (status == 0) { | 937 | if (status == 0) { |
947 | dev_set_drvdata(&spi->dev, NULL); | 938 | dev_set_drvdata(&spi->dev, NULL); |
948 | kfree(flash); | 939 | kfree(flash); |
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index 1483e18971ce..2562689ba6b4 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c | |||
@@ -104,7 +104,7 @@ static int ram_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
104 | static void __exit cleanup_mtdram(void) | 104 | static void __exit cleanup_mtdram(void) |
105 | { | 105 | { |
106 | if (mtd_info) { | 106 | if (mtd_info) { |
107 | del_mtd_device(mtd_info); | 107 | mtd_device_unregister(mtd_info); |
108 | vfree(mtd_info->priv); | 108 | vfree(mtd_info->priv); |
109 | kfree(mtd_info); | 109 | kfree(mtd_info); |
110 | } | 110 | } |
@@ -133,9 +133,8 @@ int mtdram_init_device(struct mtd_info *mtd, void *mapped_address, | |||
133 | mtd->read = ram_read; | 133 | mtd->read = ram_read; |
134 | mtd->write = ram_write; | 134 | mtd->write = ram_write; |
135 | 135 | ||
136 | if (add_mtd_device(mtd)) { | 136 | if (mtd_device_register(mtd, NULL, 0)) |
137 | return -EIO; | 137 | return -EIO; |
138 | } | ||
139 | 138 | ||
140 | return 0; | 139 | return 0; |
141 | } | 140 | } |
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 8d28fa02a5a2..23423bd00b06 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c | |||
@@ -115,7 +115,7 @@ static void unregister_devices(void) | |||
115 | struct phram_mtd_list *this, *safe; | 115 | struct phram_mtd_list *this, *safe; |
116 | 116 | ||
117 | list_for_each_entry_safe(this, safe, &phram_list, list) { | 117 | list_for_each_entry_safe(this, safe, &phram_list, list) { |
118 | del_mtd_device(&this->mtd); | 118 | mtd_device_unregister(&this->mtd); |
119 | iounmap(this->mtd.priv); | 119 | iounmap(this->mtd.priv); |
120 | kfree(this->mtd.name); | 120 | kfree(this->mtd.name); |
121 | kfree(this); | 121 | kfree(this); |
@@ -153,7 +153,7 @@ static int register_device(char *name, unsigned long start, unsigned long len) | |||
153 | new->mtd.writesize = 1; | 153 | new->mtd.writesize = 1; |
154 | 154 | ||
155 | ret = -EAGAIN; | 155 | ret = -EAGAIN; |
156 | if (add_mtd_device(&new->mtd)) { | 156 | if (mtd_device_register(&new->mtd, NULL, 0)) { |
157 | pr_err("Failed to register new device\n"); | 157 | pr_err("Failed to register new device\n"); |
158 | goto out2; | 158 | goto out2; |
159 | } | 159 | } |
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index 41b8cdcc64cb..ecff765579dd 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c | |||
@@ -798,7 +798,7 @@ static int __init init_pmc551(void) | |||
798 | mtd->writesize = 1; | 798 | mtd->writesize = 1; |
799 | mtd->owner = THIS_MODULE; | 799 | mtd->owner = THIS_MODULE; |
800 | 800 | ||
801 | if (add_mtd_device(mtd)) { | 801 | if (mtd_device_register(mtd, NULL, 0)) { |
802 | printk(KERN_NOTICE "pmc551: Failed to register new device\n"); | 802 | printk(KERN_NOTICE "pmc551: Failed to register new device\n"); |
803 | pci_iounmap(PCI_Device, priv->start); | 803 | pci_iounmap(PCI_Device, priv->start); |
804 | kfree(mtd->priv); | 804 | kfree(mtd->priv); |
@@ -806,7 +806,7 @@ static int __init init_pmc551(void) | |||
806 | break; | 806 | break; |
807 | } | 807 | } |
808 | 808 | ||
809 | /* Keep a reference as the add_mtd_device worked */ | 809 | /* Keep a reference as the mtd_device_register worked */ |
810 | pci_dev_get(PCI_Device); | 810 | pci_dev_get(PCI_Device); |
811 | 811 | ||
812 | printk(KERN_NOTICE "Registered pmc551 memory device.\n"); | 812 | printk(KERN_NOTICE "Registered pmc551 memory device.\n"); |
@@ -856,7 +856,7 @@ static void __exit cleanup_pmc551(void) | |||
856 | pci_dev_put(priv->dev); | 856 | pci_dev_put(priv->dev); |
857 | 857 | ||
858 | kfree(mtd->priv); | 858 | kfree(mtd->priv); |
859 | del_mtd_device(mtd); | 859 | mtd_device_unregister(mtd); |
860 | kfree(mtd); | 860 | kfree(mtd); |
861 | found++; | 861 | found++; |
862 | } | 862 | } |
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index 592016a0668f..e585263161b9 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c | |||
@@ -210,7 +210,7 @@ static int register_device(char *name, unsigned long start, unsigned long length | |||
210 | (*curmtd)->mtdinfo->erasesize = SLRAM_BLK_SZ; | 210 | (*curmtd)->mtdinfo->erasesize = SLRAM_BLK_SZ; |
211 | (*curmtd)->mtdinfo->writesize = 1; | 211 | (*curmtd)->mtdinfo->writesize = 1; |
212 | 212 | ||
213 | if (add_mtd_device((*curmtd)->mtdinfo)) { | 213 | if (mtd_device_register((*curmtd)->mtdinfo, NULL, 0)) { |
214 | E("slram: Failed to register new device\n"); | 214 | E("slram: Failed to register new device\n"); |
215 | iounmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start); | 215 | iounmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start); |
216 | kfree((*curmtd)->mtdinfo->priv); | 216 | kfree((*curmtd)->mtdinfo->priv); |
@@ -231,7 +231,7 @@ static void unregister_devices(void) | |||
231 | 231 | ||
232 | while (slram_mtdlist) { | 232 | while (slram_mtdlist) { |
233 | nextitem = slram_mtdlist->next; | 233 | nextitem = slram_mtdlist->next; |
234 | del_mtd_device(slram_mtdlist->mtdinfo); | 234 | mtd_device_unregister(slram_mtdlist->mtdinfo); |
235 | iounmap(((slram_priv_t *)slram_mtdlist->mtdinfo->priv)->start); | 235 | iounmap(((slram_priv_t *)slram_mtdlist->mtdinfo->priv)->start); |
236 | kfree(slram_mtdlist->mtdinfo->priv); | 236 | kfree(slram_mtdlist->mtdinfo->priv); |
237 | kfree(slram_mtdlist->mtdinfo); | 237 | kfree(slram_mtdlist->mtdinfo); |
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index c163e619abc9..1e2c430aaad2 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c | |||
@@ -66,7 +66,7 @@ struct flash_info { | |||
66 | 66 | ||
67 | #define to_sst25l_flash(x) container_of(x, struct sst25l_flash, mtd) | 67 | #define to_sst25l_flash(x) container_of(x, struct sst25l_flash, mtd) |
68 | 68 | ||
69 | static struct flash_info __initdata sst25l_flash_info[] = { | 69 | static struct flash_info __devinitdata sst25l_flash_info[] = { |
70 | {"sst25lf020a", 0xbf43, 256, 1024, 4096}, | 70 | {"sst25lf020a", 0xbf43, 256, 1024, 4096}, |
71 | {"sst25lf040a", 0xbf44, 256, 2048, 4096}, | 71 | {"sst25lf040a", 0xbf44, 256, 2048, 4096}, |
72 | }; | 72 | }; |
@@ -381,6 +381,8 @@ static int __devinit sst25l_probe(struct spi_device *spi) | |||
381 | struct sst25l_flash *flash; | 381 | struct sst25l_flash *flash; |
382 | struct flash_platform_data *data; | 382 | struct flash_platform_data *data; |
383 | int ret, i; | 383 | int ret, i; |
384 | struct mtd_partition *parts = NULL; | ||
385 | int nr_parts = 0; | ||
384 | 386 | ||
385 | flash_info = sst25l_match_device(spi); | 387 | flash_info = sst25l_match_device(spi); |
386 | if (!flash_info) | 388 | if (!flash_info) |
@@ -420,46 +422,37 @@ static int __devinit sst25l_probe(struct spi_device *spi) | |||
420 | flash->mtd.erasesize, flash->mtd.erasesize / 1024, | 422 | flash->mtd.erasesize, flash->mtd.erasesize / 1024, |
421 | flash->mtd.numeraseregions); | 423 | flash->mtd.numeraseregions); |
422 | 424 | ||
423 | if (mtd_has_partitions()) { | ||
424 | struct mtd_partition *parts = NULL; | ||
425 | int nr_parts = 0; | ||
426 | 425 | ||
427 | if (mtd_has_cmdlinepart()) { | 426 | if (mtd_has_cmdlinepart()) { |
428 | static const char *part_probes[] = | 427 | static const char *part_probes[] = {"cmdlinepart", NULL}; |
429 | {"cmdlinepart", NULL}; | ||
430 | 428 | ||
431 | nr_parts = parse_mtd_partitions(&flash->mtd, | 429 | nr_parts = parse_mtd_partitions(&flash->mtd, |
432 | part_probes, | 430 | part_probes, |
433 | &parts, 0); | 431 | &parts, 0); |
434 | } | 432 | } |
435 | 433 | ||
436 | if (nr_parts <= 0 && data && data->parts) { | 434 | if (nr_parts <= 0 && data && data->parts) { |
437 | parts = data->parts; | 435 | parts = data->parts; |
438 | nr_parts = data->nr_parts; | 436 | nr_parts = data->nr_parts; |
439 | } | 437 | } |
440 | 438 | ||
441 | if (nr_parts > 0) { | 439 | if (nr_parts > 0) { |
442 | for (i = 0; i < nr_parts; i++) { | 440 | for (i = 0; i < nr_parts; i++) { |
443 | DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " | 441 | DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " |
444 | "{.name = %s, .offset = 0x%llx, " | 442 | "{.name = %s, .offset = 0x%llx, " |
445 | ".size = 0x%llx (%lldKiB) }\n", | 443 | ".size = 0x%llx (%lldKiB) }\n", |
446 | i, parts[i].name, | 444 | i, parts[i].name, |
447 | (long long)parts[i].offset, | 445 | (long long)parts[i].offset, |
448 | (long long)parts[i].size, | 446 | (long long)parts[i].size, |
449 | (long long)(parts[i].size >> 10)); | 447 | (long long)(parts[i].size >> 10)); |
450 | } | ||
451 | |||
452 | flash->partitioned = 1; | ||
453 | return add_mtd_partitions(&flash->mtd, | ||
454 | parts, nr_parts); | ||
455 | } | 448 | } |
456 | 449 | ||
457 | } else if (data && data->nr_parts) { | 450 | flash->partitioned = 1; |
458 | dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", | 451 | return mtd_device_register(&flash->mtd, parts, |
459 | data->nr_parts, data->name); | 452 | nr_parts); |
460 | } | 453 | } |
461 | 454 | ||
462 | ret = add_mtd_device(&flash->mtd); | 455 | ret = mtd_device_register(&flash->mtd, NULL, 0); |
463 | if (ret == 1) { | 456 | if (ret == 1) { |
464 | kfree(flash); | 457 | kfree(flash); |
465 | dev_set_drvdata(&spi->dev, NULL); | 458 | dev_set_drvdata(&spi->dev, NULL); |
@@ -469,15 +462,12 @@ static int __devinit sst25l_probe(struct spi_device *spi) | |||
469 | return 0; | 462 | return 0; |
470 | } | 463 | } |
471 | 464 | ||
472 | static int __exit sst25l_remove(struct spi_device *spi) | 465 | static int __devexit sst25l_remove(struct spi_device *spi) |
473 | { | 466 | { |
474 | struct sst25l_flash *flash = dev_get_drvdata(&spi->dev); | 467 | struct sst25l_flash *flash = dev_get_drvdata(&spi->dev); |
475 | int ret; | 468 | int ret; |
476 | 469 | ||
477 | if (mtd_has_partitions() && flash->partitioned) | 470 | ret = mtd_device_unregister(&flash->mtd); |
478 | ret = del_mtd_partitions(&flash->mtd); | ||
479 | else | ||
480 | ret = del_mtd_device(&flash->mtd); | ||
481 | if (ret == 0) | 471 | if (ret == 0) |
482 | kfree(flash); | 472 | kfree(flash); |
483 | return ret; | 473 | return ret; |
@@ -490,7 +480,7 @@ static struct spi_driver sst25l_driver = { | |||
490 | .owner = THIS_MODULE, | 480 | .owner = THIS_MODULE, |
491 | }, | 481 | }, |
492 | .probe = sst25l_probe, | 482 | .probe = sst25l_probe, |
493 | .remove = __exit_p(sst25l_remove), | 483 | .remove = __devexit_p(sst25l_remove), |
494 | }; | 484 | }; |
495 | 485 | ||
496 | static int __init sst25l_init(void) | 486 | static int __init sst25l_init(void) |
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c index 12679925b420..65655dd59e1f 100644 --- a/drivers/mtd/lpddr/lpddr_cmds.c +++ b/drivers/mtd/lpddr/lpddr_cmds.c | |||
@@ -313,12 +313,7 @@ static int chip_ready(struct map_info *map, struct flchip *chip, int mode) | |||
313 | if (ret) { | 313 | if (ret) { |
314 | /* Oops. something got wrong. */ | 314 | /* Oops. something got wrong. */ |
315 | /* Resume and pretend we weren't here. */ | 315 | /* Resume and pretend we weren't here. */ |
316 | map_write(map, CMD(LPDDR_RESUME), | 316 | put_chip(map, chip); |
317 | map->pfow_base + PFOW_COMMAND_CODE); | ||
318 | map_write(map, CMD(LPDDR_START_EXECUTION), | ||
319 | map->pfow_base + PFOW_COMMAND_EXECUTE); | ||
320 | chip->state = FL_ERASING; | ||
321 | chip->oldstate = FL_READY; | ||
322 | printk(KERN_ERR "%s: suspend operation failed." | 317 | printk(KERN_ERR "%s: suspend operation failed." |
323 | "State may be wrong \n", map->name); | 318 | "State may be wrong \n", map->name); |
324 | return -EIO; | 319 | return -EIO; |
@@ -383,7 +378,6 @@ static void put_chip(struct map_info *map, struct flchip *chip) | |||
383 | 378 | ||
384 | switch (chip->oldstate) { | 379 | switch (chip->oldstate) { |
385 | case FL_ERASING: | 380 | case FL_ERASING: |
386 | chip->state = chip->oldstate; | ||
387 | map_write(map, CMD(LPDDR_RESUME), | 381 | map_write(map, CMD(LPDDR_RESUME), |
388 | map->pfow_base + PFOW_COMMAND_CODE); | 382 | map->pfow_base + PFOW_COMMAND_CODE); |
389 | map_write(map, CMD(LPDDR_START_EXECUTION), | 383 | map_write(map, CMD(LPDDR_START_EXECUTION), |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 5069111c81cc..c0c328c5b133 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -82,7 +82,6 @@ config MTD_PHYSMAP_OF | |||
82 | config MTD_PMC_MSP_EVM | 82 | config MTD_PMC_MSP_EVM |
83 | tristate "CFI Flash device mapped on PMC-Sierra MSP" | 83 | tristate "CFI Flash device mapped on PMC-Sierra MSP" |
84 | depends on PMC_MSP && MTD_CFI | 84 | depends on PMC_MSP && MTD_CFI |
85 | select MTD_PARTITIONS | ||
86 | help | 85 | help |
87 | This provides a 'mapping' driver which supports the way | 86 | This provides a 'mapping' driver which supports the way |
88 | in which user-programmable flash chips are connected on the | 87 | in which user-programmable flash chips are connected on the |
@@ -122,7 +121,7 @@ config MTD_SC520CDP | |||
122 | 121 | ||
123 | config MTD_NETSC520 | 122 | config MTD_NETSC520 |
124 | tristate "CFI Flash device mapped on AMD NetSc520" | 123 | tristate "CFI Flash device mapped on AMD NetSc520" |
125 | depends on X86 && MTD_CFI && MTD_PARTITIONS | 124 | depends on X86 && MTD_CFI |
126 | help | 125 | help |
127 | This enables access routines for the flash chips on the AMD NetSc520 | 126 | This enables access routines for the flash chips on the AMD NetSc520 |
128 | demonstration board. If you have one of these boards and would like | 127 | demonstration board. If you have one of these boards and would like |
@@ -131,7 +130,6 @@ config MTD_NETSC520 | |||
131 | config MTD_TS5500 | 130 | config MTD_TS5500 |
132 | tristate "JEDEC Flash device mapped on Technologic Systems TS-5500" | 131 | tristate "JEDEC Flash device mapped on Technologic Systems TS-5500" |
133 | depends on X86 | 132 | depends on X86 |
134 | select MTD_PARTITIONS | ||
135 | select MTD_JEDECPROBE | 133 | select MTD_JEDECPROBE |
136 | select MTD_CFI_AMDSTD | 134 | select MTD_CFI_AMDSTD |
137 | help | 135 | help |
@@ -149,7 +147,7 @@ config MTD_TS5500 | |||
149 | 147 | ||
150 | config MTD_SBC_GXX | 148 | config MTD_SBC_GXX |
151 | tristate "CFI Flash device mapped on Arcom SBC-GXx boards" | 149 | tristate "CFI Flash device mapped on Arcom SBC-GXx boards" |
152 | depends on X86 && MTD_CFI_INTELEXT && MTD_PARTITIONS && MTD_COMPLEX_MAPPINGS | 150 | depends on X86 && MTD_CFI_INTELEXT && MTD_COMPLEX_MAPPINGS |
153 | help | 151 | help |
154 | This provides a driver for the on-board flash of Arcom Control | 152 | This provides a driver for the on-board flash of Arcom Control |
155 | Systems' SBC-GXn family of boards, formerly known as SBC-MediaGX. | 153 | Systems' SBC-GXn family of boards, formerly known as SBC-MediaGX. |
@@ -161,7 +159,6 @@ config MTD_SBC_GXX | |||
161 | config MTD_PXA2XX | 159 | config MTD_PXA2XX |
162 | tristate "CFI Flash device mapped on Intel XScale PXA2xx based boards" | 160 | tristate "CFI Flash device mapped on Intel XScale PXA2xx based boards" |
163 | depends on (PXA25x || PXA27x) && MTD_CFI_INTELEXT | 161 | depends on (PXA25x || PXA27x) && MTD_CFI_INTELEXT |
164 | select MTD_PARTITIONS | ||
165 | help | 162 | help |
166 | This provides a driver for the NOR flash attached to a PXA2xx chip. | 163 | This provides a driver for the NOR flash attached to a PXA2xx chip. |
167 | 164 | ||
@@ -185,7 +182,7 @@ config MTD_VMAX | |||
185 | 182 | ||
186 | config MTD_SCx200_DOCFLASH | 183 | config MTD_SCx200_DOCFLASH |
187 | tristate "Flash device mapped with DOCCS on NatSemi SCx200" | 184 | tristate "Flash device mapped with DOCCS on NatSemi SCx200" |
188 | depends on SCx200 && MTD_CFI && MTD_PARTITIONS | 185 | depends on SCx200 && MTD_CFI |
189 | help | 186 | help |
190 | Enable support for a flash chip mapped using the DOCCS signal on a | 187 | Enable support for a flash chip mapped using the DOCCS signal on a |
191 | National Semiconductor SCx200 processor. | 188 | National Semiconductor SCx200 processor. |
@@ -247,7 +244,7 @@ config MTD_TSUNAMI | |||
247 | 244 | ||
248 | config MTD_NETtel | 245 | config MTD_NETtel |
249 | tristate "CFI flash device on SnapGear/SecureEdge" | 246 | tristate "CFI flash device on SnapGear/SecureEdge" |
250 | depends on X86 && MTD_PARTITIONS && MTD_JEDECPROBE | 247 | depends on X86 && MTD_JEDECPROBE |
251 | help | 248 | help |
252 | Support for flash chips on NETtel/SecureEdge/SnapGear boards. | 249 | Support for flash chips on NETtel/SecureEdge/SnapGear boards. |
253 | 250 | ||
@@ -269,7 +266,7 @@ config MTD_LANTIQ | |||
269 | 266 | ||
270 | config MTD_DILNETPC | 267 | config MTD_DILNETPC |
271 | tristate "CFI Flash device mapped on DIL/Net PC" | 268 | tristate "CFI Flash device mapped on DIL/Net PC" |
272 | depends on X86 && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN | 269 | depends on X86 && MTD_CFI_INTELEXT && BROKEN |
273 | help | 270 | help |
274 | MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP". | 271 | MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP". |
275 | For details, see <http://www.ssv-embedded.de/ssv/pc104/p169.htm> | 272 | For details, see <http://www.ssv-embedded.de/ssv/pc104/p169.htm> |
@@ -355,7 +352,7 @@ config MTD_CDB89712 | |||
355 | 352 | ||
356 | config MTD_SA1100 | 353 | config MTD_SA1100 |
357 | tristate "CFI Flash device mapped on StrongARM SA11x0" | 354 | tristate "CFI Flash device mapped on StrongARM SA11x0" |
358 | depends on MTD_CFI && ARCH_SA1100 && MTD_PARTITIONS | 355 | depends on MTD_CFI && ARCH_SA1100 |
359 | help | 356 | help |
360 | This enables access to the flash chips on most platforms based on | 357 | This enables access to the flash chips on most platforms based on |
361 | the SA1100 and SA1110, including the Assabet and the Compaq iPAQ. | 358 | the SA1100 and SA1110, including the Assabet and the Compaq iPAQ. |
@@ -389,7 +386,7 @@ config MTD_IXP2000 | |||
389 | 386 | ||
390 | config MTD_FORTUNET | 387 | config MTD_FORTUNET |
391 | tristate "CFI Flash device mapped on the FortuNet board" | 388 | tristate "CFI Flash device mapped on the FortuNet board" |
392 | depends on MTD_CFI && MTD_PARTITIONS && SA1100_FORTUNET | 389 | depends on MTD_CFI && SA1100_FORTUNET |
393 | help | 390 | help |
394 | This enables access to the Flash on the FortuNet board. If you | 391 | This enables access to the Flash on the FortuNet board. If you |
395 | have such a board, say 'Y'. | 392 | have such a board, say 'Y'. |
@@ -461,7 +458,6 @@ config MTD_PCMCIA_ANONYMOUS | |||
461 | config MTD_BFIN_ASYNC | 458 | config MTD_BFIN_ASYNC |
462 | tristate "Blackfin BF533-STAMP Flash Chip Support" | 459 | tristate "Blackfin BF533-STAMP Flash Chip Support" |
463 | depends on BFIN533_STAMP && MTD_CFI && MTD_COMPLEX_MAPPINGS | 460 | depends on BFIN533_STAMP && MTD_CFI && MTD_COMPLEX_MAPPINGS |
464 | select MTD_PARTITIONS | ||
465 | default y | 461 | default y |
466 | help | 462 | help |
467 | Map driver which allows for simultaneous utilization of | 463 | Map driver which allows for simultaneous utilization of |
@@ -473,7 +469,6 @@ config MTD_GPIO_ADDR | |||
473 | tristate "GPIO-assisted Flash Chip Support" | 469 | tristate "GPIO-assisted Flash Chip Support" |
474 | depends on GENERIC_GPIO || GPIOLIB | 470 | depends on GENERIC_GPIO || GPIOLIB |
475 | depends on MTD_COMPLEX_MAPPINGS | 471 | depends on MTD_COMPLEX_MAPPINGS |
476 | select MTD_PARTITIONS | ||
477 | help | 472 | help |
478 | Map driver which allows flashes to be partially physically addressed | 473 | Map driver which allows flashes to be partially physically addressed |
479 | and assisted by GPIOs. | 474 | and assisted by GPIOs. |
@@ -482,14 +477,13 @@ config MTD_GPIO_ADDR | |||
482 | 477 | ||
483 | config MTD_UCLINUX | 478 | config MTD_UCLINUX |
484 | bool "Generic uClinux RAM/ROM filesystem support" | 479 | bool "Generic uClinux RAM/ROM filesystem support" |
485 | depends on MTD_PARTITIONS && MTD_RAM=y && !MMU | 480 | depends on MTD_RAM=y && !MMU |
486 | help | 481 | help |
487 | Map driver to support image based filesystems for uClinux. | 482 | Map driver to support image based filesystems for uClinux. |
488 | 483 | ||
489 | config MTD_WRSBC8260 | 484 | config MTD_WRSBC8260 |
490 | tristate "Map driver for WindRiver PowerQUICC II MPC82xx board" | 485 | tristate "Map driver for WindRiver PowerQUICC II MPC82xx board" |
491 | depends on (SBC82xx || SBC8560) | 486 | depends on (SBC82xx || SBC8560) |
492 | select MTD_PARTITIONS | ||
493 | select MTD_MAP_BANK_WIDTH_4 | 487 | select MTD_MAP_BANK_WIDTH_4 |
494 | select MTD_MAP_BANK_WIDTH_1 | 488 | select MTD_MAP_BANK_WIDTH_1 |
495 | select MTD_CFI_I1 | 489 | select MTD_CFI_I1 |
@@ -502,7 +496,6 @@ config MTD_WRSBC8260 | |||
502 | config MTD_DMV182 | 496 | config MTD_DMV182 |
503 | tristate "Map driver for Dy-4 SVME/DMV-182 board." | 497 | tristate "Map driver for Dy-4 SVME/DMV-182 board." |
504 | depends on DMV182 | 498 | depends on DMV182 |
505 | select MTD_PARTITIONS | ||
506 | select MTD_MAP_BANK_WIDTH_32 | 499 | select MTD_MAP_BANK_WIDTH_32 |
507 | select MTD_CFI_I8 | 500 | select MTD_CFI_I8 |
508 | select MTD_CFI_AMDSTD | 501 | select MTD_CFI_AMDSTD |
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index 92de7e3a49a5..e2875d6fe129 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c | |||
@@ -82,7 +82,7 @@ static void amd76xrom_cleanup(struct amd76xrom_window *window) | |||
82 | if (map->rsrc.parent) { | 82 | if (map->rsrc.parent) { |
83 | release_resource(&map->rsrc); | 83 | release_resource(&map->rsrc); |
84 | } | 84 | } |
85 | del_mtd_device(map->mtd); | 85 | mtd_device_unregister(map->mtd); |
86 | map_destroy(map->mtd); | 86 | map_destroy(map->mtd); |
87 | list_del(&map->list); | 87 | list_del(&map->list); |
88 | kfree(map); | 88 | kfree(map); |
@@ -262,7 +262,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev, | |||
262 | 262 | ||
263 | /* Now that the mtd devices is complete claim and export it */ | 263 | /* Now that the mtd devices is complete claim and export it */ |
264 | map->mtd->owner = THIS_MODULE; | 264 | map->mtd->owner = THIS_MODULE; |
265 | if (add_mtd_device(map->mtd)) { | 265 | if (mtd_device_register(map->mtd, NULL, 0)) { |
266 | map_destroy(map->mtd); | 266 | map_destroy(map->mtd); |
267 | map->mtd = NULL; | 267 | map->mtd = NULL; |
268 | goto out; | 268 | goto out; |
diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c index 53664188fc47..e5bfd0e093bb 100644 --- a/drivers/mtd/maps/autcpu12-nvram.c +++ b/drivers/mtd/maps/autcpu12-nvram.c | |||
@@ -88,7 +88,7 @@ map: | |||
88 | sram_mtd->owner = THIS_MODULE; | 88 | sram_mtd->owner = THIS_MODULE; |
89 | sram_mtd->erasesize = 16; | 89 | sram_mtd->erasesize = 16; |
90 | 90 | ||
91 | if (add_mtd_device(sram_mtd)) { | 91 | if (mtd_device_register(sram_mtd, NULL, 0)) { |
92 | printk("NV-RAM device addition failed\n"); | 92 | printk("NV-RAM device addition failed\n"); |
93 | err = -ENOMEM; | 93 | err = -ENOMEM; |
94 | goto out_probe; | 94 | goto out_probe; |
@@ -111,7 +111,7 @@ out: | |||
111 | static void __exit cleanup_autcpu12_maps(void) | 111 | static void __exit cleanup_autcpu12_maps(void) |
112 | { | 112 | { |
113 | if (sram_mtd) { | 113 | if (sram_mtd) { |
114 | del_mtd_device(sram_mtd); | 114 | mtd_device_unregister(sram_mtd); |
115 | map_destroy(sram_mtd); | 115 | map_destroy(sram_mtd); |
116 | iounmap((void *)autcpu12_sram_map.virt); | 116 | iounmap((void *)autcpu12_sram_map.virt); |
117 | } | 117 | } |
diff --git a/drivers/mtd/maps/bcm963xx-flash.c b/drivers/mtd/maps/bcm963xx-flash.c index 1f3049590d9e..608967fe74c6 100644 --- a/drivers/mtd/maps/bcm963xx-flash.c +++ b/drivers/mtd/maps/bcm963xx-flash.c | |||
@@ -224,8 +224,8 @@ probe_ok: | |||
224 | goto err_probe; | 224 | goto err_probe; |
225 | } | 225 | } |
226 | 226 | ||
227 | return add_mtd_partitions(bcm963xx_mtd_info, parsed_parts, | 227 | return mtd_device_register(bcm963xx_mtd_info, parsed_parts, |
228 | parsed_nr_parts); | 228 | parsed_nr_parts); |
229 | 229 | ||
230 | err_probe: | 230 | err_probe: |
231 | iounmap(bcm963xx_map.virt); | 231 | iounmap(bcm963xx_map.virt); |
@@ -235,7 +235,7 @@ err_probe: | |||
235 | static int bcm963xx_remove(struct platform_device *pdev) | 235 | static int bcm963xx_remove(struct platform_device *pdev) |
236 | { | 236 | { |
237 | if (bcm963xx_mtd_info) { | 237 | if (bcm963xx_mtd_info) { |
238 | del_mtd_partitions(bcm963xx_mtd_info); | 238 | mtd_device_unregister(bcm963xx_mtd_info); |
239 | map_destroy(bcm963xx_mtd_info); | 239 | map_destroy(bcm963xx_mtd_info); |
240 | } | 240 | } |
241 | 241 | ||
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c index 85dd18193cf2..d4297a97e100 100644 --- a/drivers/mtd/maps/bfin-async-flash.c +++ b/drivers/mtd/maps/bfin-async-flash.c | |||
@@ -41,9 +41,7 @@ struct async_state { | |||
41 | uint32_t flash_ambctl0, flash_ambctl1; | 41 | uint32_t flash_ambctl0, flash_ambctl1; |
42 | uint32_t save_ambctl0, save_ambctl1; | 42 | uint32_t save_ambctl0, save_ambctl1; |
43 | unsigned long irq_flags; | 43 | unsigned long irq_flags; |
44 | #ifdef CONFIG_MTD_PARTITIONS | ||
45 | struct mtd_partition *parts; | 44 | struct mtd_partition *parts; |
46 | #endif | ||
47 | }; | 45 | }; |
48 | 46 | ||
49 | static void switch_to_flash(struct async_state *state) | 47 | static void switch_to_flash(struct async_state *state) |
@@ -124,9 +122,7 @@ static void bfin_flash_copy_to(struct map_info *map, unsigned long to, const voi | |||
124 | switch_back(state); | 122 | switch_back(state); |
125 | } | 123 | } |
126 | 124 | ||
127 | #ifdef CONFIG_MTD_PARTITIONS | ||
128 | static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; | 125 | static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; |
129 | #endif | ||
130 | 126 | ||
131 | static int __devinit bfin_flash_probe(struct platform_device *pdev) | 127 | static int __devinit bfin_flash_probe(struct platform_device *pdev) |
132 | { | 128 | { |
@@ -169,22 +165,17 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev) | |||
169 | return -ENXIO; | 165 | return -ENXIO; |
170 | } | 166 | } |
171 | 167 | ||
172 | #ifdef CONFIG_MTD_PARTITIONS | ||
173 | ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0); | 168 | ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0); |
174 | if (ret > 0) { | 169 | if (ret > 0) { |
175 | pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n"); | 170 | pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n"); |
176 | add_mtd_partitions(state->mtd, pdata->parts, ret); | 171 | mtd_device_register(state->mtd, pdata->parts, ret); |
177 | state->parts = pdata->parts; | 172 | state->parts = pdata->parts; |
178 | |||
179 | } else if (pdata->nr_parts) { | 173 | } else if (pdata->nr_parts) { |
180 | pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n"); | 174 | pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n"); |
181 | add_mtd_partitions(state->mtd, pdata->parts, pdata->nr_parts); | 175 | mtd_device_register(state->mtd, pdata->parts, pdata->nr_parts); |
182 | 176 | } else { | |
183 | } else | ||
184 | #endif | ||
185 | { | ||
186 | pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n"); | 177 | pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n"); |
187 | add_mtd_device(state->mtd); | 178 | mtd_device_register(state->mtd, NULL, 0); |
188 | } | 179 | } |
189 | 180 | ||
190 | platform_set_drvdata(pdev, state); | 181 | platform_set_drvdata(pdev, state); |
@@ -196,10 +187,8 @@ static int __devexit bfin_flash_remove(struct platform_device *pdev) | |||
196 | { | 187 | { |
197 | struct async_state *state = platform_get_drvdata(pdev); | 188 | struct async_state *state = platform_get_drvdata(pdev); |
198 | gpio_free(state->enet_flash_pin); | 189 | gpio_free(state->enet_flash_pin); |
199 | #ifdef CONFIG_MTD_PARTITIONS | 190 | mtd_device_unregister(state->mtd); |
200 | del_mtd_partitions(state->mtd); | ||
201 | kfree(state->parts); | 191 | kfree(state->parts); |
202 | #endif | ||
203 | map_destroy(state->mtd); | 192 | map_destroy(state->mtd); |
204 | kfree(state); | 193 | kfree(state); |
205 | return 0; | 194 | return 0; |
diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c index 8d92d8db9a98..c29cbf87ea0c 100644 --- a/drivers/mtd/maps/cdb89712.c +++ b/drivers/mtd/maps/cdb89712.c | |||
@@ -75,7 +75,7 @@ static int __init init_cdb89712_flash (void) | |||
75 | 75 | ||
76 | flash_mtd->owner = THIS_MODULE; | 76 | flash_mtd->owner = THIS_MODULE; |
77 | 77 | ||
78 | if (add_mtd_device(flash_mtd)) { | 78 | if (mtd_device_register(flash_mtd, NULL, 0)) { |
79 | printk("FLASH device addition failed\n"); | 79 | printk("FLASH device addition failed\n"); |
80 | err = -ENOMEM; | 80 | err = -ENOMEM; |
81 | goto out_probe; | 81 | goto out_probe; |
@@ -141,7 +141,7 @@ static int __init init_cdb89712_sram (void) | |||
141 | sram_mtd->owner = THIS_MODULE; | 141 | sram_mtd->owner = THIS_MODULE; |
142 | sram_mtd->erasesize = 16; | 142 | sram_mtd->erasesize = 16; |
143 | 143 | ||
144 | if (add_mtd_device(sram_mtd)) { | 144 | if (mtd_device_register(sram_mtd, NULL, 0)) { |
145 | printk("SRAM device addition failed\n"); | 145 | printk("SRAM device addition failed\n"); |
146 | err = -ENOMEM; | 146 | err = -ENOMEM; |
147 | goto out_probe; | 147 | goto out_probe; |
@@ -209,7 +209,7 @@ static int __init init_cdb89712_bootrom (void) | |||
209 | bootrom_mtd->owner = THIS_MODULE; | 209 | bootrom_mtd->owner = THIS_MODULE; |
210 | bootrom_mtd->erasesize = 0x10000; | 210 | bootrom_mtd->erasesize = 0x10000; |
211 | 211 | ||
212 | if (add_mtd_device(bootrom_mtd)) { | 212 | if (mtd_device_register(bootrom_mtd, NULL, 0)) { |
213 | printk("BootROM device addition failed\n"); | 213 | printk("BootROM device addition failed\n"); |
214 | err = -ENOMEM; | 214 | err = -ENOMEM; |
215 | goto out_probe; | 215 | goto out_probe; |
@@ -249,21 +249,21 @@ static int __init init_cdb89712_maps(void) | |||
249 | static void __exit cleanup_cdb89712_maps(void) | 249 | static void __exit cleanup_cdb89712_maps(void) |
250 | { | 250 | { |
251 | if (sram_mtd) { | 251 | if (sram_mtd) { |
252 | del_mtd_device(sram_mtd); | 252 | mtd_device_unregister(sram_mtd); |
253 | map_destroy(sram_mtd); | 253 | map_destroy(sram_mtd); |
254 | iounmap((void *)cdb89712_sram_map.virt); | 254 | iounmap((void *)cdb89712_sram_map.virt); |
255 | release_resource (&cdb89712_sram_resource); | 255 | release_resource (&cdb89712_sram_resource); |
256 | } | 256 | } |
257 | 257 | ||
258 | if (flash_mtd) { | 258 | if (flash_mtd) { |
259 | del_mtd_device(flash_mtd); | 259 | mtd_device_unregister(flash_mtd); |
260 | map_destroy(flash_mtd); | 260 | map_destroy(flash_mtd); |
261 | iounmap((void *)cdb89712_flash_map.virt); | 261 | iounmap((void *)cdb89712_flash_map.virt); |
262 | release_resource (&cdb89712_flash_resource); | 262 | release_resource (&cdb89712_flash_resource); |
263 | } | 263 | } |
264 | 264 | ||
265 | if (bootrom_mtd) { | 265 | if (bootrom_mtd) { |
266 | del_mtd_device(bootrom_mtd); | 266 | mtd_device_unregister(bootrom_mtd); |
267 | map_destroy(bootrom_mtd); | 267 | map_destroy(bootrom_mtd); |
268 | iounmap((void *)cdb89712_bootrom_map.virt); | 268 | iounmap((void *)cdb89712_bootrom_map.virt); |
269 | release_resource (&cdb89712_bootrom_resource); | 269 | release_resource (&cdb89712_bootrom_resource); |
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c index 23f551dc8ca8..06f9c9815720 100644 --- a/drivers/mtd/maps/ceiva.c +++ b/drivers/mtd/maps/ceiva.c | |||
@@ -224,7 +224,7 @@ static void __exit clps_destroy_mtd(struct clps_info *clps, struct mtd_info *mtd | |||
224 | { | 224 | { |
225 | int i; | 225 | int i; |
226 | 226 | ||
227 | del_mtd_partitions(mtd); | 227 | mtd_device_unregister(mtd); |
228 | 228 | ||
229 | if (mtd != clps[0].mtd) | 229 | if (mtd != clps[0].mtd) |
230 | mtd_concat_destroy(mtd); | 230 | mtd_concat_destroy(mtd); |
@@ -292,11 +292,11 @@ static void __init clps_locate_partitions(struct mtd_info *mtd) | |||
292 | if (nr_parts == 0) { | 292 | if (nr_parts == 0) { |
293 | printk(KERN_NOTICE "clps flash: no partition info " | 293 | printk(KERN_NOTICE "clps flash: no partition info " |
294 | "available, registering whole flash\n"); | 294 | "available, registering whole flash\n"); |
295 | add_mtd_device(mtd); | 295 | mtd_device_register(mtd, NULL, 0); |
296 | } else { | 296 | } else { |
297 | printk(KERN_NOTICE "clps flash: using %s partition " | 297 | printk(KERN_NOTICE "clps flash: using %s partition " |
298 | "definition\n", part_type); | 298 | "definition\n", part_type); |
299 | add_mtd_partitions(mtd, parsed_parts, nr_parts); | 299 | mtd_device_register(mtd, parsed_parts, nr_parts); |
300 | } | 300 | } |
301 | 301 | ||
302 | /* Always succeeds. */ | 302 | /* Always succeeds. */ |
diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c index f71343cd77cc..d16fc9d3b8cd 100644 --- a/drivers/mtd/maps/cfi_flagadm.c +++ b/drivers/mtd/maps/cfi_flagadm.c | |||
@@ -107,7 +107,7 @@ static int __init init_flagadm(void) | |||
107 | mymtd = do_map_probe("cfi_probe", &flagadm_map); | 107 | mymtd = do_map_probe("cfi_probe", &flagadm_map); |
108 | if (mymtd) { | 108 | if (mymtd) { |
109 | mymtd->owner = THIS_MODULE; | 109 | mymtd->owner = THIS_MODULE; |
110 | add_mtd_partitions(mymtd, flagadm_parts, PARTITION_COUNT); | 110 | mtd_device_register(mymtd, flagadm_parts, PARTITION_COUNT); |
111 | printk(KERN_NOTICE "FlagaDM flash device initialized\n"); | 111 | printk(KERN_NOTICE "FlagaDM flash device initialized\n"); |
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
@@ -119,7 +119,7 @@ static int __init init_flagadm(void) | |||
119 | static void __exit cleanup_flagadm(void) | 119 | static void __exit cleanup_flagadm(void) |
120 | { | 120 | { |
121 | if (mymtd) { | 121 | if (mymtd) { |
122 | del_mtd_partitions(mymtd); | 122 | mtd_device_unregister(mymtd); |
123 | map_destroy(mymtd); | 123 | map_destroy(mymtd); |
124 | } | 124 | } |
125 | if (flagadm_map.virt) { | 125 | if (flagadm_map.virt) { |
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index 5fdb7b26cea3..3d0e762fa5f2 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c | |||
@@ -94,7 +94,7 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window) | |||
94 | if (map->rsrc.parent) | 94 | if (map->rsrc.parent) |
95 | release_resource(&map->rsrc); | 95 | release_resource(&map->rsrc); |
96 | 96 | ||
97 | del_mtd_device(map->mtd); | 97 | mtd_device_unregister(map->mtd); |
98 | map_destroy(map->mtd); | 98 | map_destroy(map->mtd); |
99 | list_del(&map->list); | 99 | list_del(&map->list); |
100 | kfree(map); | 100 | kfree(map); |
@@ -291,7 +291,7 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev, | |||
291 | 291 | ||
292 | /* Now that the mtd devices is complete claim and export it */ | 292 | /* Now that the mtd devices is complete claim and export it */ |
293 | map->mtd->owner = THIS_MODULE; | 293 | map->mtd->owner = THIS_MODULE; |
294 | if (add_mtd_device(map->mtd)) { | 294 | if (mtd_device_register(map->mtd, NULL, 0)) { |
295 | map_destroy(map->mtd); | 295 | map_destroy(map->mtd); |
296 | map->mtd = NULL; | 296 | map->mtd = NULL; |
297 | goto out; | 297 | goto out; |
diff --git a/drivers/mtd/maps/dbox2-flash.c b/drivers/mtd/maps/dbox2-flash.c index cfacfa6f45dd..85bdece6ab3f 100644 --- a/drivers/mtd/maps/dbox2-flash.c +++ b/drivers/mtd/maps/dbox2-flash.c | |||
@@ -93,7 +93,7 @@ static int __init init_dbox2_flash(void) | |||
93 | mymtd->owner = THIS_MODULE; | 93 | mymtd->owner = THIS_MODULE; |
94 | 94 | ||
95 | /* Create MTD devices for each partition. */ | 95 | /* Create MTD devices for each partition. */ |
96 | add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS); | 96 | mtd_device_register(mymtd, partition_info, NUM_PARTITIONS); |
97 | 97 | ||
98 | return 0; | 98 | return 0; |
99 | } | 99 | } |
@@ -105,7 +105,7 @@ static int __init init_dbox2_flash(void) | |||
105 | static void __exit cleanup_dbox2_flash(void) | 105 | static void __exit cleanup_dbox2_flash(void) |
106 | { | 106 | { |
107 | if (mymtd) { | 107 | if (mymtd) { |
108 | del_mtd_partitions(mymtd); | 108 | mtd_device_unregister(mymtd); |
109 | map_destroy(mymtd); | 109 | map_destroy(mymtd); |
110 | } | 110 | } |
111 | if (dbox2_flash_map.virt) { | 111 | if (dbox2_flash_map.virt) { |
diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c index b3cb3a183809..7a9e1989c977 100644 --- a/drivers/mtd/maps/dc21285.c +++ b/drivers/mtd/maps/dc21285.c | |||
@@ -145,17 +145,13 @@ static struct map_info dc21285_map = { | |||
145 | 145 | ||
146 | 146 | ||
147 | /* Partition stuff */ | 147 | /* Partition stuff */ |
148 | #ifdef CONFIG_MTD_PARTITIONS | ||
149 | static struct mtd_partition *dc21285_parts; | 148 | static struct mtd_partition *dc21285_parts; |
150 | static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; | 149 | static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; |
151 | #endif | ||
152 | 150 | ||
153 | static int __init init_dc21285(void) | 151 | static int __init init_dc21285(void) |
154 | { | 152 | { |
155 | 153 | ||
156 | #ifdef CONFIG_MTD_PARTITIONS | ||
157 | int nrparts; | 154 | int nrparts; |
158 | #endif | ||
159 | 155 | ||
160 | /* Determine bankwidth */ | 156 | /* Determine bankwidth */ |
161 | switch (*CSR_SA110_CNTL & (3<<14)) { | 157 | switch (*CSR_SA110_CNTL & (3<<14)) { |
@@ -204,13 +200,8 @@ static int __init init_dc21285(void) | |||
204 | 200 | ||
205 | dc21285_mtd->owner = THIS_MODULE; | 201 | dc21285_mtd->owner = THIS_MODULE; |
206 | 202 | ||
207 | #ifdef CONFIG_MTD_PARTITIONS | ||
208 | nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0); | 203 | nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0); |
209 | if (nrparts > 0) | 204 | mtd_device_register(dc21285_mtd, dc21285_parts, nrparts); |
210 | add_mtd_partitions(dc21285_mtd, dc21285_parts, nrparts); | ||
211 | else | ||
212 | #endif | ||
213 | add_mtd_device(dc21285_mtd); | ||
214 | 205 | ||
215 | if(machine_is_ebsa285()) { | 206 | if(machine_is_ebsa285()) { |
216 | /* | 207 | /* |
@@ -232,14 +223,9 @@ static int __init init_dc21285(void) | |||
232 | 223 | ||
233 | static void __exit cleanup_dc21285(void) | 224 | static void __exit cleanup_dc21285(void) |
234 | { | 225 | { |
235 | #ifdef CONFIG_MTD_PARTITIONS | 226 | mtd_device_unregister(dc21285_mtd); |
236 | if (dc21285_parts) { | 227 | if (dc21285_parts) |
237 | del_mtd_partitions(dc21285_mtd); | ||
238 | kfree(dc21285_parts); | 228 | kfree(dc21285_parts); |
239 | } else | ||
240 | #endif | ||
241 | del_mtd_device(dc21285_mtd); | ||
242 | |||
243 | map_destroy(dc21285_mtd); | 229 | map_destroy(dc21285_mtd); |
244 | iounmap(dc21285_map.virt); | 230 | iounmap(dc21285_map.virt); |
245 | } | 231 | } |
diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c index 0713e3a5a22c..3e393f0da823 100644 --- a/drivers/mtd/maps/dilnetpc.c +++ b/drivers/mtd/maps/dilnetpc.c | |||
@@ -450,7 +450,7 @@ static int __init init_dnpc(void) | |||
450 | partition_info[2].mtdp = &lowlvl_parts[1]; | 450 | partition_info[2].mtdp = &lowlvl_parts[1]; |
451 | partition_info[3].mtdp = &lowlvl_parts[3]; | 451 | partition_info[3].mtdp = &lowlvl_parts[3]; |
452 | 452 | ||
453 | add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS); | 453 | mtd_device_register(mymtd, partition_info, NUM_PARTITIONS); |
454 | 454 | ||
455 | /* | 455 | /* |
456 | ** now create a virtual MTD device by concatenating the for partitions | 456 | ** now create a virtual MTD device by concatenating the for partitions |
@@ -463,7 +463,8 @@ static int __init init_dnpc(void) | |||
463 | ** we do not supply mtd pointers in higlvl_partition_info, so | 463 | ** we do not supply mtd pointers in higlvl_partition_info, so |
464 | ** add_mtd_partitions() will register the devices. | 464 | ** add_mtd_partitions() will register the devices. |
465 | */ | 465 | */ |
466 | add_mtd_partitions(merged_mtd, higlvl_partition_info, NUM_HIGHLVL_PARTITIONS); | 466 | mtd_device_register(merged_mtd, higlvl_partition_info, |
467 | NUM_HIGHLVL_PARTITIONS); | ||
467 | } | 468 | } |
468 | 469 | ||
469 | return 0; | 470 | return 0; |
@@ -472,12 +473,12 @@ static int __init init_dnpc(void) | |||
472 | static void __exit cleanup_dnpc(void) | 473 | static void __exit cleanup_dnpc(void) |
473 | { | 474 | { |
474 | if(merged_mtd) { | 475 | if(merged_mtd) { |
475 | del_mtd_partitions(merged_mtd); | 476 | mtd_device_unregister(merged_mtd); |
476 | mtd_concat_destroy(merged_mtd); | 477 | mtd_concat_destroy(merged_mtd); |
477 | } | 478 | } |
478 | 479 | ||
479 | if (mymtd) { | 480 | if (mymtd) { |
480 | del_mtd_partitions(mymtd); | 481 | mtd_device_unregister(mymtd); |
481 | map_destroy(mymtd); | 482 | map_destroy(mymtd); |
482 | } | 483 | } |
483 | if (dnpc_map.virt) { | 484 | if (dnpc_map.virt) { |
diff --git a/drivers/mtd/maps/dmv182.c b/drivers/mtd/maps/dmv182.c index d171674eb2ed..6538ac675e00 100644 --- a/drivers/mtd/maps/dmv182.c +++ b/drivers/mtd/maps/dmv182.c | |||
@@ -120,7 +120,7 @@ static int __init init_svme182(void) | |||
120 | this_mtd->size >> 20, FLASH_BASE_ADDR); | 120 | this_mtd->size >> 20, FLASH_BASE_ADDR); |
121 | 121 | ||
122 | this_mtd->owner = THIS_MODULE; | 122 | this_mtd->owner = THIS_MODULE; |
123 | add_mtd_partitions(this_mtd, partitions, num_parts); | 123 | mtd_device_register(this_mtd, partitions, num_parts); |
124 | 124 | ||
125 | return 0; | 125 | return 0; |
126 | } | 126 | } |
@@ -129,7 +129,7 @@ static void __exit cleanup_svme182(void) | |||
129 | { | 129 | { |
130 | if (this_mtd) | 130 | if (this_mtd) |
131 | { | 131 | { |
132 | del_mtd_partitions(this_mtd); | 132 | mtd_device_unregister(this_mtd); |
133 | map_destroy(this_mtd); | 133 | map_destroy(this_mtd); |
134 | } | 134 | } |
135 | 135 | ||
diff --git a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c index be9e90b44587..fe42a212bb3e 100644 --- a/drivers/mtd/maps/edb7312.c +++ b/drivers/mtd/maps/edb7312.c | |||
@@ -15,10 +15,7 @@ | |||
15 | #include <asm/io.h> | 15 | #include <asm/io.h> |
16 | #include <linux/mtd/mtd.h> | 16 | #include <linux/mtd/mtd.h> |
17 | #include <linux/mtd/map.h> | 17 | #include <linux/mtd/map.h> |
18 | |||
19 | #ifdef CONFIG_MTD_PARTITIONS | ||
20 | #include <linux/mtd/partitions.h> | 18 | #include <linux/mtd/partitions.h> |
21 | #endif | ||
22 | 19 | ||
23 | #define WINDOW_ADDR 0x00000000 /* physical properties of flash */ | 20 | #define WINDOW_ADDR 0x00000000 /* physical properties of flash */ |
24 | #define WINDOW_SIZE 0x01000000 | 21 | #define WINDOW_SIZE 0x01000000 |
@@ -40,8 +37,6 @@ struct map_info edb7312nor_map = { | |||
40 | .phys = WINDOW_ADDR, | 37 | .phys = WINDOW_ADDR, |
41 | }; | 38 | }; |
42 | 39 | ||
43 | #ifdef CONFIG_MTD_PARTITIONS | ||
44 | |||
45 | /* | 40 | /* |
46 | * MTD partitioning stuff | 41 | * MTD partitioning stuff |
47 | */ | 42 | */ |
@@ -66,8 +61,6 @@ static struct mtd_partition static_partitions[3] = | |||
66 | 61 | ||
67 | static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; | 62 | static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; |
68 | 63 | ||
69 | #endif | ||
70 | |||
71 | static int mtd_parts_nb = 0; | 64 | static int mtd_parts_nb = 0; |
72 | static struct mtd_partition *mtd_parts = 0; | 65 | static struct mtd_partition *mtd_parts = 0; |
73 | 66 | ||
@@ -96,27 +89,24 @@ static int __init init_edb7312nor(void) | |||
96 | if (mymtd) { | 89 | if (mymtd) { |
97 | mymtd->owner = THIS_MODULE; | 90 | mymtd->owner = THIS_MODULE; |
98 | 91 | ||
99 | #ifdef CONFIG_MTD_PARTITIONS | ||
100 | mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID); | 92 | mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID); |
101 | if (mtd_parts_nb > 0) | 93 | if (mtd_parts_nb > 0) |
102 | part_type = "detected"; | 94 | part_type = "detected"; |
103 | 95 | ||
104 | if (mtd_parts_nb == 0) | 96 | if (mtd_parts_nb == 0) { |
105 | { | ||
106 | mtd_parts = static_partitions; | 97 | mtd_parts = static_partitions; |
107 | mtd_parts_nb = ARRAY_SIZE(static_partitions); | 98 | mtd_parts_nb = ARRAY_SIZE(static_partitions); |
108 | part_type = "static"; | 99 | part_type = "static"; |
109 | } | 100 | } |
110 | #endif | 101 | |
111 | add_mtd_device(mymtd); | ||
112 | if (mtd_parts_nb == 0) | 102 | if (mtd_parts_nb == 0) |
113 | printk(KERN_NOTICE MSG_PREFIX "no partition info available\n"); | 103 | printk(KERN_NOTICE MSG_PREFIX "no partition info available\n"); |
114 | else | 104 | else |
115 | { | ||
116 | printk(KERN_NOTICE MSG_PREFIX | 105 | printk(KERN_NOTICE MSG_PREFIX |
117 | "using %s partition definition\n", part_type); | 106 | "using %s partition definition\n", part_type); |
118 | add_mtd_partitions(mymtd, mtd_parts, mtd_parts_nb); | 107 | /* Register the whole device first. */ |
119 | } | 108 | mtd_device_register(mymtd, NULL, 0); |
109 | mtd_device_register(mymtd, mtd_parts, mtd_parts_nb); | ||
120 | return 0; | 110 | return 0; |
121 | } | 111 | } |
122 | 112 | ||
@@ -127,7 +117,7 @@ static int __init init_edb7312nor(void) | |||
127 | static void __exit cleanup_edb7312nor(void) | 117 | static void __exit cleanup_edb7312nor(void) |
128 | { | 118 | { |
129 | if (mymtd) { | 119 | if (mymtd) { |
130 | del_mtd_device(mymtd); | 120 | mtd_device_unregister(mymtd); |
131 | map_destroy(mymtd); | 121 | map_destroy(mymtd); |
132 | } | 122 | } |
133 | if (edb7312nor_map.virt) { | 123 | if (edb7312nor_map.virt) { |
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c index 4feb7507ab7c..08322b1c3e81 100644 --- a/drivers/mtd/maps/esb2rom.c +++ b/drivers/mtd/maps/esb2rom.c | |||
@@ -128,7 +128,7 @@ static void esb2rom_cleanup(struct esb2rom_window *window) | |||
128 | list_for_each_entry_safe(map, scratch, &window->maps, list) { | 128 | list_for_each_entry_safe(map, scratch, &window->maps, list) { |
129 | if (map->rsrc.parent) | 129 | if (map->rsrc.parent) |
130 | release_resource(&map->rsrc); | 130 | release_resource(&map->rsrc); |
131 | del_mtd_device(map->mtd); | 131 | mtd_device_unregister(map->mtd); |
132 | map_destroy(map->mtd); | 132 | map_destroy(map->mtd); |
133 | list_del(&map->list); | 133 | list_del(&map->list); |
134 | kfree(map); | 134 | kfree(map); |
@@ -352,7 +352,7 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev, | |||
352 | 352 | ||
353 | /* Now that the mtd devices is complete claim and export it */ | 353 | /* Now that the mtd devices is complete claim and export it */ |
354 | map->mtd->owner = THIS_MODULE; | 354 | map->mtd->owner = THIS_MODULE; |
355 | if (add_mtd_device(map->mtd)) { | 355 | if (mtd_device_register(map->mtd, NULL, 0)) { |
356 | map_destroy(map->mtd); | 356 | map_destroy(map->mtd); |
357 | map->mtd = NULL; | 357 | map->mtd = NULL; |
358 | goto out; | 358 | goto out; |
diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c index 1e43124d498b..956e2e4f30ea 100644 --- a/drivers/mtd/maps/fortunet.c +++ b/drivers/mtd/maps/fortunet.c | |||
@@ -243,8 +243,9 @@ static int __init init_fortunet(void) | |||
243 | &map_regions[ix].map_info); | 243 | &map_regions[ix].map_info); |
244 | } | 244 | } |
245 | map_regions[ix].mymtd->owner = THIS_MODULE; | 245 | map_regions[ix].mymtd->owner = THIS_MODULE; |
246 | add_mtd_partitions(map_regions[ix].mymtd, | 246 | mtd_device_register(map_regions[ix].mymtd, |
247 | map_regions[ix].parts,map_regions_parts[ix]); | 247 | map_regions[ix].parts, |
248 | map_regions_parts[ix]); | ||
248 | } | 249 | } |
249 | } | 250 | } |
250 | if(iy) | 251 | if(iy) |
@@ -261,7 +262,7 @@ static void __exit cleanup_fortunet(void) | |||
261 | { | 262 | { |
262 | if( map_regions[ix].mymtd ) | 263 | if( map_regions[ix].mymtd ) |
263 | { | 264 | { |
264 | del_mtd_partitions( map_regions[ix].mymtd ); | 265 | mtd_device_unregister(map_regions[ix].mymtd); |
265 | map_destroy( map_regions[ix].mymtd ); | 266 | map_destroy( map_regions[ix].mymtd ); |
266 | } | 267 | } |
267 | iounmap((void *)map_regions[ix].map_info.virt); | 268 | iounmap((void *)map_regions[ix].map_info.virt); |
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c index af5707a80205..7568c5f8b8ae 100644 --- a/drivers/mtd/maps/gpio-addr-flash.c +++ b/drivers/mtd/maps/gpio-addr-flash.c | |||
@@ -155,9 +155,7 @@ static void gf_copy_to(struct map_info *map, unsigned long to, const void *from, | |||
155 | memcpy_toio(map->virt + (to % state->win_size), from, len); | 155 | memcpy_toio(map->virt + (to % state->win_size), from, len); |
156 | } | 156 | } |
157 | 157 | ||
158 | #ifdef CONFIG_MTD_PARTITIONS | ||
159 | static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; | 158 | static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; |
160 | #endif | ||
161 | 159 | ||
162 | /** | 160 | /** |
163 | * gpio_flash_probe() - setup a mapping for a GPIO assisted flash | 161 | * gpio_flash_probe() - setup a mapping for a GPIO assisted flash |
@@ -189,7 +187,7 @@ static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; | |||
189 | */ | 187 | */ |
190 | static int __devinit gpio_flash_probe(struct platform_device *pdev) | 188 | static int __devinit gpio_flash_probe(struct platform_device *pdev) |
191 | { | 189 | { |
192 | int ret; | 190 | int nr_parts; |
193 | size_t i, arr_size; | 191 | size_t i, arr_size; |
194 | struct physmap_flash_data *pdata; | 192 | struct physmap_flash_data *pdata; |
195 | struct resource *memory; | 193 | struct resource *memory; |
@@ -254,24 +252,21 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev) | |||
254 | return -ENXIO; | 252 | return -ENXIO; |
255 | } | 253 | } |
256 | 254 | ||
257 | #ifdef CONFIG_MTD_PARTITIONS | 255 | nr_parts = parse_mtd_partitions(state->mtd, part_probe_types, |
258 | ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0); | 256 | &pdata->parts, 0); |
259 | if (ret > 0) { | 257 | if (nr_parts > 0) { |
260 | pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n"); | 258 | pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n"); |
261 | add_mtd_partitions(state->mtd, pdata->parts, ret); | ||
262 | kfree(pdata->parts); | 259 | kfree(pdata->parts); |
263 | |||
264 | } else if (pdata->nr_parts) { | 260 | } else if (pdata->nr_parts) { |
265 | pr_devinit(KERN_NOTICE PFX "Using board partition definition\n"); | 261 | pr_devinit(KERN_NOTICE PFX "Using board partition definition\n"); |
266 | add_mtd_partitions(state->mtd, pdata->parts, pdata->nr_parts); | 262 | nr_parts = pdata->nr_parts; |
267 | 263 | } else { | |
268 | } else | ||
269 | #endif | ||
270 | { | ||
271 | pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n"); | 264 | pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n"); |
272 | add_mtd_device(state->mtd); | 265 | nr_parts = 0; |
273 | } | 266 | } |
274 | 267 | ||
268 | mtd_device_register(state->mtd, pdata->parts, nr_parts); | ||
269 | |||
275 | return 0; | 270 | return 0; |
276 | } | 271 | } |
277 | 272 | ||
@@ -282,9 +277,7 @@ static int __devexit gpio_flash_remove(struct platform_device *pdev) | |||
282 | do { | 277 | do { |
283 | gpio_free(state->gpio_addrs[i]); | 278 | gpio_free(state->gpio_addrs[i]); |
284 | } while (++i < state->gpio_count); | 279 | } while (++i < state->gpio_count); |
285 | #ifdef CONFIG_MTD_PARTITIONS | 280 | mtd_device_unregister(state->mtd); |
286 | del_mtd_partitions(state->mtd); | ||
287 | #endif | ||
288 | map_destroy(state->mtd); | 281 | map_destroy(state->mtd); |
289 | kfree(state); | 282 | kfree(state); |
290 | return 0; | 283 | return 0; |
diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c index 72c724fa8c27..7f035860a36b 100644 --- a/drivers/mtd/maps/h720x-flash.c +++ b/drivers/mtd/maps/h720x-flash.c | |||
@@ -92,18 +92,16 @@ static int __init h720x_mtd_init(void) | |||
92 | if (mymtd) { | 92 | if (mymtd) { |
93 | mymtd->owner = THIS_MODULE; | 93 | mymtd->owner = THIS_MODULE; |
94 | 94 | ||
95 | #ifdef CONFIG_MTD_PARTITIONS | ||
96 | nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0); | 95 | nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0); |
97 | if (nr_mtd_parts > 0) | 96 | if (nr_mtd_parts > 0) |
98 | part_type = "command line"; | 97 | part_type = "command line"; |
99 | #endif | ||
100 | if (nr_mtd_parts <= 0) { | 98 | if (nr_mtd_parts <= 0) { |
101 | mtd_parts = h720x_partitions; | 99 | mtd_parts = h720x_partitions; |
102 | nr_mtd_parts = NUM_PARTITIONS; | 100 | nr_mtd_parts = NUM_PARTITIONS; |
103 | part_type = "builtin"; | 101 | part_type = "builtin"; |
104 | } | 102 | } |
105 | printk(KERN_INFO "Using %s partition table\n", part_type); | 103 | printk(KERN_INFO "Using %s partition table\n", part_type); |
106 | add_mtd_partitions(mymtd, mtd_parts, nr_mtd_parts); | 104 | mtd_device_register(mymtd, mtd_parts, nr_mtd_parts); |
107 | return 0; | 105 | return 0; |
108 | } | 106 | } |
109 | 107 | ||
@@ -118,7 +116,7 @@ static void __exit h720x_mtd_cleanup(void) | |||
118 | { | 116 | { |
119 | 117 | ||
120 | if (mymtd) { | 118 | if (mymtd) { |
121 | del_mtd_partitions(mymtd); | 119 | mtd_device_unregister(mymtd); |
122 | map_destroy(mymtd); | 120 | map_destroy(mymtd); |
123 | } | 121 | } |
124 | 122 | ||
diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index 1337a4191a0c..6689dcb3124d 100644 --- a/drivers/mtd/maps/ichxrom.c +++ b/drivers/mtd/maps/ichxrom.c | |||
@@ -67,7 +67,7 @@ static void ichxrom_cleanup(struct ichxrom_window *window) | |||
67 | list_for_each_entry_safe(map, scratch, &window->maps, list) { | 67 | list_for_each_entry_safe(map, scratch, &window->maps, list) { |
68 | if (map->rsrc.parent) | 68 | if (map->rsrc.parent) |
69 | release_resource(&map->rsrc); | 69 | release_resource(&map->rsrc); |
70 | del_mtd_device(map->mtd); | 70 | mtd_device_unregister(map->mtd); |
71 | map_destroy(map->mtd); | 71 | map_destroy(map->mtd); |
72 | list_del(&map->list); | 72 | list_del(&map->list); |
73 | kfree(map); | 73 | kfree(map); |
@@ -287,7 +287,7 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, | |||
287 | 287 | ||
288 | /* Now that the mtd devices is complete claim and export it */ | 288 | /* Now that the mtd devices is complete claim and export it */ |
289 | map->mtd->owner = THIS_MODULE; | 289 | map->mtd->owner = THIS_MODULE; |
290 | if (add_mtd_device(map->mtd)) { | 290 | if (mtd_device_register(map->mtd, NULL, 0)) { |
291 | map_destroy(map->mtd); | 291 | map_destroy(map->mtd); |
292 | map->mtd = NULL; | 292 | map->mtd = NULL; |
293 | goto out; | 293 | goto out; |
diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c index 998a27da97f3..404a50cbafa0 100644 --- a/drivers/mtd/maps/impa7.c +++ b/drivers/mtd/maps/impa7.c | |||
@@ -15,10 +15,7 @@ | |||
15 | #include <asm/io.h> | 15 | #include <asm/io.h> |
16 | #include <linux/mtd/mtd.h> | 16 | #include <linux/mtd/mtd.h> |
17 | #include <linux/mtd/map.h> | 17 | #include <linux/mtd/map.h> |
18 | |||
19 | #ifdef CONFIG_MTD_PARTITIONS | ||
20 | #include <linux/mtd/partitions.h> | 18 | #include <linux/mtd/partitions.h> |
21 | #endif | ||
22 | 19 | ||
23 | #define WINDOW_ADDR0 0x00000000 /* physical properties of flash */ | 20 | #define WINDOW_ADDR0 0x00000000 /* physical properties of flash */ |
24 | #define WINDOW_SIZE0 0x00800000 | 21 | #define WINDOW_SIZE0 0x00800000 |
@@ -49,8 +46,6 @@ static struct map_info impa7_map[NUM_FLASHBANKS] = { | |||
49 | }, | 46 | }, |
50 | }; | 47 | }; |
51 | 48 | ||
52 | #ifdef CONFIG_MTD_PARTITIONS | ||
53 | |||
54 | /* | 49 | /* |
55 | * MTD partitioning stuff | 50 | * MTD partitioning stuff |
56 | */ | 51 | */ |
@@ -66,8 +61,6 @@ static struct mtd_partition static_partitions[] = | |||
66 | static int mtd_parts_nb[NUM_FLASHBANKS]; | 61 | static int mtd_parts_nb[NUM_FLASHBANKS]; |
67 | static struct mtd_partition *mtd_parts[NUM_FLASHBANKS]; | 62 | static struct mtd_partition *mtd_parts[NUM_FLASHBANKS]; |
68 | 63 | ||
69 | #endif | ||
70 | |||
71 | static const char *probes[] = { "cmdlinepart", NULL }; | 64 | static const char *probes[] = { "cmdlinepart", NULL }; |
72 | 65 | ||
73 | static int __init init_impa7(void) | 66 | static int __init init_impa7(void) |
@@ -104,7 +97,6 @@ static int __init init_impa7(void) | |||
104 | if (impa7_mtd[i]) { | 97 | if (impa7_mtd[i]) { |
105 | impa7_mtd[i]->owner = THIS_MODULE; | 98 | impa7_mtd[i]->owner = THIS_MODULE; |
106 | devicesfound++; | 99 | devicesfound++; |
107 | #ifdef CONFIG_MTD_PARTITIONS | ||
108 | mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i], | 100 | mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i], |
109 | probes, | 101 | probes, |
110 | &mtd_parts[i], | 102 | &mtd_parts[i], |
@@ -120,12 +112,8 @@ static int __init init_impa7(void) | |||
120 | printk(KERN_NOTICE MSG_PREFIX | 112 | printk(KERN_NOTICE MSG_PREFIX |
121 | "using %s partition definition\n", | 113 | "using %s partition definition\n", |
122 | part_type); | 114 | part_type); |
123 | add_mtd_partitions(impa7_mtd[i], | 115 | mtd_device_register(impa7_mtd[i], |
124 | mtd_parts[i], mtd_parts_nb[i]); | 116 | mtd_parts[i], mtd_parts_nb[i]); |
125 | #else | ||
126 | add_mtd_device(impa7_mtd[i]); | ||
127 | |||
128 | #endif | ||
129 | } | 117 | } |
130 | else | 118 | else |
131 | iounmap((void *)impa7_map[i].virt); | 119 | iounmap((void *)impa7_map[i].virt); |
@@ -138,11 +126,7 @@ static void __exit cleanup_impa7(void) | |||
138 | int i; | 126 | int i; |
139 | for (i=0; i<NUM_FLASHBANKS; i++) { | 127 | for (i=0; i<NUM_FLASHBANKS; i++) { |
140 | if (impa7_mtd[i]) { | 128 | if (impa7_mtd[i]) { |
141 | #ifdef CONFIG_MTD_PARTITIONS | 129 | mtd_device_unregister(impa7_mtd[i]); |
142 | del_mtd_partitions(impa7_mtd[i]); | ||
143 | #else | ||
144 | del_mtd_device(impa7_mtd[i]); | ||
145 | #endif | ||
146 | map_destroy(impa7_mtd[i]); | 130 | map_destroy(impa7_mtd[i]); |
147 | iounmap((void *)impa7_map[i].virt); | 131 | iounmap((void *)impa7_map[i].virt); |
148 | impa7_map[i].virt = 0; | 132 | impa7_map[i].virt = 0; |
diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c index fc1998512eb4..d2f47be8754b 100644 --- a/drivers/mtd/maps/intel_vr_nor.c +++ b/drivers/mtd/maps/intel_vr_nor.c | |||
@@ -66,33 +66,18 @@ struct vr_nor_mtd { | |||
66 | 66 | ||
67 | static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p) | 67 | static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p) |
68 | { | 68 | { |
69 | if (p->nr_parts > 0) { | 69 | mtd_device_unregister(p->info); |
70 | #if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE) | ||
71 | del_mtd_partitions(p->info); | ||
72 | #endif | ||
73 | } else | ||
74 | del_mtd_device(p->info); | ||
75 | } | 70 | } |
76 | 71 | ||
77 | static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p) | 72 | static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p) |
78 | { | 73 | { |
79 | int err = 0; | ||
80 | #if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE) | ||
81 | struct mtd_partition *parts; | 74 | struct mtd_partition *parts; |
82 | static const char *part_probes[] = { "cmdlinepart", NULL }; | 75 | static const char *part_probes[] = { "cmdlinepart", NULL }; |
83 | #endif | ||
84 | 76 | ||
85 | /* register the flash bank */ | 77 | /* register the flash bank */ |
86 | #if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE) | ||
87 | /* partition the flash bank */ | 78 | /* partition the flash bank */ |
88 | p->nr_parts = parse_mtd_partitions(p->info, part_probes, &parts, 0); | 79 | p->nr_parts = parse_mtd_partitions(p->info, part_probes, &parts, 0); |
89 | if (p->nr_parts > 0) | 80 | return mtd_device_register(p->info, parts, p->nr_parts); |
90 | err = add_mtd_partitions(p->info, parts, p->nr_parts); | ||
91 | #endif | ||
92 | if (p->nr_parts <= 0) | ||
93 | err = add_mtd_device(p->info); | ||
94 | |||
95 | return err; | ||
96 | } | 81 | } |
97 | 82 | ||
98 | static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p) | 83 | static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p) |
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c index 9639d83a9d6c..c00b9175ba9e 100644 --- a/drivers/mtd/maps/ixp2000.c +++ b/drivers/mtd/maps/ixp2000.c | |||
@@ -119,7 +119,7 @@ static int ixp2000_flash_remove(struct platform_device *dev) | |||
119 | return 0; | 119 | return 0; |
120 | 120 | ||
121 | if (info->mtd) { | 121 | if (info->mtd) { |
122 | del_mtd_partitions(info->mtd); | 122 | mtd_device_unregister(info->mtd); |
123 | map_destroy(info->mtd); | 123 | map_destroy(info->mtd); |
124 | } | 124 | } |
125 | if (info->map.map_priv_1) | 125 | if (info->map.map_priv_1) |
@@ -230,7 +230,7 @@ static int ixp2000_flash_probe(struct platform_device *dev) | |||
230 | 230 | ||
231 | err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0); | 231 | err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0); |
232 | if (err > 0) { | 232 | if (err > 0) { |
233 | err = add_mtd_partitions(info->mtd, info->partitions, err); | 233 | err = mtd_device_register(info->mtd, info->partitions, err); |
234 | if(err) | 234 | if(err) |
235 | dev_err(&dev->dev, "Could not parse partitions\n"); | 235 | dev_err(&dev->dev, "Could not parse partitions\n"); |
236 | } | 236 | } |
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 1f9fde0dad35..155b21942f47 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c | |||
@@ -162,7 +162,7 @@ static int ixp4xx_flash_remove(struct platform_device *dev) | |||
162 | return 0; | 162 | return 0; |
163 | 163 | ||
164 | if (info->mtd) { | 164 | if (info->mtd) { |
165 | del_mtd_partitions(info->mtd); | 165 | mtd_device_unregister(info->mtd); |
166 | map_destroy(info->mtd); | 166 | map_destroy(info->mtd); |
167 | } | 167 | } |
168 | if (info->map.virt) | 168 | if (info->map.virt) |
@@ -252,10 +252,8 @@ static int ixp4xx_flash_probe(struct platform_device *dev) | |||
252 | /* Use the fast version */ | 252 | /* Use the fast version */ |
253 | info->map.write = ixp4xx_write16; | 253 | info->map.write = ixp4xx_write16; |
254 | 254 | ||
255 | #ifdef CONFIG_MTD_PARTITIONS | ||
256 | nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions, | 255 | nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions, |
257 | dev->resource->start); | 256 | dev->resource->start); |
258 | #endif | ||
259 | if (nr_parts > 0) { | 257 | if (nr_parts > 0) { |
260 | part_type = "dynamic"; | 258 | part_type = "dynamic"; |
261 | } else { | 259 | } else { |
@@ -263,18 +261,16 @@ static int ixp4xx_flash_probe(struct platform_device *dev) | |||
263 | nr_parts = plat->nr_parts; | 261 | nr_parts = plat->nr_parts; |
264 | part_type = "static"; | 262 | part_type = "static"; |
265 | } | 263 | } |
266 | if (nr_parts == 0) { | 264 | if (nr_parts == 0) |
267 | printk(KERN_NOTICE "IXP4xx flash: no partition info " | 265 | printk(KERN_NOTICE "IXP4xx flash: no partition info " |
268 | "available, registering whole flash\n"); | 266 | "available, registering whole flash\n"); |
269 | err = add_mtd_device(info->mtd); | 267 | else |
270 | } else { | ||
271 | printk(KERN_NOTICE "IXP4xx flash: using %s partition " | 268 | printk(KERN_NOTICE "IXP4xx flash: using %s partition " |
272 | "definition\n", part_type); | 269 | "definition\n", part_type); |
273 | err = add_mtd_partitions(info->mtd, info->partitions, nr_parts); | ||
274 | 270 | ||
275 | if(err) | 271 | err = mtd_device_register(info->mtd, info->partitions, nr_parts); |
276 | printk(KERN_ERR "Could not parse partitions\n"); | 272 | if (err) |
277 | } | 273 | printk(KERN_ERR "Could not parse partitions\n"); |
278 | 274 | ||
279 | if (err) | 275 | if (err) |
280 | goto Error; | 276 | goto Error; |
diff --git a/drivers/mtd/maps/l440gx.c b/drivers/mtd/maps/l440gx.c index 9e054503c4cf..dd0360ba2412 100644 --- a/drivers/mtd/maps/l440gx.c +++ b/drivers/mtd/maps/l440gx.c | |||
@@ -138,7 +138,7 @@ static int __init init_l440gx(void) | |||
138 | if (mymtd) { | 138 | if (mymtd) { |
139 | mymtd->owner = THIS_MODULE; | 139 | mymtd->owner = THIS_MODULE; |
140 | 140 | ||
141 | add_mtd_device(mymtd); | 141 | mtd_device_register(mymtd, NULL, 0); |
142 | return 0; | 142 | return 0; |
143 | } | 143 | } |
144 | 144 | ||
@@ -148,7 +148,7 @@ static int __init init_l440gx(void) | |||
148 | 148 | ||
149 | static void __exit cleanup_l440gx(void) | 149 | static void __exit cleanup_l440gx(void) |
150 | { | 150 | { |
151 | del_mtd_device(mymtd); | 151 | mtd_device_unregister(mymtd); |
152 | map_destroy(mymtd); | 152 | map_destroy(mymtd); |
153 | 153 | ||
154 | iounmap(l440gx_map.virt); | 154 | iounmap(l440gx_map.virt); |
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c index ee2548085334..5936c466e901 100644 --- a/drivers/mtd/maps/latch-addr-flash.c +++ b/drivers/mtd/maps/latch-addr-flash.c | |||
@@ -112,18 +112,9 @@ static int latch_addr_flash_remove(struct platform_device *dev) | |||
112 | latch_addr_data = dev->dev.platform_data; | 112 | latch_addr_data = dev->dev.platform_data; |
113 | 113 | ||
114 | if (info->mtd != NULL) { | 114 | if (info->mtd != NULL) { |
115 | if (mtd_has_partitions()) { | 115 | if (info->nr_parts) |
116 | if (info->nr_parts) { | 116 | kfree(info->parts); |
117 | del_mtd_partitions(info->mtd); | 117 | mtd_device_unregister(info->mtd); |
118 | kfree(info->parts); | ||
119 | } else if (latch_addr_data->nr_parts) { | ||
120 | del_mtd_partitions(info->mtd); | ||
121 | } else { | ||
122 | del_mtd_device(info->mtd); | ||
123 | } | ||
124 | } else { | ||
125 | del_mtd_device(info->mtd); | ||
126 | } | ||
127 | map_destroy(info->mtd); | 118 | map_destroy(info->mtd); |
128 | } | 119 | } |
129 | 120 | ||
@@ -215,23 +206,21 @@ static int __devinit latch_addr_flash_probe(struct platform_device *dev) | |||
215 | } | 206 | } |
216 | info->mtd->owner = THIS_MODULE; | 207 | info->mtd->owner = THIS_MODULE; |
217 | 208 | ||
218 | if (mtd_has_partitions()) { | 209 | err = parse_mtd_partitions(info->mtd, (const char **)part_probe_types, |
219 | 210 | &info->parts, 0); | |
220 | err = parse_mtd_partitions(info->mtd, | 211 | if (err > 0) { |
221 | (const char **)part_probe_types, | 212 | mtd_device_register(info->mtd, info->parts, err); |
222 | &info->parts, 0); | 213 | return 0; |
223 | if (err > 0) { | 214 | } |
224 | add_mtd_partitions(info->mtd, info->parts, err); | 215 | if (latch_addr_data->nr_parts) { |
225 | return 0; | 216 | pr_notice("Using latch-addr-flash partition information\n"); |
226 | } | 217 | mtd_device_register(info->mtd, |
227 | if (latch_addr_data->nr_parts) { | 218 | latch_addr_data->parts, |
228 | pr_notice("Using latch-addr-flash partition information\n"); | 219 | latch_addr_data->nr_parts); |
229 | add_mtd_partitions(info->mtd, latch_addr_data->parts, | 220 | return 0; |
230 | latch_addr_data->nr_parts); | ||
231 | return 0; | ||
232 | } | ||
233 | } | 221 | } |
234 | add_mtd_device(info->mtd); | 222 | |
223 | mtd_device_register(info->mtd, NULL, 0); | ||
235 | return 0; | 224 | return 0; |
236 | 225 | ||
237 | iounmap: | 226 | iounmap: |
diff --git a/drivers/mtd/maps/mbx860.c b/drivers/mtd/maps/mbx860.c index 0eb5a7c85380..93fa56c33003 100644 --- a/drivers/mtd/maps/mbx860.c +++ b/drivers/mtd/maps/mbx860.c | |||
@@ -69,8 +69,8 @@ static int __init init_mbx(void) | |||
69 | mymtd = do_map_probe("jedec_probe", &mbx_map); | 69 | mymtd = do_map_probe("jedec_probe", &mbx_map); |
70 | if (mymtd) { | 70 | if (mymtd) { |
71 | mymtd->owner = THIS_MODULE; | 71 | mymtd->owner = THIS_MODULE; |
72 | add_mtd_device(mymtd); | 72 | mtd_device_register(mymtd, NULL, 0); |
73 | add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS); | 73 | mtd_device_register(mymtd, partition_info, NUM_PARTITIONS); |
74 | return 0; | 74 | return 0; |
75 | } | 75 | } |
76 | 76 | ||
@@ -81,7 +81,7 @@ static int __init init_mbx(void) | |||
81 | static void __exit cleanup_mbx(void) | 81 | static void __exit cleanup_mbx(void) |
82 | { | 82 | { |
83 | if (mymtd) { | 83 | if (mymtd) { |
84 | del_mtd_device(mymtd); | 84 | mtd_device_unregister(mymtd); |
85 | map_destroy(mymtd); | 85 | map_destroy(mymtd); |
86 | } | 86 | } |
87 | if (mbx_map.virt) { | 87 | if (mbx_map.virt) { |
diff --git a/drivers/mtd/maps/netsc520.c b/drivers/mtd/maps/netsc520.c index c0cb319b2b70..81dc2598bc0a 100644 --- a/drivers/mtd/maps/netsc520.c +++ b/drivers/mtd/maps/netsc520.c | |||
@@ -116,14 +116,14 @@ static int __init init_netsc520(void) | |||
116 | } | 116 | } |
117 | 117 | ||
118 | mymtd->owner = THIS_MODULE; | 118 | mymtd->owner = THIS_MODULE; |
119 | add_mtd_partitions( mymtd, partition_info, NUM_PARTITIONS ); | 119 | mtd_device_register(mymtd, partition_info, NUM_PARTITIONS); |
120 | return 0; | 120 | return 0; |
121 | } | 121 | } |
122 | 122 | ||
123 | static void __exit cleanup_netsc520(void) | 123 | static void __exit cleanup_netsc520(void) |
124 | { | 124 | { |
125 | if (mymtd) { | 125 | if (mymtd) { |
126 | del_mtd_partitions(mymtd); | 126 | mtd_device_unregister(mymtd); |
127 | map_destroy(mymtd); | 127 | map_destroy(mymtd); |
128 | } | 128 | } |
129 | if (netsc520_map.virt) { | 129 | if (netsc520_map.virt) { |
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c index a97133eb9d70..eadcfffc4f9c 100644 --- a/drivers/mtd/maps/nettel.c +++ b/drivers/mtd/maps/nettel.c | |||
@@ -383,13 +383,13 @@ static int __init nettel_init(void) | |||
383 | /* No BIOS regions when AMD boot */ | 383 | /* No BIOS regions when AMD boot */ |
384 | num_intel_partitions -= 2; | 384 | num_intel_partitions -= 2; |
385 | } | 385 | } |
386 | rc = add_mtd_partitions(intel_mtd, nettel_intel_partitions, | 386 | rc = mtd_device_register(intel_mtd, nettel_intel_partitions, |
387 | num_intel_partitions); | 387 | num_intel_partitions); |
388 | #endif | 388 | #endif |
389 | 389 | ||
390 | if (amd_mtd) { | 390 | if (amd_mtd) { |
391 | rc = add_mtd_partitions(amd_mtd, nettel_amd_partitions, | 391 | rc = mtd_device_register(amd_mtd, nettel_amd_partitions, |
392 | num_amd_partitions); | 392 | num_amd_partitions); |
393 | } | 393 | } |
394 | 394 | ||
395 | #ifdef CONFIG_MTD_CFI_INTELEXT | 395 | #ifdef CONFIG_MTD_CFI_INTELEXT |
@@ -419,7 +419,7 @@ static void __exit nettel_cleanup(void) | |||
419 | unregister_reboot_notifier(&nettel_notifier_block); | 419 | unregister_reboot_notifier(&nettel_notifier_block); |
420 | #endif | 420 | #endif |
421 | if (amd_mtd) { | 421 | if (amd_mtd) { |
422 | del_mtd_partitions(amd_mtd); | 422 | mtd_device_unregister(amd_mtd); |
423 | map_destroy(amd_mtd); | 423 | map_destroy(amd_mtd); |
424 | } | 424 | } |
425 | if (nettel_mmcrp) { | 425 | if (nettel_mmcrp) { |
@@ -432,7 +432,7 @@ static void __exit nettel_cleanup(void) | |||
432 | } | 432 | } |
433 | #ifdef CONFIG_MTD_CFI_INTELEXT | 433 | #ifdef CONFIG_MTD_CFI_INTELEXT |
434 | if (intel_mtd) { | 434 | if (intel_mtd) { |
435 | del_mtd_partitions(intel_mtd); | 435 | mtd_device_unregister(intel_mtd); |
436 | map_destroy(intel_mtd); | 436 | map_destroy(intel_mtd); |
437 | } | 437 | } |
438 | if (nettel_intel_map.virt) { | 438 | if (nettel_intel_map.virt) { |
diff --git a/drivers/mtd/maps/octagon-5066.c b/drivers/mtd/maps/octagon-5066.c index 23fe1786770f..807ac2a2e686 100644 --- a/drivers/mtd/maps/octagon-5066.c +++ b/drivers/mtd/maps/octagon-5066.c | |||
@@ -175,7 +175,7 @@ void cleanup_oct5066(void) | |||
175 | int i; | 175 | int i; |
176 | for (i=0; i<2; i++) { | 176 | for (i=0; i<2; i++) { |
177 | if (oct5066_mtd[i]) { | 177 | if (oct5066_mtd[i]) { |
178 | del_mtd_device(oct5066_mtd[i]); | 178 | mtd_device_unregister(oct5066_mtd[i]); |
179 | map_destroy(oct5066_mtd[i]); | 179 | map_destroy(oct5066_mtd[i]); |
180 | } | 180 | } |
181 | } | 181 | } |
@@ -220,7 +220,7 @@ static int __init init_oct5066(void) | |||
220 | oct5066_mtd[i] = do_map_probe("map_rom", &oct5066_map[i]); | 220 | oct5066_mtd[i] = do_map_probe("map_rom", &oct5066_map[i]); |
221 | if (oct5066_mtd[i]) { | 221 | if (oct5066_mtd[i]) { |
222 | oct5066_mtd[i]->owner = THIS_MODULE; | 222 | oct5066_mtd[i]->owner = THIS_MODULE; |
223 | add_mtd_device(oct5066_mtd[i]); | 223 | mtd_device_register(oct5066_mtd[i], NULL, 0); |
224 | } | 224 | } |
225 | } | 225 | } |
226 | 226 | ||
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index 48f4cf5cb9d1..1d005a3e9b41 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c | |||
@@ -313,7 +313,7 @@ mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
313 | goto release; | 313 | goto release; |
314 | 314 | ||
315 | mtd->owner = THIS_MODULE; | 315 | mtd->owner = THIS_MODULE; |
316 | add_mtd_device(mtd); | 316 | mtd_device_register(mtd, NULL, 0); |
317 | 317 | ||
318 | pci_set_drvdata(dev, mtd); | 318 | pci_set_drvdata(dev, mtd); |
319 | 319 | ||
@@ -336,7 +336,7 @@ mtd_pci_remove(struct pci_dev *dev) | |||
336 | struct mtd_info *mtd = pci_get_drvdata(dev); | 336 | struct mtd_info *mtd = pci_get_drvdata(dev); |
337 | struct map_pci_info *map = mtd->priv; | 337 | struct map_pci_info *map = mtd->priv; |
338 | 338 | ||
339 | del_mtd_device(mtd); | 339 | mtd_device_unregister(mtd); |
340 | map_destroy(mtd); | 340 | map_destroy(mtd); |
341 | map->exit(dev, map); | 341 | map->exit(dev, map); |
342 | kfree(map); | 342 | kfree(map); |
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 33dc2829b01b..bbe168b65c26 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c | |||
@@ -630,7 +630,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
630 | dev->pcmcia_map.copy_to = pcmcia_copy_to; | 630 | dev->pcmcia_map.copy_to = pcmcia_copy_to; |
631 | } | 631 | } |
632 | 632 | ||
633 | if(add_mtd_device(mtd)) { | 633 | if (mtd_device_register(mtd, NULL, 0)) { |
634 | map_destroy(mtd); | 634 | map_destroy(mtd); |
635 | dev->mtd_info = NULL; | 635 | dev->mtd_info = NULL; |
636 | dev_err(&dev->p_dev->dev, | 636 | dev_err(&dev->p_dev->dev, |
@@ -669,7 +669,7 @@ static void pcmciamtd_detach(struct pcmcia_device *link) | |||
669 | DEBUG(3, "link=0x%p", link); | 669 | DEBUG(3, "link=0x%p", link); |
670 | 670 | ||
671 | if(dev->mtd_info) { | 671 | if(dev->mtd_info) { |
672 | del_mtd_device(dev->mtd_info); | 672 | mtd_device_unregister(dev->mtd_info); |
673 | dev_info(&dev->p_dev->dev, "mtd%d: Removing\n", | 673 | dev_info(&dev->p_dev->dev, "mtd%d: Removing\n", |
674 | dev->mtd_info->index); | 674 | dev->mtd_info->index); |
675 | map_destroy(dev->mtd_info); | 675 | map_destroy(dev->mtd_info); |
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 1a9b94f0ee54..f64cee4a3bfb 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c | |||
@@ -27,10 +27,8 @@ struct physmap_flash_info { | |||
27 | struct mtd_info *mtd[MAX_RESOURCES]; | 27 | struct mtd_info *mtd[MAX_RESOURCES]; |
28 | struct mtd_info *cmtd; | 28 | struct mtd_info *cmtd; |
29 | struct map_info map[MAX_RESOURCES]; | 29 | struct map_info map[MAX_RESOURCES]; |
30 | #ifdef CONFIG_MTD_PARTITIONS | ||
31 | int nr_parts; | 30 | int nr_parts; |
32 | struct mtd_partition *parts; | 31 | struct mtd_partition *parts; |
33 | #endif | ||
34 | }; | 32 | }; |
35 | 33 | ||
36 | static int physmap_flash_remove(struct platform_device *dev) | 34 | static int physmap_flash_remove(struct platform_device *dev) |
@@ -47,18 +45,9 @@ static int physmap_flash_remove(struct platform_device *dev) | |||
47 | physmap_data = dev->dev.platform_data; | 45 | physmap_data = dev->dev.platform_data; |
48 | 46 | ||
49 | if (info->cmtd) { | 47 | if (info->cmtd) { |
50 | #ifdef CONFIG_MTD_PARTITIONS | 48 | mtd_device_unregister(info->cmtd); |
51 | if (info->nr_parts || physmap_data->nr_parts) { | 49 | if (info->nr_parts) |
52 | del_mtd_partitions(info->cmtd); | 50 | kfree(info->parts); |
53 | |||
54 | if (info->nr_parts) | ||
55 | kfree(info->parts); | ||
56 | } else { | ||
57 | del_mtd_device(info->cmtd); | ||
58 | } | ||
59 | #else | ||
60 | del_mtd_device(info->cmtd); | ||
61 | #endif | ||
62 | if (info->cmtd != info->mtd[0]) | 51 | if (info->cmtd != info->mtd[0]) |
63 | mtd_concat_destroy(info->cmtd); | 52 | mtd_concat_destroy(info->cmtd); |
64 | } | 53 | } |
@@ -92,10 +81,8 @@ static const char *rom_probe_types[] = { | |||
92 | "qinfo_probe", | 81 | "qinfo_probe", |
93 | "map_rom", | 82 | "map_rom", |
94 | NULL }; | 83 | NULL }; |
95 | #ifdef CONFIG_MTD_PARTITIONS | ||
96 | static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", "afs", | 84 | static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", "afs", |
97 | NULL }; | 85 | NULL }; |
98 | #endif | ||
99 | 86 | ||
100 | static int physmap_flash_probe(struct platform_device *dev) | 87 | static int physmap_flash_probe(struct platform_device *dev) |
101 | { | 88 | { |
@@ -188,24 +175,23 @@ static int physmap_flash_probe(struct platform_device *dev) | |||
188 | if (err) | 175 | if (err) |
189 | goto err_out; | 176 | goto err_out; |
190 | 177 | ||
191 | #ifdef CONFIG_MTD_PARTITIONS | ||
192 | err = parse_mtd_partitions(info->cmtd, part_probe_types, | 178 | err = parse_mtd_partitions(info->cmtd, part_probe_types, |
193 | &info->parts, 0); | 179 | &info->parts, 0); |
194 | if (err > 0) { | 180 | if (err > 0) { |
195 | add_mtd_partitions(info->cmtd, info->parts, err); | 181 | mtd_device_register(info->cmtd, info->parts, err); |
196 | info->nr_parts = err; | 182 | info->nr_parts = err; |
197 | return 0; | 183 | return 0; |
198 | } | 184 | } |
199 | 185 | ||
200 | if (physmap_data->nr_parts) { | 186 | if (physmap_data->nr_parts) { |
201 | printk(KERN_NOTICE "Using physmap partition information\n"); | 187 | printk(KERN_NOTICE "Using physmap partition information\n"); |
202 | add_mtd_partitions(info->cmtd, physmap_data->parts, | 188 | mtd_device_register(info->cmtd, physmap_data->parts, |
203 | physmap_data->nr_parts); | 189 | physmap_data->nr_parts); |
204 | return 0; | 190 | return 0; |
205 | } | 191 | } |
206 | #endif | ||
207 | 192 | ||
208 | add_mtd_device(info->cmtd); | 193 | mtd_device_register(info->cmtd, NULL, 0); |
194 | |||
209 | return 0; | 195 | return 0; |
210 | 196 | ||
211 | err_out: | 197 | err_out: |
@@ -269,14 +255,12 @@ void physmap_configure(unsigned long addr, unsigned long size, | |||
269 | physmap_flash_data.set_vpp = set_vpp; | 255 | physmap_flash_data.set_vpp = set_vpp; |
270 | } | 256 | } |
271 | 257 | ||
272 | #ifdef CONFIG_MTD_PARTITIONS | ||
273 | void physmap_set_partitions(struct mtd_partition *parts, int num_parts) | 258 | void physmap_set_partitions(struct mtd_partition *parts, int num_parts) |
274 | { | 259 | { |
275 | physmap_flash_data.nr_parts = num_parts; | 260 | physmap_flash_data.nr_parts = num_parts; |
276 | physmap_flash_data.parts = parts; | 261 | physmap_flash_data.parts = parts; |
277 | } | 262 | } |
278 | #endif | 263 | #endif |
279 | #endif | ||
280 | 264 | ||
281 | static int __init physmap_init(void) | 265 | static int __init physmap_init(void) |
282 | { | 266 | { |
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index c1d33464aee8..d251d1db129b 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -34,16 +34,12 @@ struct of_flash_list { | |||
34 | 34 | ||
35 | struct of_flash { | 35 | struct of_flash { |
36 | struct mtd_info *cmtd; | 36 | struct mtd_info *cmtd; |
37 | #ifdef CONFIG_MTD_PARTITIONS | ||
38 | struct mtd_partition *parts; | 37 | struct mtd_partition *parts; |
39 | #endif | ||
40 | int list_size; /* number of elements in of_flash_list */ | 38 | int list_size; /* number of elements in of_flash_list */ |
41 | struct of_flash_list list[0]; | 39 | struct of_flash_list list[0]; |
42 | }; | 40 | }; |
43 | 41 | ||
44 | #ifdef CONFIG_MTD_PARTITIONS | ||
45 | #define OF_FLASH_PARTS(info) ((info)->parts) | 42 | #define OF_FLASH_PARTS(info) ((info)->parts) |
46 | |||
47 | static int parse_obsolete_partitions(struct platform_device *dev, | 43 | static int parse_obsolete_partitions(struct platform_device *dev, |
48 | struct of_flash *info, | 44 | struct of_flash *info, |
49 | struct device_node *dp) | 45 | struct device_node *dp) |
@@ -89,10 +85,6 @@ static int parse_obsolete_partitions(struct platform_device *dev, | |||
89 | 85 | ||
90 | return nr_parts; | 86 | return nr_parts; |
91 | } | 87 | } |
92 | #else /* MTD_PARTITIONS */ | ||
93 | #define OF_FLASH_PARTS(info) (0) | ||
94 | #define parse_partitions(info, dev) (0) | ||
95 | #endif /* MTD_PARTITIONS */ | ||
96 | 88 | ||
97 | static int of_flash_remove(struct platform_device *dev) | 89 | static int of_flash_remove(struct platform_device *dev) |
98 | { | 90 | { |
@@ -105,17 +97,14 @@ static int of_flash_remove(struct platform_device *dev) | |||
105 | dev_set_drvdata(&dev->dev, NULL); | 97 | dev_set_drvdata(&dev->dev, NULL); |
106 | 98 | ||
107 | if (info->cmtd != info->list[0].mtd) { | 99 | if (info->cmtd != info->list[0].mtd) { |
108 | del_mtd_device(info->cmtd); | 100 | mtd_device_unregister(info->cmtd); |
109 | mtd_concat_destroy(info->cmtd); | 101 | mtd_concat_destroy(info->cmtd); |
110 | } | 102 | } |
111 | 103 | ||
112 | if (info->cmtd) { | 104 | if (info->cmtd) { |
113 | if (OF_FLASH_PARTS(info)) { | 105 | if (OF_FLASH_PARTS(info)) |
114 | del_mtd_partitions(info->cmtd); | ||
115 | kfree(OF_FLASH_PARTS(info)); | 106 | kfree(OF_FLASH_PARTS(info)); |
116 | } else { | 107 | mtd_device_unregister(info->cmtd); |
117 | del_mtd_device(info->cmtd); | ||
118 | } | ||
119 | } | 108 | } |
120 | 109 | ||
121 | for (i = 0; i < info->list_size; i++) { | 110 | for (i = 0; i < info->list_size; i++) { |
@@ -172,7 +161,6 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev, | |||
172 | } | 161 | } |
173 | } | 162 | } |
174 | 163 | ||
175 | #ifdef CONFIG_MTD_PARTITIONS | ||
176 | /* When partitions are set we look for a linux,part-probe property which | 164 | /* When partitions are set we look for a linux,part-probe property which |
177 | specifies the list of partition probers to use. If none is given then the | 165 | specifies the list of partition probers to use. If none is given then the |
178 | default is use. These take precedence over other device tree | 166 | default is use. These take precedence over other device tree |
@@ -212,14 +200,11 @@ static void __devinit of_free_probes(const char **probes) | |||
212 | if (probes != part_probe_types_def) | 200 | if (probes != part_probe_types_def) |
213 | kfree(probes); | 201 | kfree(probes); |
214 | } | 202 | } |
215 | #endif | ||
216 | 203 | ||
217 | static struct of_device_id of_flash_match[]; | 204 | static struct of_device_id of_flash_match[]; |
218 | static int __devinit of_flash_probe(struct platform_device *dev) | 205 | static int __devinit of_flash_probe(struct platform_device *dev) |
219 | { | 206 | { |
220 | #ifdef CONFIG_MTD_PARTITIONS | ||
221 | const char **part_probe_types; | 207 | const char **part_probe_types; |
222 | #endif | ||
223 | const struct of_device_id *match; | 208 | const struct of_device_id *match; |
224 | struct device_node *dp = dev->dev.of_node; | 209 | struct device_node *dp = dev->dev.of_node; |
225 | struct resource res; | 210 | struct resource res; |
@@ -346,7 +331,6 @@ static int __devinit of_flash_probe(struct platform_device *dev) | |||
346 | if (err) | 331 | if (err) |
347 | goto err_out; | 332 | goto err_out; |
348 | 333 | ||
349 | #ifdef CONFIG_MTD_PARTITIONS | ||
350 | part_probe_types = of_get_probes(dp); | 334 | part_probe_types = of_get_probes(dp); |
351 | err = parse_mtd_partitions(info->cmtd, part_probe_types, | 335 | err = parse_mtd_partitions(info->cmtd, part_probe_types, |
352 | &info->parts, 0); | 336 | &info->parts, 0); |
@@ -356,13 +340,11 @@ static int __devinit of_flash_probe(struct platform_device *dev) | |||
356 | } | 340 | } |
357 | of_free_probes(part_probe_types); | 341 | of_free_probes(part_probe_types); |
358 | 342 | ||
359 | #ifdef CONFIG_MTD_OF_PARTS | ||
360 | if (err == 0) { | 343 | if (err == 0) { |
361 | err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts); | 344 | err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts); |
362 | if (err < 0) | 345 | if (err < 0) |
363 | goto err_out; | 346 | goto err_out; |
364 | } | 347 | } |
365 | #endif | ||
366 | 348 | ||
367 | if (err == 0) { | 349 | if (err == 0) { |
368 | err = parse_obsolete_partitions(dev, info, dp); | 350 | err = parse_obsolete_partitions(dev, info, dp); |
@@ -370,11 +352,7 @@ static int __devinit of_flash_probe(struct platform_device *dev) | |||
370 | goto err_out; | 352 | goto err_out; |
371 | } | 353 | } |
372 | 354 | ||
373 | if (err > 0) | 355 | mtd_device_register(info->cmtd, info->parts, err); |
374 | add_mtd_partitions(info->cmtd, info->parts, err); | ||
375 | else | ||
376 | #endif | ||
377 | add_mtd_device(info->cmtd); | ||
378 | 356 | ||
379 | kfree(mtd_list); | 357 | kfree(mtd_list); |
380 | 358 | ||
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 76a76be5a7bd..9ca1eccba4bc 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c | |||
@@ -94,14 +94,11 @@ static int platram_remove(struct platform_device *pdev) | |||
94 | return 0; | 94 | return 0; |
95 | 95 | ||
96 | if (info->mtd) { | 96 | if (info->mtd) { |
97 | #ifdef CONFIG_MTD_PARTITIONS | 97 | mtd_device_unregister(info->mtd); |
98 | if (info->partitions) { | 98 | if (info->partitions) { |
99 | del_mtd_partitions(info->mtd); | ||
100 | if (info->free_partitions) | 99 | if (info->free_partitions) |
101 | kfree(info->partitions); | 100 | kfree(info->partitions); |
102 | } | 101 | } |
103 | #endif | ||
104 | del_mtd_device(info->mtd); | ||
105 | map_destroy(info->mtd); | 102 | map_destroy(info->mtd); |
106 | } | 103 | } |
107 | 104 | ||
@@ -231,7 +228,6 @@ static int platram_probe(struct platform_device *pdev) | |||
231 | /* check to see if there are any available partitions, or wether | 228 | /* check to see if there are any available partitions, or wether |
232 | * to add this device whole */ | 229 | * to add this device whole */ |
233 | 230 | ||
234 | #ifdef CONFIG_MTD_PARTITIONS | ||
235 | if (!pdata->nr_partitions) { | 231 | if (!pdata->nr_partitions) { |
236 | /* try to probe using the supplied probe type */ | 232 | /* try to probe using the supplied probe type */ |
237 | if (pdata->probes) { | 233 | if (pdata->probes) { |
@@ -239,24 +235,22 @@ static int platram_probe(struct platform_device *pdev) | |||
239 | &info->partitions, 0); | 235 | &info->partitions, 0); |
240 | info->free_partitions = 1; | 236 | info->free_partitions = 1; |
241 | if (err > 0) | 237 | if (err > 0) |
242 | err = add_mtd_partitions(info->mtd, | 238 | err = mtd_device_register(info->mtd, |
243 | info->partitions, err); | 239 | info->partitions, err); |
244 | } | 240 | } |
245 | } | 241 | } |
246 | /* use the static mapping */ | 242 | /* use the static mapping */ |
247 | else | 243 | else |
248 | err = add_mtd_partitions(info->mtd, pdata->partitions, | 244 | err = mtd_device_register(info->mtd, pdata->partitions, |
249 | pdata->nr_partitions); | 245 | pdata->nr_partitions); |
250 | #endif /* CONFIG_MTD_PARTITIONS */ | ||
251 | |||
252 | if (add_mtd_device(info->mtd)) { | ||
253 | dev_err(&pdev->dev, "add_mtd_device() failed\n"); | ||
254 | err = -ENOMEM; | ||
255 | } | ||
256 | |||
257 | if (!err) | 246 | if (!err) |
258 | dev_info(&pdev->dev, "registered mtd device\n"); | 247 | dev_info(&pdev->dev, "registered mtd device\n"); |
259 | 248 | ||
249 | /* add the whole device. */ | ||
250 | err = mtd_device_register(info->mtd, NULL, 0); | ||
251 | if (err) | ||
252 | dev_err(&pdev->dev, "failed to register the entire device\n"); | ||
253 | |||
260 | return err; | 254 | return err; |
261 | 255 | ||
262 | exit_free: | 256 | exit_free: |
diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c index 64aea6acd48e..744ca5cacc9b 100644 --- a/drivers/mtd/maps/pmcmsp-flash.c +++ b/drivers/mtd/maps/pmcmsp-flash.c | |||
@@ -173,7 +173,7 @@ static int __init init_msp_flash(void) | |||
173 | msp_flash[i] = do_map_probe("cfi_probe", &msp_maps[i]); | 173 | msp_flash[i] = do_map_probe("cfi_probe", &msp_maps[i]); |
174 | if (msp_flash[i]) { | 174 | if (msp_flash[i]) { |
175 | msp_flash[i]->owner = THIS_MODULE; | 175 | msp_flash[i]->owner = THIS_MODULE; |
176 | add_mtd_partitions(msp_flash[i], msp_parts[i], pcnt); | 176 | mtd_device_register(msp_flash[i], msp_parts[i], pcnt); |
177 | } else { | 177 | } else { |
178 | printk(KERN_ERR "map probe failed for flash\n"); | 178 | printk(KERN_ERR "map probe failed for flash\n"); |
179 | ret = -ENXIO; | 179 | ret = -ENXIO; |
@@ -188,7 +188,7 @@ static int __init init_msp_flash(void) | |||
188 | 188 | ||
189 | cleanup_loop: | 189 | cleanup_loop: |
190 | while (i--) { | 190 | while (i--) { |
191 | del_mtd_partitions(msp_flash[i]); | 191 | mtd_device_unregister(msp_flash[i]); |
192 | map_destroy(msp_flash[i]); | 192 | map_destroy(msp_flash[i]); |
193 | kfree(msp_maps[i].name); | 193 | kfree(msp_maps[i].name); |
194 | iounmap(msp_maps[i].virt); | 194 | iounmap(msp_maps[i].virt); |
@@ -207,7 +207,7 @@ static void __exit cleanup_msp_flash(void) | |||
207 | int i; | 207 | int i; |
208 | 208 | ||
209 | for (i = 0; i < fcnt; i++) { | 209 | for (i = 0; i < fcnt; i++) { |
210 | del_mtd_partitions(msp_flash[i]); | 210 | mtd_device_unregister(msp_flash[i]); |
211 | map_destroy(msp_flash[i]); | 211 | map_destroy(msp_flash[i]); |
212 | iounmap((void *)msp_maps[i].virt); | 212 | iounmap((void *)msp_maps[i].virt); |
213 | 213 | ||
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index d8ae634d347e..f59d62f74d44 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c | |||
@@ -104,23 +104,18 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev) | |||
104 | } | 104 | } |
105 | info->mtd->owner = THIS_MODULE; | 105 | info->mtd->owner = THIS_MODULE; |
106 | 106 | ||
107 | #ifdef CONFIG_MTD_PARTITIONS | ||
108 | ret = parse_mtd_partitions(info->mtd, probes, &parts, 0); | 107 | ret = parse_mtd_partitions(info->mtd, probes, &parts, 0); |
109 | 108 | ||
110 | if (ret > 0) { | 109 | if (ret > 0) { |
111 | info->nr_parts = ret; | 110 | info->nr_parts = ret; |
112 | info->parts = parts; | 111 | info->parts = parts; |
113 | } | 112 | } |
114 | #endif | ||
115 | 113 | ||
116 | if (info->nr_parts) { | 114 | if (!info->nr_parts) |
117 | add_mtd_partitions(info->mtd, info->parts, | ||
118 | info->nr_parts); | ||
119 | } else { | ||
120 | printk("Registering %s as whole device\n", | 115 | printk("Registering %s as whole device\n", |
121 | info->map.name); | 116 | info->map.name); |
122 | add_mtd_device(info->mtd); | 117 | |
123 | } | 118 | mtd_device_register(info->mtd, info->parts, info->nr_parts); |
124 | 119 | ||
125 | platform_set_drvdata(pdev, info); | 120 | platform_set_drvdata(pdev, info); |
126 | return 0; | 121 | return 0; |
@@ -132,12 +127,7 @@ static int __devexit pxa2xx_flash_remove(struct platform_device *dev) | |||
132 | 127 | ||
133 | platform_set_drvdata(dev, NULL); | 128 | platform_set_drvdata(dev, NULL); |
134 | 129 | ||
135 | #ifdef CONFIG_MTD_PARTITIONS | 130 | mtd_device_unregister(info->mtd); |
136 | if (info->nr_parts) | ||
137 | del_mtd_partitions(info->mtd); | ||
138 | else | ||
139 | #endif | ||
140 | del_mtd_device(info->mtd); | ||
141 | 131 | ||
142 | map_destroy(info->mtd); | 132 | map_destroy(info->mtd); |
143 | iounmap(info->map.virt); | 133 | iounmap(info->map.virt); |
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c index 83ed64512c5e..761fb459d2c7 100644 --- a/drivers/mtd/maps/rbtx4939-flash.c +++ b/drivers/mtd/maps/rbtx4939-flash.c | |||
@@ -25,10 +25,8 @@ | |||
25 | struct rbtx4939_flash_info { | 25 | struct rbtx4939_flash_info { |
26 | struct mtd_info *mtd; | 26 | struct mtd_info *mtd; |
27 | struct map_info map; | 27 | struct map_info map; |
28 | #ifdef CONFIG_MTD_PARTITIONS | ||
29 | int nr_parts; | 28 | int nr_parts; |
30 | struct mtd_partition *parts; | 29 | struct mtd_partition *parts; |
31 | #endif | ||
32 | }; | 30 | }; |
33 | 31 | ||
34 | static int rbtx4939_flash_remove(struct platform_device *dev) | 32 | static int rbtx4939_flash_remove(struct platform_device *dev) |
@@ -41,28 +39,18 @@ static int rbtx4939_flash_remove(struct platform_device *dev) | |||
41 | platform_set_drvdata(dev, NULL); | 39 | platform_set_drvdata(dev, NULL); |
42 | 40 | ||
43 | if (info->mtd) { | 41 | if (info->mtd) { |
44 | #ifdef CONFIG_MTD_PARTITIONS | ||
45 | struct rbtx4939_flash_data *pdata = dev->dev.platform_data; | 42 | struct rbtx4939_flash_data *pdata = dev->dev.platform_data; |
46 | 43 | ||
47 | if (info->nr_parts) { | 44 | if (info->nr_parts) |
48 | del_mtd_partitions(info->mtd); | ||
49 | kfree(info->parts); | 45 | kfree(info->parts); |
50 | } else if (pdata->nr_parts) | 46 | mtd_device_unregister(info->mtd); |
51 | del_mtd_partitions(info->mtd); | ||
52 | else | ||
53 | del_mtd_device(info->mtd); | ||
54 | #else | ||
55 | del_mtd_device(info->mtd); | ||
56 | #endif | ||
57 | map_destroy(info->mtd); | 47 | map_destroy(info->mtd); |
58 | } | 48 | } |
59 | return 0; | 49 | return 0; |
60 | } | 50 | } |
61 | 51 | ||
62 | static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; | 52 | static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; |
63 | #ifdef CONFIG_MTD_PARTITIONS | ||
64 | static const char *part_probe_types[] = { "cmdlinepart", NULL }; | 53 | static const char *part_probe_types[] = { "cmdlinepart", NULL }; |
65 | #endif | ||
66 | 54 | ||
67 | static int rbtx4939_flash_probe(struct platform_device *dev) | 55 | static int rbtx4939_flash_probe(struct platform_device *dev) |
68 | { | 56 | { |
@@ -120,23 +108,21 @@ static int rbtx4939_flash_probe(struct platform_device *dev) | |||
120 | if (err) | 108 | if (err) |
121 | goto err_out; | 109 | goto err_out; |
122 | 110 | ||
123 | #ifdef CONFIG_MTD_PARTITIONS | ||
124 | err = parse_mtd_partitions(info->mtd, part_probe_types, | 111 | err = parse_mtd_partitions(info->mtd, part_probe_types, |
125 | &info->parts, 0); | 112 | &info->parts, 0); |
126 | if (err > 0) { | 113 | if (err > 0) { |
127 | add_mtd_partitions(info->mtd, info->parts, err); | 114 | mtd_device_register(info->mtd, info->parts, err); |
128 | info->nr_parts = err; | 115 | info->nr_parts = err; |
129 | return 0; | 116 | return 0; |
130 | } | 117 | } |
131 | 118 | ||
132 | if (pdata->nr_parts) { | 119 | if (pdata->nr_parts) { |
133 | pr_notice("Using rbtx4939 partition information\n"); | 120 | pr_notice("Using rbtx4939 partition information\n"); |
134 | add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts); | 121 | mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts); |
135 | return 0; | 122 | return 0; |
136 | } | 123 | } |
137 | #endif | ||
138 | 124 | ||
139 | add_mtd_device(info->mtd); | 125 | mtd_device_register(info->mtd, NULL, 0); |
140 | return 0; | 126 | return 0; |
141 | 127 | ||
142 | err_out: | 128 | err_out: |
diff --git a/drivers/mtd/maps/rpxlite.c b/drivers/mtd/maps/rpxlite.c index 3e3ef53d4fd4..ed88225bf667 100644 --- a/drivers/mtd/maps/rpxlite.c +++ b/drivers/mtd/maps/rpxlite.c | |||
@@ -36,7 +36,7 @@ static int __init init_rpxlite(void) | |||
36 | mymtd = do_map_probe("cfi_probe", &rpxlite_map); | 36 | mymtd = do_map_probe("cfi_probe", &rpxlite_map); |
37 | if (mymtd) { | 37 | if (mymtd) { |
38 | mymtd->owner = THIS_MODULE; | 38 | mymtd->owner = THIS_MODULE; |
39 | add_mtd_device(mymtd); | 39 | mtd_device_register(mymtd, NULL, 0); |
40 | return 0; | 40 | return 0; |
41 | } | 41 | } |
42 | 42 | ||
@@ -47,7 +47,7 @@ static int __init init_rpxlite(void) | |||
47 | static void __exit cleanup_rpxlite(void) | 47 | static void __exit cleanup_rpxlite(void) |
48 | { | 48 | { |
49 | if (mymtd) { | 49 | if (mymtd) { |
50 | del_mtd_device(mymtd); | 50 | mtd_device_unregister(mymtd); |
51 | map_destroy(mymtd); | 51 | map_destroy(mymtd); |
52 | } | 52 | } |
53 | if (rpxlite_map.virt) { | 53 | if (rpxlite_map.virt) { |
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index da875908ea8e..a9b5e0e5c4c5 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c | |||
@@ -226,12 +226,7 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla | |||
226 | int i; | 226 | int i; |
227 | 227 | ||
228 | if (info->mtd) { | 228 | if (info->mtd) { |
229 | if (info->nr_parts == 0) | 229 | mtd_device_unregister(info->mtd); |
230 | del_mtd_device(info->mtd); | ||
231 | #ifdef CONFIG_MTD_PARTITIONS | ||
232 | else | ||
233 | del_mtd_partitions(info->mtd); | ||
234 | #endif | ||
235 | if (info->mtd != info->subdev[0].mtd) | 230 | if (info->mtd != info->subdev[0].mtd) |
236 | mtd_concat_destroy(info->mtd); | 231 | mtd_concat_destroy(info->mtd); |
237 | } | 232 | } |
@@ -363,28 +358,24 @@ static int __devinit sa1100_mtd_probe(struct platform_device *pdev) | |||
363 | /* | 358 | /* |
364 | * Partition selection stuff. | 359 | * Partition selection stuff. |
365 | */ | 360 | */ |
366 | #ifdef CONFIG_MTD_PARTITIONS | ||
367 | nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0); | 361 | nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0); |
368 | if (nr_parts > 0) { | 362 | if (nr_parts > 0) { |
369 | info->parts = parts; | 363 | info->parts = parts; |
370 | part_type = "dynamic"; | 364 | part_type = "dynamic"; |
371 | } else | 365 | } else { |
372 | #endif | ||
373 | { | ||
374 | parts = plat->parts; | 366 | parts = plat->parts; |
375 | nr_parts = plat->nr_parts; | 367 | nr_parts = plat->nr_parts; |
376 | part_type = "static"; | 368 | part_type = "static"; |
377 | } | 369 | } |
378 | 370 | ||
379 | if (nr_parts == 0) { | 371 | if (nr_parts == 0) |
380 | printk(KERN_NOTICE "SA1100 flash: no partition info " | 372 | printk(KERN_NOTICE "SA1100 flash: no partition info " |
381 | "available, registering whole flash\n"); | 373 | "available, registering whole flash\n"); |
382 | add_mtd_device(info->mtd); | 374 | else |
383 | } else { | ||
384 | printk(KERN_NOTICE "SA1100 flash: using %s partition " | 375 | printk(KERN_NOTICE "SA1100 flash: using %s partition " |
385 | "definition\n", part_type); | 376 | "definition\n", part_type); |
386 | add_mtd_partitions(info->mtd, parts, nr_parts); | 377 | |
387 | } | 378 | mtd_device_register(info->mtd, parts, nr_parts); |
388 | 379 | ||
389 | info->nr_parts = nr_parts; | 380 | info->nr_parts = nr_parts; |
390 | 381 | ||
diff --git a/drivers/mtd/maps/sbc_gxx.c b/drivers/mtd/maps/sbc_gxx.c index 04b2781fc627..556a2dfe94c5 100644 --- a/drivers/mtd/maps/sbc_gxx.c +++ b/drivers/mtd/maps/sbc_gxx.c | |||
@@ -182,7 +182,7 @@ static struct mtd_info *all_mtd; | |||
182 | static void cleanup_sbc_gxx(void) | 182 | static void cleanup_sbc_gxx(void) |
183 | { | 183 | { |
184 | if( all_mtd ) { | 184 | if( all_mtd ) { |
185 | del_mtd_partitions( all_mtd ); | 185 | mtd_device_unregister(all_mtd); |
186 | map_destroy( all_mtd ); | 186 | map_destroy( all_mtd ); |
187 | } | 187 | } |
188 | 188 | ||
@@ -223,7 +223,7 @@ static int __init init_sbc_gxx(void) | |||
223 | all_mtd->owner = THIS_MODULE; | 223 | all_mtd->owner = THIS_MODULE; |
224 | 224 | ||
225 | /* Create MTD devices for each partition. */ | 225 | /* Create MTD devices for each partition. */ |
226 | add_mtd_partitions(all_mtd, partition_info, NUM_PARTITIONS ); | 226 | mtd_device_register(all_mtd, partition_info, NUM_PARTITIONS); |
227 | 227 | ||
228 | return 0; | 228 | return 0; |
229 | } | 229 | } |
diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c index 4d8aaaf4bb76..8fead8e46bce 100644 --- a/drivers/mtd/maps/sc520cdp.c +++ b/drivers/mtd/maps/sc520cdp.c | |||
@@ -266,10 +266,10 @@ static int __init init_sc520cdp(void) | |||
266 | /* Combine the two flash banks into a single MTD device & register it: */ | 266 | /* Combine the two flash banks into a single MTD device & register it: */ |
267 | merged_mtd = mtd_concat_create(mymtd, 2, "SC520CDP Flash Banks #0 and #1"); | 267 | merged_mtd = mtd_concat_create(mymtd, 2, "SC520CDP Flash Banks #0 and #1"); |
268 | if(merged_mtd) | 268 | if(merged_mtd) |
269 | add_mtd_device(merged_mtd); | 269 | mtd_device_register(merged_mtd, NULL, 0); |
270 | } | 270 | } |
271 | if(devices_found == 3) /* register the third (DIL-Flash) device */ | 271 | if(devices_found == 3) /* register the third (DIL-Flash) device */ |
272 | add_mtd_device(mymtd[2]); | 272 | mtd_device_register(mymtd[2], NULL, 0); |
273 | return(devices_found ? 0 : -ENXIO); | 273 | return(devices_found ? 0 : -ENXIO); |
274 | } | 274 | } |
275 | 275 | ||
@@ -278,11 +278,11 @@ static void __exit cleanup_sc520cdp(void) | |||
278 | int i; | 278 | int i; |
279 | 279 | ||
280 | if (merged_mtd) { | 280 | if (merged_mtd) { |
281 | del_mtd_device(merged_mtd); | 281 | mtd_device_unregister(merged_mtd); |
282 | mtd_concat_destroy(merged_mtd); | 282 | mtd_concat_destroy(merged_mtd); |
283 | } | 283 | } |
284 | if (mymtd[2]) | 284 | if (mymtd[2]) |
285 | del_mtd_device(mymtd[2]); | 285 | mtd_device_unregister(mymtd[2]); |
286 | 286 | ||
287 | for (i = 0; i < NUM_FLASH_BANKS; i++) { | 287 | for (i = 0; i < NUM_FLASH_BANKS; i++) { |
288 | if (mymtd[i]) | 288 | if (mymtd[i]) |
diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c index 7e329f09a548..d88c8426bb0f 100644 --- a/drivers/mtd/maps/scb2_flash.c +++ b/drivers/mtd/maps/scb2_flash.c | |||
@@ -180,7 +180,7 @@ scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent) | |||
180 | 180 | ||
181 | scb2_mtd->owner = THIS_MODULE; | 181 | scb2_mtd->owner = THIS_MODULE; |
182 | if (scb2_fixup_mtd(scb2_mtd) < 0) { | 182 | if (scb2_fixup_mtd(scb2_mtd) < 0) { |
183 | del_mtd_device(scb2_mtd); | 183 | mtd_device_unregister(scb2_mtd); |
184 | map_destroy(scb2_mtd); | 184 | map_destroy(scb2_mtd); |
185 | iounmap(scb2_ioaddr); | 185 | iounmap(scb2_ioaddr); |
186 | if (!region_fail) | 186 | if (!region_fail) |
@@ -192,7 +192,7 @@ scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent) | |||
192 | (unsigned long long)scb2_mtd->size, | 192 | (unsigned long long)scb2_mtd->size, |
193 | (unsigned long long)(SCB2_WINDOW - scb2_mtd->size)); | 193 | (unsigned long long)(SCB2_WINDOW - scb2_mtd->size)); |
194 | 194 | ||
195 | add_mtd_device(scb2_mtd); | 195 | mtd_device_register(scb2_mtd, NULL, 0); |
196 | 196 | ||
197 | return 0; | 197 | return 0; |
198 | } | 198 | } |
@@ -207,7 +207,7 @@ scb2_flash_remove(struct pci_dev *dev) | |||
207 | if (scb2_mtd->lock) | 207 | if (scb2_mtd->lock) |
208 | scb2_mtd->lock(scb2_mtd, 0, scb2_mtd->size); | 208 | scb2_mtd->lock(scb2_mtd, 0, scb2_mtd->size); |
209 | 209 | ||
210 | del_mtd_device(scb2_mtd); | 210 | mtd_device_unregister(scb2_mtd); |
211 | map_destroy(scb2_mtd); | 211 | map_destroy(scb2_mtd); |
212 | 212 | ||
213 | iounmap(scb2_ioaddr); | 213 | iounmap(scb2_ioaddr); |
diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c index 027e628a4f1d..f1c1f737d0d7 100644 --- a/drivers/mtd/maps/scx200_docflash.c +++ b/drivers/mtd/maps/scx200_docflash.c | |||
@@ -44,7 +44,6 @@ static struct resource docmem = { | |||
44 | 44 | ||
45 | static struct mtd_info *mymtd; | 45 | static struct mtd_info *mymtd; |
46 | 46 | ||
47 | #ifdef CONFIG_MTD_PARTITIONS | ||
48 | static struct mtd_partition partition_info[] = { | 47 | static struct mtd_partition partition_info[] = { |
49 | { | 48 | { |
50 | .name = "DOCCS Boot kernel", | 49 | .name = "DOCCS Boot kernel", |
@@ -68,8 +67,6 @@ static struct mtd_partition partition_info[] = { | |||
68 | }, | 67 | }, |
69 | }; | 68 | }; |
70 | #define NUM_PARTITIONS ARRAY_SIZE(partition_info) | 69 | #define NUM_PARTITIONS ARRAY_SIZE(partition_info) |
71 | #endif | ||
72 | |||
73 | 70 | ||
74 | static struct map_info scx200_docflash_map = { | 71 | static struct map_info scx200_docflash_map = { |
75 | .name = "NatSemi SCx200 DOCCS Flash", | 72 | .name = "NatSemi SCx200 DOCCS Flash", |
@@ -198,24 +195,17 @@ static int __init init_scx200_docflash(void) | |||
198 | 195 | ||
199 | mymtd->owner = THIS_MODULE; | 196 | mymtd->owner = THIS_MODULE; |
200 | 197 | ||
201 | #ifdef CONFIG_MTD_PARTITIONS | ||
202 | partition_info[3].offset = mymtd->size-partition_info[3].size; | 198 | partition_info[3].offset = mymtd->size-partition_info[3].size; |
203 | partition_info[2].size = partition_info[3].offset-partition_info[2].offset; | 199 | partition_info[2].size = partition_info[3].offset-partition_info[2].offset; |
204 | add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS); | 200 | mtd_device_register(mymtd, partition_info, NUM_PARTITIONS); |
205 | #else | 201 | |
206 | add_mtd_device(mymtd); | ||
207 | #endif | ||
208 | return 0; | 202 | return 0; |
209 | } | 203 | } |
210 | 204 | ||
211 | static void __exit cleanup_scx200_docflash(void) | 205 | static void __exit cleanup_scx200_docflash(void) |
212 | { | 206 | { |
213 | if (mymtd) { | 207 | if (mymtd) { |
214 | #ifdef CONFIG_MTD_PARTITIONS | 208 | mtd_device_unregister(mymtd); |
215 | del_mtd_partitions(mymtd); | ||
216 | #else | ||
217 | del_mtd_device(mymtd); | ||
218 | #endif | ||
219 | map_destroy(mymtd); | 209 | map_destroy(mymtd); |
220 | } | 210 | } |
221 | if (scx200_docflash_map.virt) { | 211 | if (scx200_docflash_map.virt) { |
diff --git a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c index 0eb41d9c6786..cbf6bade9354 100644 --- a/drivers/mtd/maps/solutionengine.c +++ b/drivers/mtd/maps/solutionengine.c | |||
@@ -89,7 +89,7 @@ static int __init init_soleng_maps(void) | |||
89 | eprom_mtd = do_map_probe("map_rom", &soleng_eprom_map); | 89 | eprom_mtd = do_map_probe("map_rom", &soleng_eprom_map); |
90 | if (eprom_mtd) { | 90 | if (eprom_mtd) { |
91 | eprom_mtd->owner = THIS_MODULE; | 91 | eprom_mtd->owner = THIS_MODULE; |
92 | add_mtd_device(eprom_mtd); | 92 | mtd_device_register(eprom_mtd, NULL, 0); |
93 | } | 93 | } |
94 | 94 | ||
95 | nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0); | 95 | nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0); |
@@ -104,9 +104,9 @@ static int __init init_soleng_maps(void) | |||
104 | #endif /* CONFIG_MTD_SUPERH_RESERVE */ | 104 | #endif /* CONFIG_MTD_SUPERH_RESERVE */ |
105 | 105 | ||
106 | if (nr_parts > 0) | 106 | if (nr_parts > 0) |
107 | add_mtd_partitions(flash_mtd, parsed_parts, nr_parts); | 107 | mtd_device_register(flash_mtd, parsed_parts, nr_parts); |
108 | else | 108 | else |
109 | add_mtd_device(flash_mtd); | 109 | mtd_device_register(flash_mtd, NULL, 0); |
110 | 110 | ||
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
@@ -114,14 +114,14 @@ static int __init init_soleng_maps(void) | |||
114 | static void __exit cleanup_soleng_maps(void) | 114 | static void __exit cleanup_soleng_maps(void) |
115 | { | 115 | { |
116 | if (eprom_mtd) { | 116 | if (eprom_mtd) { |
117 | del_mtd_device(eprom_mtd); | 117 | mtd_device_unregister(eprom_mtd); |
118 | map_destroy(eprom_mtd); | 118 | map_destroy(eprom_mtd); |
119 | } | 119 | } |
120 | 120 | ||
121 | if (parsed_parts) | 121 | if (parsed_parts) |
122 | del_mtd_partitions(flash_mtd); | 122 | mtd_device_unregister(flash_mtd); |
123 | else | 123 | else |
124 | del_mtd_device(flash_mtd); | 124 | mtd_device_unregister(flash_mtd); |
125 | map_destroy(flash_mtd); | 125 | map_destroy(flash_mtd); |
126 | } | 126 | } |
127 | 127 | ||
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 3f1cb328a574..2d66234f57cb 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c | |||
@@ -101,7 +101,7 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp) | |||
101 | 101 | ||
102 | up->mtd->owner = THIS_MODULE; | 102 | up->mtd->owner = THIS_MODULE; |
103 | 103 | ||
104 | add_mtd_device(up->mtd); | 104 | mtd_device_register(up->mtd, NULL, 0); |
105 | 105 | ||
106 | dev_set_drvdata(&op->dev, up); | 106 | dev_set_drvdata(&op->dev, up); |
107 | 107 | ||
@@ -126,7 +126,7 @@ static int __devexit uflash_remove(struct platform_device *op) | |||
126 | struct uflash_dev *up = dev_get_drvdata(&op->dev); | 126 | struct uflash_dev *up = dev_get_drvdata(&op->dev); |
127 | 127 | ||
128 | if (up->mtd) { | 128 | if (up->mtd) { |
129 | del_mtd_device(up->mtd); | 129 | mtd_device_unregister(up->mtd); |
130 | map_destroy(up->mtd); | 130 | map_destroy(up->mtd); |
131 | } | 131 | } |
132 | if (up->map.virt) { | 132 | if (up->map.virt) { |
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c index 0718dfb3ee64..d78587990e7e 100644 --- a/drivers/mtd/maps/tqm8xxl.c +++ b/drivers/mtd/maps/tqm8xxl.c | |||
@@ -62,7 +62,6 @@ static void __iomem *start_scan_addr; | |||
62 | * "struct map_desc *_io_desc" for the corresponding machine. | 62 | * "struct map_desc *_io_desc" for the corresponding machine. |
63 | */ | 63 | */ |
64 | 64 | ||
65 | #ifdef CONFIG_MTD_PARTITIONS | ||
66 | /* Currently, TQM8xxL has up to 8MiB flash */ | 65 | /* Currently, TQM8xxL has up to 8MiB flash */ |
67 | static unsigned long tqm8xxl_max_flash_size = 0x00800000; | 66 | static unsigned long tqm8xxl_max_flash_size = 0x00800000; |
68 | 67 | ||
@@ -107,7 +106,6 @@ static struct mtd_partition tqm8xxl_fs_partitions[] = { | |||
107 | //.size = MTDPART_SIZ_FULL, | 106 | //.size = MTDPART_SIZ_FULL, |
108 | } | 107 | } |
109 | }; | 108 | }; |
110 | #endif | ||
111 | 109 | ||
112 | static int __init init_tqm_mtd(void) | 110 | static int __init init_tqm_mtd(void) |
113 | { | 111 | { |
@@ -188,7 +186,6 @@ static int __init init_tqm_mtd(void) | |||
188 | goto error_mem; | 186 | goto error_mem; |
189 | } | 187 | } |
190 | 188 | ||
191 | #ifdef CONFIG_MTD_PARTITIONS | ||
192 | /* | 189 | /* |
193 | * Select Static partition definitions | 190 | * Select Static partition definitions |
194 | */ | 191 | */ |
@@ -201,21 +198,14 @@ static int __init init_tqm_mtd(void) | |||
201 | part_banks[1].nums = ARRAY_SIZE(tqm8xxl_fs_partitions); | 198 | part_banks[1].nums = ARRAY_SIZE(tqm8xxl_fs_partitions); |
202 | 199 | ||
203 | for(idx = 0; idx < num_banks ; idx++) { | 200 | for(idx = 0; idx < num_banks ; idx++) { |
204 | if (part_banks[idx].nums == 0) { | 201 | if (part_banks[idx].nums == 0) |
205 | printk(KERN_NOTICE "TQM flash%d: no partition info available, registering whole flash at once\n", idx); | 202 | printk(KERN_NOTICE "TQM flash%d: no partition info available, registering whole flash at once\n", idx); |
206 | add_mtd_device(mtd_banks[idx]); | 203 | else |
207 | } else { | ||
208 | printk(KERN_NOTICE "TQM flash%d: Using %s partition definition\n", | 204 | printk(KERN_NOTICE "TQM flash%d: Using %s partition definition\n", |
209 | idx, part_banks[idx].type); | 205 | idx, part_banks[idx].type); |
210 | add_mtd_partitions(mtd_banks[idx], part_banks[idx].mtd_part, | 206 | mtd_device_register(mtd_banks[idx], part_banks[idx].mtd_part, |
211 | part_banks[idx].nums); | 207 | part_banks[idx].nums); |
212 | } | ||
213 | } | 208 | } |
214 | #else | ||
215 | printk(KERN_NOTICE "TQM flash: registering %d whole flash banks at once\n", num_banks); | ||
216 | for(idx = 0 ; idx < num_banks ; idx++) | ||
217 | add_mtd_device(mtd_banks[idx]); | ||
218 | #endif | ||
219 | return 0; | 209 | return 0; |
220 | error_mem: | 210 | error_mem: |
221 | for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { | 211 | for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { |
@@ -237,7 +227,7 @@ static void __exit cleanup_tqm_mtd(void) | |||
237 | for(idx = 0 ; idx < num_banks ; idx++) { | 227 | for(idx = 0 ; idx < num_banks ; idx++) { |
238 | /* destroy mtd_info previously allocated */ | 228 | /* destroy mtd_info previously allocated */ |
239 | if (mtd_banks[idx]) { | 229 | if (mtd_banks[idx]) { |
240 | del_mtd_partitions(mtd_banks[idx]); | 230 | mtd_device_unregister(mtd_banks[idx]); |
241 | map_destroy(mtd_banks[idx]); | 231 | map_destroy(mtd_banks[idx]); |
242 | } | 232 | } |
243 | /* release map_info not used anymore */ | 233 | /* release map_info not used anymore */ |
diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c index e02dfa9d4ddd..d1d671daf235 100644 --- a/drivers/mtd/maps/ts5500_flash.c +++ b/drivers/mtd/maps/ts5500_flash.c | |||
@@ -89,7 +89,7 @@ static int __init init_ts5500_map(void) | |||
89 | } | 89 | } |
90 | 90 | ||
91 | mymtd->owner = THIS_MODULE; | 91 | mymtd->owner = THIS_MODULE; |
92 | add_mtd_partitions(mymtd, ts5500_partitions, NUM_PARTITIONS); | 92 | mtd_device_register(mymtd, ts5500_partitions, NUM_PARTITIONS); |
93 | 93 | ||
94 | return 0; | 94 | return 0; |
95 | 95 | ||
@@ -102,7 +102,7 @@ err2: | |||
102 | static void __exit cleanup_ts5500_map(void) | 102 | static void __exit cleanup_ts5500_map(void) |
103 | { | 103 | { |
104 | if (mymtd) { | 104 | if (mymtd) { |
105 | del_mtd_partitions(mymtd); | 105 | mtd_device_unregister(mymtd); |
106 | map_destroy(mymtd); | 106 | map_destroy(mymtd); |
107 | } | 107 | } |
108 | 108 | ||
diff --git a/drivers/mtd/maps/tsunami_flash.c b/drivers/mtd/maps/tsunami_flash.c index 77a8bfc02577..1de390e1c2fb 100644 --- a/drivers/mtd/maps/tsunami_flash.c +++ b/drivers/mtd/maps/tsunami_flash.c | |||
@@ -76,7 +76,7 @@ static void __exit cleanup_tsunami_flash(void) | |||
76 | struct mtd_info *mtd; | 76 | struct mtd_info *mtd; |
77 | mtd = tsunami_flash_mtd; | 77 | mtd = tsunami_flash_mtd; |
78 | if (mtd) { | 78 | if (mtd) { |
79 | del_mtd_device(mtd); | 79 | mtd_device_unregister(mtd); |
80 | map_destroy(mtd); | 80 | map_destroy(mtd); |
81 | } | 81 | } |
82 | tsunami_flash_mtd = 0; | 82 | tsunami_flash_mtd = 0; |
@@ -97,7 +97,7 @@ static int __init init_tsunami_flash(void) | |||
97 | } | 97 | } |
98 | if (tsunami_flash_mtd) { | 98 | if (tsunami_flash_mtd) { |
99 | tsunami_flash_mtd->owner = THIS_MODULE; | 99 | tsunami_flash_mtd->owner = THIS_MODULE; |
100 | add_mtd_device(tsunami_flash_mtd); | 100 | mtd_device_register(tsunami_flash_mtd, NULL, 0); |
101 | return 0; | 101 | return 0; |
102 | } | 102 | } |
103 | return -ENXIO; | 103 | return -ENXIO; |
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index 35009294b435..6793074f3f40 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c | |||
@@ -89,11 +89,7 @@ static int __init uclinux_mtd_init(void) | |||
89 | mtd->priv = mapp; | 89 | mtd->priv = mapp; |
90 | 90 | ||
91 | uclinux_ram_mtdinfo = mtd; | 91 | uclinux_ram_mtdinfo = mtd; |
92 | #ifdef CONFIG_MTD_PARTITIONS | 92 | mtd_device_register(mtd, uclinux_romfs, NUM_PARTITIONS); |
93 | add_mtd_partitions(mtd, uclinux_romfs, NUM_PARTITIONS); | ||
94 | #else | ||
95 | add_mtd_device(mtd); | ||
96 | #endif | ||
97 | 93 | ||
98 | return(0); | 94 | return(0); |
99 | } | 95 | } |
@@ -103,11 +99,7 @@ static int __init uclinux_mtd_init(void) | |||
103 | static void __exit uclinux_mtd_cleanup(void) | 99 | static void __exit uclinux_mtd_cleanup(void) |
104 | { | 100 | { |
105 | if (uclinux_ram_mtdinfo) { | 101 | if (uclinux_ram_mtdinfo) { |
106 | #ifdef CONFIG_MTD_PARTITIONS | 102 | mtd_device_unregister(uclinux_ram_mtdinfo); |
107 | del_mtd_partitions(uclinux_ram_mtdinfo); | ||
108 | #else | ||
109 | del_mtd_device(uclinux_ram_mtdinfo); | ||
110 | #endif | ||
111 | map_destroy(uclinux_ram_mtdinfo); | 103 | map_destroy(uclinux_ram_mtdinfo); |
112 | uclinux_ram_mtdinfo = NULL; | 104 | uclinux_ram_mtdinfo = NULL; |
113 | } | 105 | } |
diff --git a/drivers/mtd/maps/vmax301.c b/drivers/mtd/maps/vmax301.c index 6adaa6acc193..5e68de73eabc 100644 --- a/drivers/mtd/maps/vmax301.c +++ b/drivers/mtd/maps/vmax301.c | |||
@@ -138,7 +138,7 @@ static void __exit cleanup_vmax301(void) | |||
138 | 138 | ||
139 | for (i=0; i<2; i++) { | 139 | for (i=0; i<2; i++) { |
140 | if (vmax_mtd[i]) { | 140 | if (vmax_mtd[i]) { |
141 | del_mtd_device(vmax_mtd[i]); | 141 | mtd_device_unregister(vmax_mtd[i]); |
142 | map_destroy(vmax_mtd[i]); | 142 | map_destroy(vmax_mtd[i]); |
143 | } | 143 | } |
144 | } | 144 | } |
@@ -176,7 +176,7 @@ static int __init init_vmax301(void) | |||
176 | vmax_mtd[i] = do_map_probe("map_rom", &vmax_map[i]); | 176 | vmax_mtd[i] = do_map_probe("map_rom", &vmax_map[i]); |
177 | if (vmax_mtd[i]) { | 177 | if (vmax_mtd[i]) { |
178 | vmax_mtd[i]->owner = THIS_MODULE; | 178 | vmax_mtd[i]->owner = THIS_MODULE; |
179 | add_mtd_device(vmax_mtd[i]); | 179 | mtd_device_register(vmax_mtd[i], NULL, 0); |
180 | } | 180 | } |
181 | } | 181 | } |
182 | 182 | ||
diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c index 4afc167731ef..3a04b078576a 100644 --- a/drivers/mtd/maps/vmu-flash.c +++ b/drivers/mtd/maps/vmu-flash.c | |||
@@ -563,7 +563,7 @@ static void vmu_queryblocks(struct mapleq *mq) | |||
563 | goto fail_cache_create; | 563 | goto fail_cache_create; |
564 | part_cur->pcache = pcache; | 564 | part_cur->pcache = pcache; |
565 | 565 | ||
566 | error = add_mtd_device(mtd_cur); | 566 | error = mtd_device_register(mtd_cur, NULL, 0); |
567 | if (error) | 567 | if (error) |
568 | goto fail_mtd_register; | 568 | goto fail_mtd_register; |
569 | 569 | ||
@@ -709,7 +709,7 @@ static void __devexit vmu_disconnect(struct maple_device *mdev) | |||
709 | for (x = 0; x < card->partitions; x++) { | 709 | for (x = 0; x < card->partitions; x++) { |
710 | mpart = ((card->mtd)[x]).priv; | 710 | mpart = ((card->mtd)[x]).priv; |
711 | mpart->mdev = NULL; | 711 | mpart->mdev = NULL; |
712 | del_mtd_device(&((card->mtd)[x])); | 712 | mtd_device_unregister(&((card->mtd)[x])); |
713 | kfree(((card->parts)[x]).name); | 713 | kfree(((card->parts)[x]).name); |
714 | } | 714 | } |
715 | kfree(card->parts); | 715 | kfree(card->parts); |
diff --git a/drivers/mtd/maps/wr_sbc82xx_flash.c b/drivers/mtd/maps/wr_sbc82xx_flash.c index 933a2b6598b4..901ce968efae 100644 --- a/drivers/mtd/maps/wr_sbc82xx_flash.c +++ b/drivers/mtd/maps/wr_sbc82xx_flash.c | |||
@@ -132,17 +132,20 @@ static int __init init_sbc82xx_flash(void) | |||
132 | nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes, | 132 | nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes, |
133 | &sbcmtd_parts[i], 0); | 133 | &sbcmtd_parts[i], 0); |
134 | if (nr_parts > 0) { | 134 | if (nr_parts > 0) { |
135 | add_mtd_partitions (sbcmtd[i], sbcmtd_parts[i], nr_parts); | 135 | mtd_device_register(sbcmtd[i], sbcmtd_parts[i], |
136 | nr_parts); | ||
136 | continue; | 137 | continue; |
137 | } | 138 | } |
138 | 139 | ||
139 | /* No partitioning detected. Use default */ | 140 | /* No partitioning detected. Use default */ |
140 | if (i == 2) { | 141 | if (i == 2) { |
141 | add_mtd_device(sbcmtd[i]); | 142 | mtd_device_register(sbcmtd[i], NULL, 0); |
142 | } else if (i == bigflash) { | 143 | } else if (i == bigflash) { |
143 | add_mtd_partitions (sbcmtd[i], bigflash_parts, ARRAY_SIZE(bigflash_parts)); | 144 | mtd_device_register(sbcmtd[i], bigflash_parts, |
145 | ARRAY_SIZE(bigflash_parts)); | ||
144 | } else { | 146 | } else { |
145 | add_mtd_partitions (sbcmtd[i], smallflash_parts, ARRAY_SIZE(smallflash_parts)); | 147 | mtd_device_register(sbcmtd[i], smallflash_parts, |
148 | ARRAY_SIZE(smallflash_parts)); | ||
146 | } | 149 | } |
147 | } | 150 | } |
148 | return 0; | 151 | return 0; |
@@ -157,9 +160,9 @@ static void __exit cleanup_sbc82xx_flash(void) | |||
157 | continue; | 160 | continue; |
158 | 161 | ||
159 | if (i<2 || sbcmtd_parts[i]) | 162 | if (i<2 || sbcmtd_parts[i]) |
160 | del_mtd_partitions(sbcmtd[i]); | 163 | mtd_device_unregister(sbcmtd[i]); |
161 | else | 164 | else |
162 | del_mtd_device(sbcmtd[i]); | 165 | mtd_device_unregister(sbcmtd[i]); |
163 | 166 | ||
164 | kfree(sbcmtd_parts[i]); | 167 | kfree(sbcmtd_parts[i]); |
165 | map_destroy(sbcmtd[i]); | 168 | map_destroy(sbcmtd[i]); |
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index a534e1f0c348..ca385697446e 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -221,15 +221,33 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) | |||
221 | kref_get(&dev->ref); | 221 | kref_get(&dev->ref); |
222 | __module_get(dev->tr->owner); | 222 | __module_get(dev->tr->owner); |
223 | 223 | ||
224 | if (dev->mtd) { | 224 | if (!dev->mtd) |
225 | ret = dev->tr->open ? dev->tr->open(dev) : 0; | 225 | goto unlock; |
226 | __get_mtd_device(dev->mtd); | 226 | |
227 | if (dev->tr->open) { | ||
228 | ret = dev->tr->open(dev); | ||
229 | if (ret) | ||
230 | goto error_put; | ||
227 | } | 231 | } |
228 | 232 | ||
233 | ret = __get_mtd_device(dev->mtd); | ||
234 | if (ret) | ||
235 | goto error_release; | ||
236 | |||
229 | unlock: | 237 | unlock: |
230 | mutex_unlock(&dev->lock); | 238 | mutex_unlock(&dev->lock); |
231 | blktrans_dev_put(dev); | 239 | blktrans_dev_put(dev); |
232 | return ret; | 240 | return ret; |
241 | |||
242 | error_release: | ||
243 | if (dev->tr->release) | ||
244 | dev->tr->release(dev); | ||
245 | error_put: | ||
246 | module_put(dev->tr->owner); | ||
247 | kref_put(&dev->ref, blktrans_dev_release); | ||
248 | mutex_unlock(&dev->lock); | ||
249 | blktrans_dev_put(dev); | ||
250 | return ret; | ||
233 | } | 251 | } |
234 | 252 | ||
235 | static int blktrans_release(struct gendisk *disk, fmode_t mode) | 253 | static int blktrans_release(struct gendisk *disk, fmode_t mode) |
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 4c36ef66a46b..3f92731a5b9e 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -166,10 +166,23 @@ static int mtd_close(struct inode *inode, struct file *file) | |||
166 | return 0; | 166 | return 0; |
167 | } /* mtd_close */ | 167 | } /* mtd_close */ |
168 | 168 | ||
169 | /* FIXME: This _really_ needs to die. In 2.5, we should lock the | 169 | /* Back in June 2001, dwmw2 wrote: |
170 | userspace buffer down and use it directly with readv/writev. | 170 | * |
171 | */ | 171 | * FIXME: This _really_ needs to die. In 2.5, we should lock the |
172 | #define MAX_KMALLOC_SIZE 0x20000 | 172 | * userspace buffer down and use it directly with readv/writev. |
173 | * | ||
174 | * The implementation below, using mtd_kmalloc_up_to, mitigates | ||
175 | * allocation failures when the system is under low-memory situations | ||
176 | * or if memory is highly fragmented at the cost of reducing the | ||
177 | * performance of the requested transfer due to a smaller buffer size. | ||
178 | * | ||
179 | * A more complex but more memory-efficient implementation based on | ||
180 | * get_user_pages and iovecs to cover extents of those pages is a | ||
181 | * longer-term goal, as intimated by dwmw2 above. However, for the | ||
182 | * write case, this requires yet more complex head and tail transfer | ||
183 | * handling when those head and tail offsets and sizes are such that | ||
184 | * alignment requirements are not met in the NAND subdriver. | ||
185 | */ | ||
173 | 186 | ||
174 | static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos) | 187 | static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos) |
175 | { | 188 | { |
@@ -179,6 +192,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t | |||
179 | size_t total_retlen=0; | 192 | size_t total_retlen=0; |
180 | int ret=0; | 193 | int ret=0; |
181 | int len; | 194 | int len; |
195 | size_t size = count; | ||
182 | char *kbuf; | 196 | char *kbuf; |
183 | 197 | ||
184 | DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n"); | 198 | DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n"); |
@@ -189,23 +203,12 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t | |||
189 | if (!count) | 203 | if (!count) |
190 | return 0; | 204 | return 0; |
191 | 205 | ||
192 | /* FIXME: Use kiovec in 2.5 to lock down the user's buffers | 206 | kbuf = mtd_kmalloc_up_to(mtd, &size); |
193 | and pass them directly to the MTD functions */ | ||
194 | |||
195 | if (count > MAX_KMALLOC_SIZE) | ||
196 | kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL); | ||
197 | else | ||
198 | kbuf=kmalloc(count, GFP_KERNEL); | ||
199 | |||
200 | if (!kbuf) | 207 | if (!kbuf) |
201 | return -ENOMEM; | 208 | return -ENOMEM; |
202 | 209 | ||
203 | while (count) { | 210 | while (count) { |
204 | 211 | len = min_t(size_t, count, size); | |
205 | if (count > MAX_KMALLOC_SIZE) | ||
206 | len = MAX_KMALLOC_SIZE; | ||
207 | else | ||
208 | len = count; | ||
209 | 212 | ||
210 | switch (mfi->mode) { | 213 | switch (mfi->mode) { |
211 | case MTD_MODE_OTP_FACTORY: | 214 | case MTD_MODE_OTP_FACTORY: |
@@ -268,6 +271,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count | |||
268 | { | 271 | { |
269 | struct mtd_file_info *mfi = file->private_data; | 272 | struct mtd_file_info *mfi = file->private_data; |
270 | struct mtd_info *mtd = mfi->mtd; | 273 | struct mtd_info *mtd = mfi->mtd; |
274 | size_t size = count; | ||
271 | char *kbuf; | 275 | char *kbuf; |
272 | size_t retlen; | 276 | size_t retlen; |
273 | size_t total_retlen=0; | 277 | size_t total_retlen=0; |
@@ -285,20 +289,12 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count | |||
285 | if (!count) | 289 | if (!count) |
286 | return 0; | 290 | return 0; |
287 | 291 | ||
288 | if (count > MAX_KMALLOC_SIZE) | 292 | kbuf = mtd_kmalloc_up_to(mtd, &size); |
289 | kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL); | ||
290 | else | ||
291 | kbuf=kmalloc(count, GFP_KERNEL); | ||
292 | |||
293 | if (!kbuf) | 293 | if (!kbuf) |
294 | return -ENOMEM; | 294 | return -ENOMEM; |
295 | 295 | ||
296 | while (count) { | 296 | while (count) { |
297 | 297 | len = min_t(size_t, count, size); | |
298 | if (count > MAX_KMALLOC_SIZE) | ||
299 | len = MAX_KMALLOC_SIZE; | ||
300 | else | ||
301 | len = count; | ||
302 | 298 | ||
303 | if (copy_from_user(kbuf, buf, len)) { | 299 | if (copy_from_user(kbuf, buf, len)) { |
304 | kfree(kbuf); | 300 | kfree(kbuf); |
@@ -512,7 +508,6 @@ static int shrink_ecclayout(const struct nand_ecclayout *from, | |||
512 | return 0; | 508 | return 0; |
513 | } | 509 | } |
514 | 510 | ||
515 | #ifdef CONFIG_MTD_PARTITIONS | ||
516 | static int mtd_blkpg_ioctl(struct mtd_info *mtd, | 511 | static int mtd_blkpg_ioctl(struct mtd_info *mtd, |
517 | struct blkpg_ioctl_arg __user *arg) | 512 | struct blkpg_ioctl_arg __user *arg) |
518 | { | 513 | { |
@@ -548,8 +543,6 @@ static int mtd_blkpg_ioctl(struct mtd_info *mtd, | |||
548 | return -EINVAL; | 543 | return -EINVAL; |
549 | } | 544 | } |
550 | } | 545 | } |
551 | #endif | ||
552 | |||
553 | 546 | ||
554 | static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | 547 | static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) |
555 | { | 548 | { |
@@ -941,7 +934,6 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
941 | break; | 934 | break; |
942 | } | 935 | } |
943 | 936 | ||
944 | #ifdef CONFIG_MTD_PARTITIONS | ||
945 | case BLKPG: | 937 | case BLKPG: |
946 | { | 938 | { |
947 | ret = mtd_blkpg_ioctl(mtd, | 939 | ret = mtd_blkpg_ioctl(mtd, |
@@ -955,7 +947,6 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
955 | ret = 0; | 947 | ret = 0; |
956 | break; | 948 | break; |
957 | } | 949 | } |
958 | #endif | ||
959 | 950 | ||
960 | default: | 951 | default: |
961 | ret = -ENOTTY; | 952 | ret = -ENOTTY; |
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 5060e608ea5d..e601672a5305 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c | |||
@@ -319,7 +319,7 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) | |||
319 | if (!(mtd->flags & MTD_WRITEABLE)) | 319 | if (!(mtd->flags & MTD_WRITEABLE)) |
320 | return -EROFS; | 320 | return -EROFS; |
321 | 321 | ||
322 | ops->retlen = 0; | 322 | ops->retlen = ops->oobretlen = 0; |
323 | 323 | ||
324 | for (i = 0; i < concat->num_subdev; i++) { | 324 | for (i = 0; i < concat->num_subdev; i++) { |
325 | struct mtd_info *subdev = concat->subdev[i]; | 325 | struct mtd_info *subdev = concat->subdev[i]; |
@@ -334,7 +334,7 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) | |||
334 | devops.len = subdev->size - to; | 334 | devops.len = subdev->size - to; |
335 | 335 | ||
336 | err = subdev->write_oob(subdev, to, &devops); | 336 | err = subdev->write_oob(subdev, to, &devops); |
337 | ops->retlen += devops.retlen; | 337 | ops->retlen += devops.oobretlen; |
338 | if (err) | 338 | if (err) |
339 | return err; | 339 | return err; |
340 | 340 | ||
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index da69bc8a5a7d..c510aff289a8 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/ptrace.h> | 26 | #include <linux/ptrace.h> |
27 | #include <linux/seq_file.h> | ||
27 | #include <linux/string.h> | 28 | #include <linux/string.h> |
28 | #include <linux/timer.h> | 29 | #include <linux/timer.h> |
29 | #include <linux/major.h> | 30 | #include <linux/major.h> |
@@ -37,6 +38,7 @@ | |||
37 | #include <linux/gfp.h> | 38 | #include <linux/gfp.h> |
38 | 39 | ||
39 | #include <linux/mtd/mtd.h> | 40 | #include <linux/mtd/mtd.h> |
41 | #include <linux/mtd/partitions.h> | ||
40 | 42 | ||
41 | #include "mtdcore.h" | 43 | #include "mtdcore.h" |
42 | /* | 44 | /* |
@@ -391,7 +393,7 @@ fail_locked: | |||
391 | * if the requested device does not appear to be present in the list. | 393 | * if the requested device does not appear to be present in the list. |
392 | */ | 394 | */ |
393 | 395 | ||
394 | int del_mtd_device (struct mtd_info *mtd) | 396 | int del_mtd_device(struct mtd_info *mtd) |
395 | { | 397 | { |
396 | int ret; | 398 | int ret; |
397 | struct mtd_notifier *not; | 399 | struct mtd_notifier *not; |
@@ -427,6 +429,50 @@ out_error: | |||
427 | } | 429 | } |
428 | 430 | ||
429 | /** | 431 | /** |
432 | * mtd_device_register - register an MTD device. | ||
433 | * | ||
434 | * @master: the MTD device to register | ||
435 | * @parts: the partitions to register - only valid if nr_parts > 0 | ||
436 | * @nr_parts: the number of partitions in parts. If zero then the full MTD | ||
437 | * device is registered | ||
438 | * | ||
439 | * Register an MTD device with the system and optionally, a number of | ||
440 | * partitions. If nr_parts is 0 then the whole device is registered, otherwise | ||
441 | * only the partitions are registered. To register both the full device *and* | ||
442 | * the partitions, call mtd_device_register() twice, once with nr_parts == 0 | ||
443 | * and once equal to the number of partitions. | ||
444 | */ | ||
445 | int mtd_device_register(struct mtd_info *master, | ||
446 | const struct mtd_partition *parts, | ||
447 | int nr_parts) | ||
448 | { | ||
449 | return parts ? add_mtd_partitions(master, parts, nr_parts) : | ||
450 | add_mtd_device(master); | ||
451 | } | ||
452 | EXPORT_SYMBOL_GPL(mtd_device_register); | ||
453 | |||
454 | /** | ||
455 | * mtd_device_unregister - unregister an existing MTD device. | ||
456 | * | ||
457 | * @master: the MTD device to unregister. This will unregister both the master | ||
458 | * and any partitions if registered. | ||
459 | */ | ||
460 | int mtd_device_unregister(struct mtd_info *master) | ||
461 | { | ||
462 | int err; | ||
463 | |||
464 | err = del_mtd_partitions(master); | ||
465 | if (err) | ||
466 | return err; | ||
467 | |||
468 | if (!device_is_registered(&master->dev)) | ||
469 | return 0; | ||
470 | |||
471 | return del_mtd_device(master); | ||
472 | } | ||
473 | EXPORT_SYMBOL_GPL(mtd_device_unregister); | ||
474 | |||
475 | /** | ||
430 | * register_mtd_user - register a 'user' of MTD devices. | 476 | * register_mtd_user - register a 'user' of MTD devices. |
431 | * @new: pointer to notifier info structure | 477 | * @new: pointer to notifier info structure |
432 | * | 478 | * |
@@ -443,7 +489,7 @@ void register_mtd_user (struct mtd_notifier *new) | |||
443 | 489 | ||
444 | list_add(&new->list, &mtd_notifiers); | 490 | list_add(&new->list, &mtd_notifiers); |
445 | 491 | ||
446 | __module_get(THIS_MODULE); | 492 | __module_get(THIS_MODULE); |
447 | 493 | ||
448 | mtd_for_each_device(mtd) | 494 | mtd_for_each_device(mtd) |
449 | new->add(mtd); | 495 | new->add(mtd); |
@@ -532,7 +578,6 @@ int __get_mtd_device(struct mtd_info *mtd) | |||
532 | return -ENODEV; | 578 | return -ENODEV; |
533 | 579 | ||
534 | if (mtd->get_device) { | 580 | if (mtd->get_device) { |
535 | |||
536 | err = mtd->get_device(mtd); | 581 | err = mtd->get_device(mtd); |
537 | 582 | ||
538 | if (err) { | 583 | if (err) { |
@@ -570,21 +615,13 @@ struct mtd_info *get_mtd_device_nm(const char *name) | |||
570 | if (!mtd) | 615 | if (!mtd) |
571 | goto out_unlock; | 616 | goto out_unlock; |
572 | 617 | ||
573 | if (!try_module_get(mtd->owner)) | 618 | err = __get_mtd_device(mtd); |
619 | if (err) | ||
574 | goto out_unlock; | 620 | goto out_unlock; |
575 | 621 | ||
576 | if (mtd->get_device) { | ||
577 | err = mtd->get_device(mtd); | ||
578 | if (err) | ||
579 | goto out_put; | ||
580 | } | ||
581 | |||
582 | mtd->usecount++; | ||
583 | mutex_unlock(&mtd_table_mutex); | 622 | mutex_unlock(&mtd_table_mutex); |
584 | return mtd; | 623 | return mtd; |
585 | 624 | ||
586 | out_put: | ||
587 | module_put(mtd->owner); | ||
588 | out_unlock: | 625 | out_unlock: |
589 | mutex_unlock(&mtd_table_mutex); | 626 | mutex_unlock(&mtd_table_mutex); |
590 | return ERR_PTR(err); | 627 | return ERR_PTR(err); |
@@ -638,8 +675,54 @@ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, | |||
638 | return ret; | 675 | return ret; |
639 | } | 676 | } |
640 | 677 | ||
641 | EXPORT_SYMBOL_GPL(add_mtd_device); | 678 | /** |
642 | EXPORT_SYMBOL_GPL(del_mtd_device); | 679 | * mtd_kmalloc_up_to - allocate a contiguous buffer up to the specified size |
680 | * @size: A pointer to the ideal or maximum size of the allocation. Points | ||
681 | * to the actual allocation size on success. | ||
682 | * | ||
683 | * This routine attempts to allocate a contiguous kernel buffer up to | ||
684 | * the specified size, backing off the size of the request exponentially | ||
685 | * until the request succeeds or until the allocation size falls below | ||
686 | * the system page size. This attempts to make sure it does not adversely | ||
687 | * impact system performance, so when allocating more than one page, we | ||
688 | * ask the memory allocator to avoid re-trying, swapping, writing back | ||
689 | * or performing I/O. | ||
690 | * | ||
691 | * Note, this function also makes sure that the allocated buffer is aligned to | ||
692 | * the MTD device's min. I/O unit, i.e. the "mtd->writesize" value. | ||
693 | * | ||
694 | * This is called, for example by mtd_{read,write} and jffs2_scan_medium, | ||
695 | * to handle smaller (i.e. degraded) buffer allocations under low- or | ||
696 | * fragmented-memory situations where such reduced allocations, from a | ||
697 | * requested ideal, are allowed. | ||
698 | * | ||
699 | * Returns a pointer to the allocated buffer on success; otherwise, NULL. | ||
700 | */ | ||
701 | void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size) | ||
702 | { | ||
703 | gfp_t flags = __GFP_NOWARN | __GFP_WAIT | | ||
704 | __GFP_NORETRY | __GFP_NO_KSWAPD; | ||
705 | size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE); | ||
706 | void *kbuf; | ||
707 | |||
708 | *size = min_t(size_t, *size, KMALLOC_MAX_SIZE); | ||
709 | |||
710 | while (*size > min_alloc) { | ||
711 | kbuf = kmalloc(*size, flags); | ||
712 | if (kbuf) | ||
713 | return kbuf; | ||
714 | |||
715 | *size >>= 1; | ||
716 | *size = ALIGN(*size, mtd->writesize); | ||
717 | } | ||
718 | |||
719 | /* | ||
720 | * For the last resort allocation allow 'kmalloc()' to do all sorts of | ||
721 | * things (write-back, dropping caches, etc) by using GFP_KERNEL. | ||
722 | */ | ||
723 | return kmalloc(*size, GFP_KERNEL); | ||
724 | } | ||
725 | |||
643 | EXPORT_SYMBOL_GPL(get_mtd_device); | 726 | EXPORT_SYMBOL_GPL(get_mtd_device); |
644 | EXPORT_SYMBOL_GPL(get_mtd_device_nm); | 727 | EXPORT_SYMBOL_GPL(get_mtd_device_nm); |
645 | EXPORT_SYMBOL_GPL(__get_mtd_device); | 728 | EXPORT_SYMBOL_GPL(__get_mtd_device); |
@@ -648,6 +731,7 @@ EXPORT_SYMBOL_GPL(__put_mtd_device); | |||
648 | EXPORT_SYMBOL_GPL(register_mtd_user); | 731 | EXPORT_SYMBOL_GPL(register_mtd_user); |
649 | EXPORT_SYMBOL_GPL(unregister_mtd_user); | 732 | EXPORT_SYMBOL_GPL(unregister_mtd_user); |
650 | EXPORT_SYMBOL_GPL(default_mtd_writev); | 733 | EXPORT_SYMBOL_GPL(default_mtd_writev); |
734 | EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to); | ||
651 | 735 | ||
652 | #ifdef CONFIG_PROC_FS | 736 | #ifdef CONFIG_PROC_FS |
653 | 737 | ||
@@ -656,44 +740,32 @@ EXPORT_SYMBOL_GPL(default_mtd_writev); | |||
656 | 740 | ||
657 | static struct proc_dir_entry *proc_mtd; | 741 | static struct proc_dir_entry *proc_mtd; |
658 | 742 | ||
659 | static inline int mtd_proc_info(char *buf, struct mtd_info *this) | 743 | static int mtd_proc_show(struct seq_file *m, void *v) |
660 | { | ||
661 | return sprintf(buf, "mtd%d: %8.8llx %8.8x \"%s\"\n", this->index, | ||
662 | (unsigned long long)this->size, | ||
663 | this->erasesize, this->name); | ||
664 | } | ||
665 | |||
666 | static int mtd_read_proc (char *page, char **start, off_t off, int count, | ||
667 | int *eof, void *data_unused) | ||
668 | { | 744 | { |
669 | struct mtd_info *mtd; | 745 | struct mtd_info *mtd; |
670 | int len, l; | ||
671 | off_t begin = 0; | ||
672 | 746 | ||
747 | seq_puts(m, "dev: size erasesize name\n"); | ||
673 | mutex_lock(&mtd_table_mutex); | 748 | mutex_lock(&mtd_table_mutex); |
674 | |||
675 | len = sprintf(page, "dev: size erasesize name\n"); | ||
676 | mtd_for_each_device(mtd) { | 749 | mtd_for_each_device(mtd) { |
677 | l = mtd_proc_info(page + len, mtd); | 750 | seq_printf(m, "mtd%d: %8.8llx %8.8x \"%s\"\n", |
678 | len += l; | 751 | mtd->index, (unsigned long long)mtd->size, |
679 | if (len+begin > off+count) | 752 | mtd->erasesize, mtd->name); |
680 | goto done; | 753 | } |
681 | if (len+begin < off) { | ||
682 | begin += len; | ||
683 | len = 0; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | *eof = 1; | ||
688 | |||
689 | done: | ||
690 | mutex_unlock(&mtd_table_mutex); | 754 | mutex_unlock(&mtd_table_mutex); |
691 | if (off >= len+begin) | 755 | return 0; |
692 | return 0; | 756 | } |
693 | *start = page + (off-begin); | 757 | |
694 | return ((count < begin+len-off) ? count : begin+len-off); | 758 | static int mtd_proc_open(struct inode *inode, struct file *file) |
759 | { | ||
760 | return single_open(file, mtd_proc_show, NULL); | ||
695 | } | 761 | } |
696 | 762 | ||
763 | static const struct file_operations mtd_proc_ops = { | ||
764 | .open = mtd_proc_open, | ||
765 | .read = seq_read, | ||
766 | .llseek = seq_lseek, | ||
767 | .release = single_release, | ||
768 | }; | ||
697 | #endif /* CONFIG_PROC_FS */ | 769 | #endif /* CONFIG_PROC_FS */ |
698 | 770 | ||
699 | /*====================================================================*/ | 771 | /*====================================================================*/ |
@@ -734,8 +806,7 @@ static int __init init_mtd(void) | |||
734 | goto err_bdi3; | 806 | goto err_bdi3; |
735 | 807 | ||
736 | #ifdef CONFIG_PROC_FS | 808 | #ifdef CONFIG_PROC_FS |
737 | if ((proc_mtd = create_proc_entry( "mtd", 0, NULL ))) | 809 | proc_mtd = proc_create("mtd", 0, NULL, &mtd_proc_ops); |
738 | proc_mtd->read_proc = mtd_read_proc; | ||
739 | #endif /* CONFIG_PROC_FS */ | 810 | #endif /* CONFIG_PROC_FS */ |
740 | return 0; | 811 | return 0; |
741 | 812 | ||
@@ -753,7 +824,7 @@ err_reg: | |||
753 | static void __exit cleanup_mtd(void) | 824 | static void __exit cleanup_mtd(void) |
754 | { | 825 | { |
755 | #ifdef CONFIG_PROC_FS | 826 | #ifdef CONFIG_PROC_FS |
756 | if (proc_mtd) | 827 | if (proc_mtd) |
757 | remove_proc_entry( "mtd", NULL); | 828 | remove_proc_entry( "mtd", NULL); |
758 | #endif /* CONFIG_PROC_FS */ | 829 | #endif /* CONFIG_PROC_FS */ |
759 | class_unregister(&mtd_class); | 830 | class_unregister(&mtd_class); |
diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h index 6a64fdebc898..0ed6126b4c1f 100644 --- a/drivers/mtd/mtdcore.h +++ b/drivers/mtd/mtdcore.h | |||
@@ -10,6 +10,12 @@ | |||
10 | extern struct mutex mtd_table_mutex; | 10 | extern struct mutex mtd_table_mutex; |
11 | extern struct mtd_info *__mtd_next_device(int i); | 11 | extern struct mtd_info *__mtd_next_device(int i); |
12 | 12 | ||
13 | extern int add_mtd_device(struct mtd_info *mtd); | ||
14 | extern int del_mtd_device(struct mtd_info *mtd); | ||
15 | extern int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, | ||
16 | int); | ||
17 | extern int del_mtd_partitions(struct mtd_info *); | ||
18 | |||
13 | #define mtd_for_each_device(mtd) \ | 19 | #define mtd_for_each_device(mtd) \ |
14 | for ((mtd) = __mtd_next_device(0); \ | 20 | for ((mtd) = __mtd_next_device(0); \ |
15 | (mtd) != NULL; \ | 21 | (mtd) != NULL; \ |
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 0a4760174782..630be3e7da04 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/mtd/partitions.h> | 31 | #include <linux/mtd/partitions.h> |
32 | #include <linux/err.h> | 32 | #include <linux/err.h> |
33 | 33 | ||
34 | #include "mtdcore.h" | ||
35 | |||
34 | /* Our partition linked list */ | 36 | /* Our partition linked list */ |
35 | static LIST_HEAD(mtd_partitions); | 37 | static LIST_HEAD(mtd_partitions); |
36 | static DEFINE_MUTEX(mtd_partitions_mutex); | 38 | static DEFINE_MUTEX(mtd_partitions_mutex); |
@@ -376,7 +378,6 @@ int del_mtd_partitions(struct mtd_info *master) | |||
376 | 378 | ||
377 | return err; | 379 | return err; |
378 | } | 380 | } |
379 | EXPORT_SYMBOL(del_mtd_partitions); | ||
380 | 381 | ||
381 | static struct mtd_part *allocate_partition(struct mtd_info *master, | 382 | static struct mtd_part *allocate_partition(struct mtd_info *master, |
382 | const struct mtd_partition *part, int partno, | 383 | const struct mtd_partition *part, int partno, |
@@ -671,7 +672,6 @@ int add_mtd_partitions(struct mtd_info *master, | |||
671 | 672 | ||
672 | return 0; | 673 | return 0; |
673 | } | 674 | } |
674 | EXPORT_SYMBOL(add_mtd_partitions); | ||
675 | 675 | ||
676 | static DEFINE_SPINLOCK(part_parser_lock); | 676 | static DEFINE_SPINLOCK(part_parser_lock); |
677 | static LIST_HEAD(part_parsers); | 677 | static LIST_HEAD(part_parsers); |
@@ -722,11 +722,8 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types, | |||
722 | parser = get_partition_parser(*types); | 722 | parser = get_partition_parser(*types); |
723 | if (!parser && !request_module("%s", *types)) | 723 | if (!parser && !request_module("%s", *types)) |
724 | parser = get_partition_parser(*types); | 724 | parser = get_partition_parser(*types); |
725 | if (!parser) { | 725 | if (!parser) |
726 | printk(KERN_NOTICE "%s partition parsing not available\n", | ||
727 | *types); | ||
728 | continue; | 726 | continue; |
729 | } | ||
730 | ret = (*parser->parse_fn)(master, pparts, origin); | 727 | ret = (*parser->parse_fn)(master, pparts, origin); |
731 | if (ret > 0) { | 728 | if (ret > 0) { |
732 | printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", | 729 | printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", |
diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c index fed215c4cfa1..fd7885327611 100644 --- a/drivers/mtd/mtdswap.c +++ b/drivers/mtd/mtdswap.c | |||
@@ -1450,7 +1450,13 @@ static void mtdswap_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
1450 | } | 1450 | } |
1451 | 1451 | ||
1452 | oinfo = mtd->ecclayout; | 1452 | oinfo = mtd->ecclayout; |
1453 | if (!mtd->oobsize || !oinfo || oinfo->oobavail < MTDSWAP_OOBSIZE) { | 1453 | if (!oinfo) { |
1454 | printk(KERN_ERR "%s: mtd%d does not have OOB\n", | ||
1455 | MTDSWAP_PREFIX, mtd->index); | ||
1456 | return; | ||
1457 | } | ||
1458 | |||
1459 | if (!mtd->oobsize || oinfo->oobavail < MTDSWAP_OOBSIZE) { | ||
1454 | printk(KERN_ERR "%s: Not enough free bytes in OOB, " | 1460 | printk(KERN_ERR "%s: Not enough free bytes in OOB, " |
1455 | "%d available, %zu needed.\n", | 1461 | "%d available, %zu needed.\n", |
1456 | MTDSWAP_PREFIX, oinfo->oobavail, MTDSWAP_OOBSIZE); | 1462 | MTDSWAP_PREFIX, oinfo->oobavail, MTDSWAP_OOBSIZE); |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index edec457d361d..4c3425235adc 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -92,7 +92,7 @@ config MTD_NAND_EDB7312 | |||
92 | 92 | ||
93 | config MTD_NAND_H1900 | 93 | config MTD_NAND_H1900 |
94 | tristate "iPAQ H1900 flash" | 94 | tristate "iPAQ H1900 flash" |
95 | depends on ARCH_PXA && MTD_PARTITIONS | 95 | depends on ARCH_PXA |
96 | help | 96 | help |
97 | This enables the driver for the iPAQ h1900 flash. | 97 | This enables the driver for the iPAQ h1900 flash. |
98 | 98 | ||
@@ -419,7 +419,6 @@ config MTD_NAND_TMIO | |||
419 | 419 | ||
420 | config MTD_NAND_NANDSIM | 420 | config MTD_NAND_NANDSIM |
421 | tristate "Support for NAND Flash Simulator" | 421 | tristate "Support for NAND Flash Simulator" |
422 | depends on MTD_PARTITIONS | ||
423 | help | 422 | help |
424 | The simulator may simulate various NAND flash chips for the | 423 | The simulator may simulate various NAND flash chips for the |
425 | MTD nand layer. | 424 | MTD nand layer. |
@@ -513,7 +512,7 @@ config MTD_NAND_SOCRATES | |||
513 | 512 | ||
514 | config MTD_NAND_NUC900 | 513 | config MTD_NAND_NUC900 |
515 | tristate "Support for NAND on Nuvoton NUC9xx/w90p910 evaluation boards." | 514 | tristate "Support for NAND on Nuvoton NUC9xx/w90p910 evaluation boards." |
516 | depends on ARCH_W90X900 && MTD_PARTITIONS | 515 | depends on ARCH_W90X900 |
517 | help | 516 | help |
518 | This enables the driver for the NAND Flash on evaluation board based | 517 | This enables the driver for the NAND Flash on evaluation board based |
519 | on w90p910 / NUC9xx. | 518 | on w90p910 / NUC9xx. |
diff --git a/drivers/mtd/nand/alauda.c b/drivers/mtd/nand/alauda.c index 8691e0482ed2..eb40ea829ab2 100644 --- a/drivers/mtd/nand/alauda.c +++ b/drivers/mtd/nand/alauda.c | |||
@@ -120,7 +120,7 @@ static void alauda_delete(struct kref *kref) | |||
120 | struct alauda *al = container_of(kref, struct alauda, kref); | 120 | struct alauda *al = container_of(kref, struct alauda, kref); |
121 | 121 | ||
122 | if (al->mtd) { | 122 | if (al->mtd) { |
123 | del_mtd_device(al->mtd); | 123 | mtd_device_unregister(al->mtd); |
124 | kfree(al->mtd); | 124 | kfree(al->mtd); |
125 | } | 125 | } |
126 | usb_put_dev(al->dev); | 126 | usb_put_dev(al->dev); |
@@ -592,7 +592,7 @@ static int alauda_init_media(struct alauda *al) | |||
592 | mtd->priv = al; | 592 | mtd->priv = al; |
593 | mtd->owner = THIS_MODULE; | 593 | mtd->owner = THIS_MODULE; |
594 | 594 | ||
595 | err = add_mtd_device(mtd); | 595 | err = mtd_device_register(mtd, NULL, 0); |
596 | if (err) { | 596 | if (err) { |
597 | err = -ENFILE; | 597 | err = -ENFILE; |
598 | goto error; | 598 | goto error; |
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index bc65bf71e1a2..78017eb9318e 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c | |||
@@ -235,8 +235,8 @@ static int __devinit ams_delta_init(struct platform_device *pdev) | |||
235 | } | 235 | } |
236 | 236 | ||
237 | /* Register the partitions */ | 237 | /* Register the partitions */ |
238 | add_mtd_partitions(ams_delta_mtd, partition_info, | 238 | mtd_device_register(ams_delta_mtd, partition_info, |
239 | ARRAY_SIZE(partition_info)); | 239 | ARRAY_SIZE(partition_info)); |
240 | 240 | ||
241 | goto out; | 241 | goto out; |
242 | 242 | ||
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 950646aa4c4b..b300705d41cb 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/mtd/nand.h> | 30 | #include <linux/mtd/nand.h> |
31 | #include <linux/mtd/partitions.h> | 31 | #include <linux/mtd/partitions.h> |
32 | 32 | ||
33 | #include <linux/dmaengine.h> | ||
33 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
34 | #include <linux/io.h> | 35 | #include <linux/io.h> |
35 | 36 | ||
@@ -494,11 +495,8 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
494 | struct resource *regs; | 495 | struct resource *regs; |
495 | struct resource *mem; | 496 | struct resource *mem; |
496 | int res; | 497 | int res; |
497 | |||
498 | #ifdef CONFIG_MTD_PARTITIONS | ||
499 | struct mtd_partition *partitions = NULL; | 498 | struct mtd_partition *partitions = NULL; |
500 | int num_partitions = 0; | 499 | int num_partitions = 0; |
501 | #endif | ||
502 | 500 | ||
503 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 501 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
504 | if (!mem) { | 502 | if (!mem) { |
@@ -656,7 +654,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
656 | goto err_scan_tail; | 654 | goto err_scan_tail; |
657 | } | 655 | } |
658 | 656 | ||
659 | #ifdef CONFIG_MTD_PARTITIONS | ||
660 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 657 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
661 | mtd->name = "atmel_nand"; | 658 | mtd->name = "atmel_nand"; |
662 | num_partitions = parse_mtd_partitions(mtd, part_probes, | 659 | num_partitions = parse_mtd_partitions(mtd, part_probes, |
@@ -672,17 +669,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
672 | goto err_no_partitions; | 669 | goto err_no_partitions; |
673 | } | 670 | } |
674 | 671 | ||
675 | res = add_mtd_partitions(mtd, partitions, num_partitions); | 672 | res = mtd_device_register(mtd, partitions, num_partitions); |
676 | #else | ||
677 | res = add_mtd_device(mtd); | ||
678 | #endif | ||
679 | |||
680 | if (!res) | 673 | if (!res) |
681 | return res; | 674 | return res; |
682 | 675 | ||
683 | #ifdef CONFIG_MTD_PARTITIONS | ||
684 | err_no_partitions: | 676 | err_no_partitions: |
685 | #endif | ||
686 | nand_release(mtd); | 677 | nand_release(mtd); |
687 | err_scan_tail: | 678 | err_scan_tail: |
688 | err_scan_ident: | 679 | err_scan_ident: |
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 5d513b54a7d7..e7767eef4505 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c | |||
@@ -581,7 +581,8 @@ static int __init au1xxx_nand_init(void) | |||
581 | } | 581 | } |
582 | 582 | ||
583 | /* Register the partitions */ | 583 | /* Register the partitions */ |
584 | add_mtd_partitions(au1550_mtd, partition_info, ARRAY_SIZE(partition_info)); | 584 | mtd_device_register(au1550_mtd, partition_info, |
585 | ARRAY_SIZE(partition_info)); | ||
585 | 586 | ||
586 | return 0; | 587 | return 0; |
587 | 588 | ||
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index 0911cf03db80..eddc9a224985 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c | |||
@@ -185,20 +185,20 @@ static int __init autcpu12_init(void) | |||
185 | /* Register the partitions */ | 185 | /* Register the partitions */ |
186 | switch (autcpu12_mtd->size) { | 186 | switch (autcpu12_mtd->size) { |
187 | case SZ_16M: | 187 | case SZ_16M: |
188 | add_mtd_partitions(autcpu12_mtd, partition_info16k, | 188 | mtd_device_register(autcpu12_mtd, partition_info16k, |
189 | NUM_PARTITIONS16K); | 189 | NUM_PARTITIONS16K); |
190 | break; | 190 | break; |
191 | case SZ_32M: | 191 | case SZ_32M: |
192 | add_mtd_partitions(autcpu12_mtd, partition_info32k, | 192 | mtd_device_register(autcpu12_mtd, partition_info32k, |
193 | NUM_PARTITIONS32K); | 193 | NUM_PARTITIONS32K); |
194 | break; | 194 | break; |
195 | case SZ_64M: | 195 | case SZ_64M: |
196 | add_mtd_partitions(autcpu12_mtd, partition_info64k, | 196 | mtd_device_register(autcpu12_mtd, partition_info64k, |
197 | NUM_PARTITIONS64K); | 197 | NUM_PARTITIONS64K); |
198 | break; | 198 | break; |
199 | case SZ_128M: | 199 | case SZ_128M: |
200 | add_mtd_partitions(autcpu12_mtd, partition_info128k, | 200 | mtd_device_register(autcpu12_mtd, partition_info128k, |
201 | NUM_PARTITIONS128K); | 201 | NUM_PARTITIONS128K); |
202 | break; | 202 | break; |
203 | default: | 203 | default: |
204 | printk("Unsupported SmartMedia device\n"); | 204 | printk("Unsupported SmartMedia device\n"); |
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c index dfe262c726fb..9ec280738a9a 100644 --- a/drivers/mtd/nand/bcm_umi_nand.c +++ b/drivers/mtd/nand/bcm_umi_nand.c | |||
@@ -52,9 +52,7 @@ | |||
52 | static const __devinitconst char gBanner[] = KERN_INFO \ | 52 | static const __devinitconst char gBanner[] = KERN_INFO \ |
53 | "BCM UMI MTD NAND Driver: 1.00\n"; | 53 | "BCM UMI MTD NAND Driver: 1.00\n"; |
54 | 54 | ||
55 | #ifdef CONFIG_MTD_PARTITIONS | ||
56 | const char *part_probes[] = { "cmdlinepart", NULL }; | 55 | const char *part_probes[] = { "cmdlinepart", NULL }; |
57 | #endif | ||
58 | 56 | ||
59 | #if NAND_ECC_BCH | 57 | #if NAND_ECC_BCH |
60 | static uint8_t scan_ff_pattern[] = { 0xff }; | 58 | static uint8_t scan_ff_pattern[] = { 0xff }; |
@@ -509,7 +507,7 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev) | |||
509 | kfree(board_mtd); | 507 | kfree(board_mtd); |
510 | return -EIO; | 508 | return -EIO; |
511 | } | 509 | } |
512 | add_mtd_partitions(board_mtd, partition_info, nr_partitions); | 510 | mtd_device_register(board_mtd, partition_info, nr_partitions); |
513 | } | 511 | } |
514 | 512 | ||
515 | /* Return happy */ | 513 | /* Return happy */ |
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 79947bea4d57..dd899cb5d366 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -659,15 +659,10 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info) | |||
659 | static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info) | 659 | static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info) |
660 | { | 660 | { |
661 | struct mtd_info *mtd = &info->mtd; | 661 | struct mtd_info *mtd = &info->mtd; |
662 | |||
663 | #ifdef CONFIG_MTD_PARTITIONS | ||
664 | struct mtd_partition *parts = info->platform->partitions; | 662 | struct mtd_partition *parts = info->platform->partitions; |
665 | int nr = info->platform->nr_partitions; | 663 | int nr = info->platform->nr_partitions; |
666 | 664 | ||
667 | return add_mtd_partitions(mtd, parts, nr); | 665 | return mtd_device_register(mtd, parts, nr); |
668 | #else | ||
669 | return add_mtd_device(mtd); | ||
670 | #endif | ||
671 | } | 666 | } |
672 | 667 | ||
673 | static int __devexit bf5xx_nand_remove(struct platform_device *pdev) | 668 | static int __devexit bf5xx_nand_remove(struct platform_device *pdev) |
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index e06c8983978e..87ebb4e5b0c3 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c | |||
@@ -90,9 +90,7 @@ static unsigned int numtimings; | |||
90 | static int timing[3]; | 90 | static int timing[3]; |
91 | module_param_array(timing, int, &numtimings, 0644); | 91 | module_param_array(timing, int, &numtimings, 0644); |
92 | 92 | ||
93 | #ifdef CONFIG_MTD_PARTITIONS | ||
94 | static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; | 93 | static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; |
95 | #endif | ||
96 | 94 | ||
97 | /* Hrm. Why isn't this already conditional on something in the struct device? */ | 95 | /* Hrm. Why isn't this already conditional on something in the struct device? */ |
98 | #define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0) | 96 | #define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0) |
@@ -632,10 +630,8 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
632 | struct cafe_priv *cafe; | 630 | struct cafe_priv *cafe; |
633 | uint32_t ctrl; | 631 | uint32_t ctrl; |
634 | int err = 0; | 632 | int err = 0; |
635 | #ifdef CONFIG_MTD_PARTITIONS | ||
636 | struct mtd_partition *parts; | 633 | struct mtd_partition *parts; |
637 | int nr_parts; | 634 | int nr_parts; |
638 | #endif | ||
639 | 635 | ||
640 | /* Very old versions shared the same PCI ident for all three | 636 | /* Very old versions shared the same PCI ident for all three |
641 | functions on the chip. Verify the class too... */ | 637 | functions on the chip. Verify the class too... */ |
@@ -804,9 +800,8 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
804 | pci_set_drvdata(pdev, mtd); | 800 | pci_set_drvdata(pdev, mtd); |
805 | 801 | ||
806 | /* We register the whole device first, separate from the partitions */ | 802 | /* We register the whole device first, separate from the partitions */ |
807 | add_mtd_device(mtd); | 803 | mtd_device_register(mtd, NULL, 0); |
808 | 804 | ||
809 | #ifdef CONFIG_MTD_PARTITIONS | ||
810 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 805 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
811 | mtd->name = "cafe_nand"; | 806 | mtd->name = "cafe_nand"; |
812 | #endif | 807 | #endif |
@@ -814,9 +809,8 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
814 | if (nr_parts > 0) { | 809 | if (nr_parts > 0) { |
815 | cafe->parts = parts; | 810 | cafe->parts = parts; |
816 | dev_info(&cafe->pdev->dev, "%d partitions found\n", nr_parts); | 811 | dev_info(&cafe->pdev->dev, "%d partitions found\n", nr_parts); |
817 | add_mtd_partitions(mtd, parts, nr_parts); | 812 | mtd_device_register(mtd, parts, nr_parts); |
818 | } | 813 | } |
819 | #endif | ||
820 | goto out; | 814 | goto out; |
821 | 815 | ||
822 | out_irq: | 816 | out_irq: |
@@ -838,7 +832,6 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev) | |||
838 | struct mtd_info *mtd = pci_get_drvdata(pdev); | 832 | struct mtd_info *mtd = pci_get_drvdata(pdev); |
839 | struct cafe_priv *cafe = mtd->priv; | 833 | struct cafe_priv *cafe = mtd->priv; |
840 | 834 | ||
841 | del_mtd_device(mtd); | ||
842 | /* Disable NAND IRQ in global IRQ mask register */ | 835 | /* Disable NAND IRQ in global IRQ mask register */ |
843 | cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); | 836 | cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); |
844 | free_irq(pdev->irq, mtd); | 837 | free_irq(pdev->irq, mtd); |
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c index 6e6495278258..6fc043a30d1e 100644 --- a/drivers/mtd/nand/cmx270_nand.c +++ b/drivers/mtd/nand/cmx270_nand.c | |||
@@ -238,7 +238,7 @@ static int __init cmx270_init(void) | |||
238 | 238 | ||
239 | /* Register the partitions */ | 239 | /* Register the partitions */ |
240 | pr_notice("Using %s partition definition\n", part_type); | 240 | pr_notice("Using %s partition definition\n", part_type); |
241 | ret = add_mtd_partitions(cmx270_nand_mtd, mtd_parts, mtd_parts_nb); | 241 | ret = mtd_device_register(cmx270_nand_mtd, mtd_parts, mtd_parts_nb); |
242 | if (ret) | 242 | if (ret) |
243 | goto err_scan; | 243 | goto err_scan; |
244 | 244 | ||
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index 71c35a0b9826..f59ad1f2d5db 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c | |||
@@ -277,22 +277,15 @@ static int is_geode(void) | |||
277 | return 0; | 277 | return 0; |
278 | } | 278 | } |
279 | 279 | ||
280 | |||
281 | #ifdef CONFIG_MTD_PARTITIONS | ||
282 | static const char *part_probes[] = { "cmdlinepart", NULL }; | 280 | static const char *part_probes[] = { "cmdlinepart", NULL }; |
283 | #endif | ||
284 | |||
285 | 281 | ||
286 | static int __init cs553x_init(void) | 282 | static int __init cs553x_init(void) |
287 | { | 283 | { |
288 | int err = -ENXIO; | 284 | int err = -ENXIO; |
289 | int i; | 285 | int i; |
290 | uint64_t val; | 286 | uint64_t val; |
291 | |||
292 | #ifdef CONFIG_MTD_PARTITIONS | ||
293 | int mtd_parts_nb = 0; | 287 | int mtd_parts_nb = 0; |
294 | struct mtd_partition *mtd_parts = NULL; | 288 | struct mtd_partition *mtd_parts = NULL; |
295 | #endif | ||
296 | 289 | ||
297 | /* If the CPU isn't a Geode GX or LX, abort */ | 290 | /* If the CPU isn't a Geode GX or LX, abort */ |
298 | if (!is_geode()) | 291 | if (!is_geode()) |
@@ -324,17 +317,11 @@ static int __init cs553x_init(void) | |||
324 | if (cs553x_mtd[i]) { | 317 | if (cs553x_mtd[i]) { |
325 | 318 | ||
326 | /* If any devices registered, return success. Else the last error. */ | 319 | /* If any devices registered, return success. Else the last error. */ |
327 | #ifdef CONFIG_MTD_PARTITIONS | ||
328 | mtd_parts_nb = parse_mtd_partitions(cs553x_mtd[i], part_probes, &mtd_parts, 0); | 320 | mtd_parts_nb = parse_mtd_partitions(cs553x_mtd[i], part_probes, &mtd_parts, 0); |
329 | if (mtd_parts_nb > 0) { | 321 | if (mtd_parts_nb > 0) |
330 | printk(KERN_NOTICE "Using command line partition definition\n"); | 322 | printk(KERN_NOTICE "Using command line partition definition\n"); |
331 | add_mtd_partitions(cs553x_mtd[i], mtd_parts, mtd_parts_nb); | 323 | mtd_device_register(cs553x_mtd[i], mtd_parts, |
332 | } else { | 324 | mtd_parts_nb); |
333 | add_mtd_device(cs553x_mtd[i]); | ||
334 | } | ||
335 | #else | ||
336 | add_mtd_device(cs553x_mtd[i]); | ||
337 | #endif | ||
338 | err = 0; | 325 | err = 0; |
339 | } | 326 | } |
340 | } | 327 | } |
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index aff3468867ac..1f34951ae1a7 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -530,6 +530,8 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
530 | int ret; | 530 | int ret; |
531 | uint32_t val; | 531 | uint32_t val; |
532 | nand_ecc_modes_t ecc_mode; | 532 | nand_ecc_modes_t ecc_mode; |
533 | struct mtd_partition *mtd_parts = NULL; | ||
534 | int mtd_parts_nb = 0; | ||
533 | 535 | ||
534 | /* insist on board-specific configuration */ | 536 | /* insist on board-specific configuration */ |
535 | if (!pdata) | 537 | if (!pdata) |
@@ -749,41 +751,33 @@ syndrome_done: | |||
749 | if (ret < 0) | 751 | if (ret < 0) |
750 | goto err_scan; | 752 | goto err_scan; |
751 | 753 | ||
752 | if (mtd_has_partitions()) { | 754 | if (mtd_has_cmdlinepart()) { |
753 | struct mtd_partition *mtd_parts = NULL; | 755 | static const char *probes[] __initconst = { |
754 | int mtd_parts_nb = 0; | 756 | "cmdlinepart", NULL |
757 | }; | ||
755 | 758 | ||
756 | if (mtd_has_cmdlinepart()) { | 759 | mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes, |
757 | static const char *probes[] __initconst = | 760 | &mtd_parts, 0); |
758 | { "cmdlinepart", NULL }; | 761 | } |
759 | |||
760 | mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes, | ||
761 | &mtd_parts, 0); | ||
762 | } | ||
763 | |||
764 | if (mtd_parts_nb <= 0) { | ||
765 | mtd_parts = pdata->parts; | ||
766 | mtd_parts_nb = pdata->nr_parts; | ||
767 | } | ||
768 | 762 | ||
769 | /* Register any partitions */ | 763 | if (mtd_parts_nb <= 0) { |
770 | if (mtd_parts_nb > 0) { | 764 | mtd_parts = pdata->parts; |
771 | ret = add_mtd_partitions(&info->mtd, | 765 | mtd_parts_nb = pdata->nr_parts; |
772 | mtd_parts, mtd_parts_nb); | 766 | } |
773 | if (ret == 0) | ||
774 | info->partitioned = true; | ||
775 | } | ||
776 | 767 | ||
777 | } else if (pdata->nr_parts) { | 768 | /* Register any partitions */ |
778 | dev_warn(&pdev->dev, "ignoring %d default partitions on %s\n", | 769 | if (mtd_parts_nb > 0) { |
779 | pdata->nr_parts, info->mtd.name); | 770 | ret = mtd_device_register(&info->mtd, mtd_parts, |
771 | mtd_parts_nb); | ||
772 | if (ret == 0) | ||
773 | info->partitioned = true; | ||
780 | } | 774 | } |
781 | 775 | ||
782 | /* If there's no partition info, just package the whole chip | 776 | /* If there's no partition info, just package the whole chip |
783 | * as a single MTD device. | 777 | * as a single MTD device. |
784 | */ | 778 | */ |
785 | if (!info->partitioned) | 779 | if (!info->partitioned) |
786 | ret = add_mtd_device(&info->mtd) ? -ENODEV : 0; | 780 | ret = mtd_device_register(&info->mtd, NULL, 0) ? -ENODEV : 0; |
787 | 781 | ||
788 | if (ret < 0) | 782 | if (ret < 0) |
789 | goto err_scan; | 783 | goto err_scan; |
@@ -824,10 +818,7 @@ static int __exit nand_davinci_remove(struct platform_device *pdev) | |||
824 | struct davinci_nand_info *info = platform_get_drvdata(pdev); | 818 | struct davinci_nand_info *info = platform_get_drvdata(pdev); |
825 | int status; | 819 | int status; |
826 | 820 | ||
827 | if (mtd_has_partitions() && info->partitioned) | 821 | status = mtd_device_unregister(&info->mtd); |
828 | status = del_mtd_partitions(&info->mtd); | ||
829 | else | ||
830 | status = del_mtd_device(&info->mtd); | ||
831 | 822 | ||
832 | spin_lock_irq(&davinci_nand_lock); | 823 | spin_lock_irq(&davinci_nand_lock); |
833 | if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME) | 824 | if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME) |
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 4633f094c510..d5276218945f 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/dma-mapping.h> | ||
22 | #include <linux/wait.h> | 23 | #include <linux/wait.h> |
23 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
@@ -44,16 +45,16 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting." | |||
44 | 45 | ||
45 | /* We define a macro here that combines all interrupts this driver uses into | 46 | /* We define a macro here that combines all interrupts this driver uses into |
46 | * a single constant value, for convenience. */ | 47 | * a single constant value, for convenience. */ |
47 | #define DENALI_IRQ_ALL (INTR_STATUS0__DMA_CMD_COMP | \ | 48 | #define DENALI_IRQ_ALL (INTR_STATUS__DMA_CMD_COMP | \ |
48 | INTR_STATUS0__ECC_TRANSACTION_DONE | \ | 49 | INTR_STATUS__ECC_TRANSACTION_DONE | \ |
49 | INTR_STATUS0__ECC_ERR | \ | 50 | INTR_STATUS__ECC_ERR | \ |
50 | INTR_STATUS0__PROGRAM_FAIL | \ | 51 | INTR_STATUS__PROGRAM_FAIL | \ |
51 | INTR_STATUS0__LOAD_COMP | \ | 52 | INTR_STATUS__LOAD_COMP | \ |
52 | INTR_STATUS0__PROGRAM_COMP | \ | 53 | INTR_STATUS__PROGRAM_COMP | \ |
53 | INTR_STATUS0__TIME_OUT | \ | 54 | INTR_STATUS__TIME_OUT | \ |
54 | INTR_STATUS0__ERASE_FAIL | \ | 55 | INTR_STATUS__ERASE_FAIL | \ |
55 | INTR_STATUS0__RST_COMP | \ | 56 | INTR_STATUS__RST_COMP | \ |
56 | INTR_STATUS0__ERASE_COMP) | 57 | INTR_STATUS__ERASE_COMP) |
57 | 58 | ||
58 | /* indicates whether or not the internal value for the flash bank is | 59 | /* indicates whether or not the internal value for the flash bank is |
59 | * valid or not */ | 60 | * valid or not */ |
@@ -95,30 +96,6 @@ static const struct pci_device_id denali_pci_ids[] = { | |||
95 | { /* end: all zeroes */ } | 96 | { /* end: all zeroes */ } |
96 | }; | 97 | }; |
97 | 98 | ||
98 | |||
99 | /* these are static lookup tables that give us easy access to | ||
100 | * registers in the NAND controller. | ||
101 | */ | ||
102 | static const uint32_t intr_status_addresses[4] = {INTR_STATUS0, | ||
103 | INTR_STATUS1, | ||
104 | INTR_STATUS2, | ||
105 | INTR_STATUS3}; | ||
106 | |||
107 | static const uint32_t device_reset_banks[4] = {DEVICE_RESET__BANK0, | ||
108 | DEVICE_RESET__BANK1, | ||
109 | DEVICE_RESET__BANK2, | ||
110 | DEVICE_RESET__BANK3}; | ||
111 | |||
112 | static const uint32_t operation_timeout[4] = {INTR_STATUS0__TIME_OUT, | ||
113 | INTR_STATUS1__TIME_OUT, | ||
114 | INTR_STATUS2__TIME_OUT, | ||
115 | INTR_STATUS3__TIME_OUT}; | ||
116 | |||
117 | static const uint32_t reset_complete[4] = {INTR_STATUS0__RST_COMP, | ||
118 | INTR_STATUS1__RST_COMP, | ||
119 | INTR_STATUS2__RST_COMP, | ||
120 | INTR_STATUS3__RST_COMP}; | ||
121 | |||
122 | /* forward declarations */ | 99 | /* forward declarations */ |
123 | static void clear_interrupts(struct denali_nand_info *denali); | 100 | static void clear_interrupts(struct denali_nand_info *denali); |
124 | static uint32_t wait_for_irq(struct denali_nand_info *denali, | 101 | static uint32_t wait_for_irq(struct denali_nand_info *denali, |
@@ -180,19 +157,17 @@ static void read_status(struct denali_nand_info *denali) | |||
180 | static void reset_bank(struct denali_nand_info *denali) | 157 | static void reset_bank(struct denali_nand_info *denali) |
181 | { | 158 | { |
182 | uint32_t irq_status = 0; | 159 | uint32_t irq_status = 0; |
183 | uint32_t irq_mask = reset_complete[denali->flash_bank] | | 160 | uint32_t irq_mask = INTR_STATUS__RST_COMP | |
184 | operation_timeout[denali->flash_bank]; | 161 | INTR_STATUS__TIME_OUT; |
185 | int bank = 0; | ||
186 | 162 | ||
187 | clear_interrupts(denali); | 163 | clear_interrupts(denali); |
188 | 164 | ||
189 | bank = device_reset_banks[denali->flash_bank]; | 165 | iowrite32(1 << denali->flash_bank, denali->flash_reg + DEVICE_RESET); |
190 | iowrite32(bank, denali->flash_reg + DEVICE_RESET); | ||
191 | 166 | ||
192 | irq_status = wait_for_irq(denali, irq_mask); | 167 | irq_status = wait_for_irq(denali, irq_mask); |
193 | 168 | ||
194 | if (irq_status & operation_timeout[denali->flash_bank]) | 169 | if (irq_status & INTR_STATUS__TIME_OUT) |
195 | dev_err(&denali->dev->dev, "reset bank failed.\n"); | 170 | dev_err(denali->dev, "reset bank failed.\n"); |
196 | } | 171 | } |
197 | 172 | ||
198 | /* Reset the flash controller */ | 173 | /* Reset the flash controller */ |
@@ -200,29 +175,28 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali) | |||
200 | { | 175 | { |
201 | uint32_t i; | 176 | uint32_t i; |
202 | 177 | ||
203 | dev_dbg(&denali->dev->dev, "%s, Line %d, Function: %s\n", | 178 | dev_dbg(denali->dev, "%s, Line %d, Function: %s\n", |
204 | __FILE__, __LINE__, __func__); | 179 | __FILE__, __LINE__, __func__); |
205 | 180 | ||
206 | for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) | 181 | for (i = 0 ; i < denali->max_banks; i++) |
207 | iowrite32(reset_complete[i] | operation_timeout[i], | 182 | iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT, |
208 | denali->flash_reg + intr_status_addresses[i]); | 183 | denali->flash_reg + INTR_STATUS(i)); |
209 | 184 | ||
210 | for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) { | 185 | for (i = 0 ; i < denali->max_banks; i++) { |
211 | iowrite32(device_reset_banks[i], | 186 | iowrite32(1 << i, denali->flash_reg + DEVICE_RESET); |
212 | denali->flash_reg + DEVICE_RESET); | ||
213 | while (!(ioread32(denali->flash_reg + | 187 | while (!(ioread32(denali->flash_reg + |
214 | intr_status_addresses[i]) & | 188 | INTR_STATUS(i)) & |
215 | (reset_complete[i] | operation_timeout[i]))) | 189 | (INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT))) |
216 | cpu_relax(); | 190 | cpu_relax(); |
217 | if (ioread32(denali->flash_reg + intr_status_addresses[i]) & | 191 | if (ioread32(denali->flash_reg + INTR_STATUS(i)) & |
218 | operation_timeout[i]) | 192 | INTR_STATUS__TIME_OUT) |
219 | dev_dbg(&denali->dev->dev, | 193 | dev_dbg(denali->dev, |
220 | "NAND Reset operation timed out on bank %d\n", i); | 194 | "NAND Reset operation timed out on bank %d\n", i); |
221 | } | 195 | } |
222 | 196 | ||
223 | for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) | 197 | for (i = 0; i < denali->max_banks; i++) |
224 | iowrite32(reset_complete[i] | operation_timeout[i], | 198 | iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT, |
225 | denali->flash_reg + intr_status_addresses[i]); | 199 | denali->flash_reg + INTR_STATUS(i)); |
226 | 200 | ||
227 | return PASS; | 201 | return PASS; |
228 | } | 202 | } |
@@ -254,7 +228,7 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali, | |||
254 | uint16_t acc_clks; | 228 | uint16_t acc_clks; |
255 | uint16_t addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt; | 229 | uint16_t addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt; |
256 | 230 | ||
257 | dev_dbg(&denali->dev->dev, "%s, Line %d, Function: %s\n", | 231 | dev_dbg(denali->dev, "%s, Line %d, Function: %s\n", |
258 | __FILE__, __LINE__, __func__); | 232 | __FILE__, __LINE__, __func__); |
259 | 233 | ||
260 | en_lo = CEIL_DIV(Trp[mode], CLK_X); | 234 | en_lo = CEIL_DIV(Trp[mode], CLK_X); |
@@ -291,7 +265,7 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali, | |||
291 | acc_clks++; | 265 | acc_clks++; |
292 | 266 | ||
293 | if ((data_invalid - acc_clks * CLK_X) < 2) | 267 | if ((data_invalid - acc_clks * CLK_X) < 2) |
294 | dev_warn(&denali->dev->dev, "%s, Line %d: Warning!\n", | 268 | dev_warn(denali->dev, "%s, Line %d: Warning!\n", |
295 | __FILE__, __LINE__); | 269 | __FILE__, __LINE__); |
296 | 270 | ||
297 | addr_2_data = CEIL_DIV(Tadl[mode], CLK_X); | 271 | addr_2_data = CEIL_DIV(Tadl[mode], CLK_X); |
@@ -419,7 +393,7 @@ static void get_hynix_nand_para(struct denali_nand_info *denali, | |||
419 | #endif | 393 | #endif |
420 | break; | 394 | break; |
421 | default: | 395 | default: |
422 | dev_warn(&denali->dev->dev, | 396 | dev_warn(denali->dev, |
423 | "Spectra: Unknown Hynix NAND (Device ID: 0x%x)." | 397 | "Spectra: Unknown Hynix NAND (Device ID: 0x%x)." |
424 | "Will use default parameter values instead.\n", | 398 | "Will use default parameter values instead.\n", |
425 | device_id); | 399 | device_id); |
@@ -431,17 +405,17 @@ static void get_hynix_nand_para(struct denali_nand_info *denali, | |||
431 | */ | 405 | */ |
432 | static void find_valid_banks(struct denali_nand_info *denali) | 406 | static void find_valid_banks(struct denali_nand_info *denali) |
433 | { | 407 | { |
434 | uint32_t id[LLD_MAX_FLASH_BANKS]; | 408 | uint32_t id[denali->max_banks]; |
435 | int i; | 409 | int i; |
436 | 410 | ||
437 | denali->total_used_banks = 1; | 411 | denali->total_used_banks = 1; |
438 | for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) { | 412 | for (i = 0; i < denali->max_banks; i++) { |
439 | index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 0), 0x90); | 413 | index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 0), 0x90); |
440 | index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 1), 0); | 414 | index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 1), 0); |
441 | index_addr_read_data(denali, | 415 | index_addr_read_data(denali, |
442 | (uint32_t)(MODE_11 | (i << 24) | 2), &id[i]); | 416 | (uint32_t)(MODE_11 | (i << 24) | 2), &id[i]); |
443 | 417 | ||
444 | dev_dbg(&denali->dev->dev, | 418 | dev_dbg(denali->dev, |
445 | "Return 1st ID for bank[%d]: %x\n", i, id[i]); | 419 | "Return 1st ID for bank[%d]: %x\n", i, id[i]); |
446 | 420 | ||
447 | if (i == 0) { | 421 | if (i == 0) { |
@@ -461,16 +435,27 @@ static void find_valid_banks(struct denali_nand_info *denali) | |||
461 | * Multichip support is not enabled. | 435 | * Multichip support is not enabled. |
462 | */ | 436 | */ |
463 | if (denali->total_used_banks != 1) { | 437 | if (denali->total_used_banks != 1) { |
464 | dev_err(&denali->dev->dev, | 438 | dev_err(denali->dev, |
465 | "Sorry, Intel CE4100 only supports " | 439 | "Sorry, Intel CE4100 only supports " |
466 | "a single NAND device.\n"); | 440 | "a single NAND device.\n"); |
467 | BUG(); | 441 | BUG(); |
468 | } | 442 | } |
469 | } | 443 | } |
470 | dev_dbg(&denali->dev->dev, | 444 | dev_dbg(denali->dev, |
471 | "denali->total_used_banks: %d\n", denali->total_used_banks); | 445 | "denali->total_used_banks: %d\n", denali->total_used_banks); |
472 | } | 446 | } |
473 | 447 | ||
448 | /* | ||
449 | * Use the configuration feature register to determine the maximum number of | ||
450 | * banks that the hardware supports. | ||
451 | */ | ||
452 | static void detect_max_banks(struct denali_nand_info *denali) | ||
453 | { | ||
454 | uint32_t features = ioread32(denali->flash_reg + FEATURES); | ||
455 | |||
456 | denali->max_banks = 2 << (features & FEATURES__N_BANKS); | ||
457 | } | ||
458 | |||
474 | static void detect_partition_feature(struct denali_nand_info *denali) | 459 | static void detect_partition_feature(struct denali_nand_info *denali) |
475 | { | 460 | { |
476 | /* For MRST platform, denali->fwblks represent the | 461 | /* For MRST platform, denali->fwblks represent the |
@@ -480,15 +465,15 @@ static void detect_partition_feature(struct denali_nand_info *denali) | |||
480 | * blocks it can't touch. | 465 | * blocks it can't touch. |
481 | * */ | 466 | * */ |
482 | if (ioread32(denali->flash_reg + FEATURES) & FEATURES__PARTITION) { | 467 | if (ioread32(denali->flash_reg + FEATURES) & FEATURES__PARTITION) { |
483 | if ((ioread32(denali->flash_reg + PERM_SRC_ID_1) & | 468 | if ((ioread32(denali->flash_reg + PERM_SRC_ID(1)) & |
484 | PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) { | 469 | PERM_SRC_ID__SRCID) == SPECTRA_PARTITION_ID) { |
485 | denali->fwblks = | 470 | denali->fwblks = |
486 | ((ioread32(denali->flash_reg + MIN_MAX_BANK_1) & | 471 | ((ioread32(denali->flash_reg + MIN_MAX_BANK(1)) & |
487 | MIN_MAX_BANK_1__MIN_VALUE) * | 472 | MIN_MAX_BANK__MIN_VALUE) * |
488 | denali->blksperchip) | 473 | denali->blksperchip) |
489 | + | 474 | + |
490 | (ioread32(denali->flash_reg + MIN_BLK_ADDR_1) & | 475 | (ioread32(denali->flash_reg + MIN_BLK_ADDR(1)) & |
491 | MIN_BLK_ADDR_1__VALUE); | 476 | MIN_BLK_ADDR__VALUE); |
492 | } else | 477 | } else |
493 | denali->fwblks = SPECTRA_START_BLOCK; | 478 | denali->fwblks = SPECTRA_START_BLOCK; |
494 | } else | 479 | } else |
@@ -501,7 +486,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) | |||
501 | uint32_t id_bytes[5], addr; | 486 | uint32_t id_bytes[5], addr; |
502 | uint8_t i, maf_id, device_id; | 487 | uint8_t i, maf_id, device_id; |
503 | 488 | ||
504 | dev_dbg(&denali->dev->dev, | 489 | dev_dbg(denali->dev, |
505 | "%s, Line %d, Function: %s\n", | 490 | "%s, Line %d, Function: %s\n", |
506 | __FILE__, __LINE__, __func__); | 491 | __FILE__, __LINE__, __func__); |
507 | 492 | ||
@@ -530,7 +515,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) | |||
530 | get_hynix_nand_para(denali, device_id); | 515 | get_hynix_nand_para(denali, device_id); |
531 | } | 516 | } |
532 | 517 | ||
533 | dev_info(&denali->dev->dev, | 518 | dev_info(denali->dev, |
534 | "Dump timing register values:" | 519 | "Dump timing register values:" |
535 | "acc_clks: %d, re_2_we: %d, re_2_re: %d\n" | 520 | "acc_clks: %d, re_2_we: %d, re_2_re: %d\n" |
536 | "we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n" | 521 | "we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n" |
@@ -560,7 +545,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) | |||
560 | static void denali_set_intr_modes(struct denali_nand_info *denali, | 545 | static void denali_set_intr_modes(struct denali_nand_info *denali, |
561 | uint16_t INT_ENABLE) | 546 | uint16_t INT_ENABLE) |
562 | { | 547 | { |
563 | dev_dbg(&denali->dev->dev, "%s, Line %d, Function: %s\n", | 548 | dev_dbg(denali->dev, "%s, Line %d, Function: %s\n", |
564 | __FILE__, __LINE__, __func__); | 549 | __FILE__, __LINE__, __func__); |
565 | 550 | ||
566 | if (INT_ENABLE) | 551 | if (INT_ENABLE) |
@@ -580,6 +565,7 @@ static inline bool is_flash_bank_valid(int flash_bank) | |||
580 | static void denali_irq_init(struct denali_nand_info *denali) | 565 | static void denali_irq_init(struct denali_nand_info *denali) |
581 | { | 566 | { |
582 | uint32_t int_mask = 0; | 567 | uint32_t int_mask = 0; |
568 | int i; | ||
583 | 569 | ||
584 | /* Disable global interrupts */ | 570 | /* Disable global interrupts */ |
585 | denali_set_intr_modes(denali, false); | 571 | denali_set_intr_modes(denali, false); |
@@ -587,10 +573,8 @@ static void denali_irq_init(struct denali_nand_info *denali) | |||
587 | int_mask = DENALI_IRQ_ALL; | 573 | int_mask = DENALI_IRQ_ALL; |
588 | 574 | ||
589 | /* Clear all status bits */ | 575 | /* Clear all status bits */ |
590 | iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS0); | 576 | for (i = 0; i < denali->max_banks; ++i) |
591 | iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS1); | 577 | iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS(i)); |
592 | iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS2); | ||
593 | iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS3); | ||
594 | 578 | ||
595 | denali_irq_enable(denali, int_mask); | 579 | denali_irq_enable(denali, int_mask); |
596 | } | 580 | } |
@@ -604,10 +588,10 @@ static void denali_irq_cleanup(int irqnum, struct denali_nand_info *denali) | |||
604 | static void denali_irq_enable(struct denali_nand_info *denali, | 588 | static void denali_irq_enable(struct denali_nand_info *denali, |
605 | uint32_t int_mask) | 589 | uint32_t int_mask) |
606 | { | 590 | { |
607 | iowrite32(int_mask, denali->flash_reg + INTR_EN0); | 591 | int i; |
608 | iowrite32(int_mask, denali->flash_reg + INTR_EN1); | 592 | |
609 | iowrite32(int_mask, denali->flash_reg + INTR_EN2); | 593 | for (i = 0; i < denali->max_banks; ++i) |
610 | iowrite32(int_mask, denali->flash_reg + INTR_EN3); | 594 | iowrite32(int_mask, denali->flash_reg + INTR_EN(i)); |
611 | } | 595 | } |
612 | 596 | ||
613 | /* This function only returns when an interrupt that this driver cares about | 597 | /* This function only returns when an interrupt that this driver cares about |
@@ -624,7 +608,7 @@ static inline void clear_interrupt(struct denali_nand_info *denali, | |||
624 | { | 608 | { |
625 | uint32_t intr_status_reg = 0; | 609 | uint32_t intr_status_reg = 0; |
626 | 610 | ||
627 | intr_status_reg = intr_status_addresses[denali->flash_bank]; | 611 | intr_status_reg = INTR_STATUS(denali->flash_bank); |
628 | 612 | ||
629 | iowrite32(irq_mask, denali->flash_reg + intr_status_reg); | 613 | iowrite32(irq_mask, denali->flash_reg + intr_status_reg); |
630 | } | 614 | } |
@@ -645,7 +629,7 @@ static uint32_t read_interrupt_status(struct denali_nand_info *denali) | |||
645 | { | 629 | { |
646 | uint32_t intr_status_reg = 0; | 630 | uint32_t intr_status_reg = 0; |
647 | 631 | ||
648 | intr_status_reg = intr_status_addresses[denali->flash_bank]; | 632 | intr_status_reg = INTR_STATUS(denali->flash_bank); |
649 | 633 | ||
650 | return ioread32(denali->flash_reg + intr_status_reg); | 634 | return ioread32(denali->flash_reg + intr_status_reg); |
651 | } | 635 | } |
@@ -754,7 +738,7 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, | |||
754 | irq_mask = 0; | 738 | irq_mask = 0; |
755 | 739 | ||
756 | if (op == DENALI_READ) | 740 | if (op == DENALI_READ) |
757 | irq_mask = INTR_STATUS0__LOAD_COMP; | 741 | irq_mask = INTR_STATUS__LOAD_COMP; |
758 | else if (op == DENALI_WRITE) | 742 | else if (op == DENALI_WRITE) |
759 | irq_mask = 0; | 743 | irq_mask = 0; |
760 | else | 744 | else |
@@ -800,7 +784,7 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, | |||
800 | irq_status = wait_for_irq(denali, irq_mask); | 784 | irq_status = wait_for_irq(denali, irq_mask); |
801 | 785 | ||
802 | if (irq_status == 0) { | 786 | if (irq_status == 0) { |
803 | dev_err(&denali->dev->dev, | 787 | dev_err(denali->dev, |
804 | "cmd, page, addr on timeout " | 788 | "cmd, page, addr on timeout " |
805 | "(0x%x, 0x%x, 0x%x)\n", | 789 | "(0x%x, 0x%x, 0x%x)\n", |
806 | cmd, denali->page, addr); | 790 | cmd, denali->page, addr); |
@@ -861,8 +845,8 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | |||
861 | { | 845 | { |
862 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 846 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
863 | uint32_t irq_status = 0; | 847 | uint32_t irq_status = 0; |
864 | uint32_t irq_mask = INTR_STATUS0__PROGRAM_COMP | | 848 | uint32_t irq_mask = INTR_STATUS__PROGRAM_COMP | |
865 | INTR_STATUS0__PROGRAM_FAIL; | 849 | INTR_STATUS__PROGRAM_FAIL; |
866 | int status = 0; | 850 | int status = 0; |
867 | 851 | ||
868 | denali->page = page; | 852 | denali->page = page; |
@@ -875,11 +859,11 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | |||
875 | irq_status = wait_for_irq(denali, irq_mask); | 859 | irq_status = wait_for_irq(denali, irq_mask); |
876 | 860 | ||
877 | if (irq_status == 0) { | 861 | if (irq_status == 0) { |
878 | dev_err(&denali->dev->dev, "OOB write failed\n"); | 862 | dev_err(denali->dev, "OOB write failed\n"); |
879 | status = -EIO; | 863 | status = -EIO; |
880 | } | 864 | } |
881 | } else { | 865 | } else { |
882 | dev_err(&denali->dev->dev, "unable to send pipeline command\n"); | 866 | dev_err(denali->dev, "unable to send pipeline command\n"); |
883 | status = -EIO; | 867 | status = -EIO; |
884 | } | 868 | } |
885 | return status; | 869 | return status; |
@@ -889,7 +873,7 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | |||
889 | static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | 873 | static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) |
890 | { | 874 | { |
891 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 875 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
892 | uint32_t irq_mask = INTR_STATUS0__LOAD_COMP, | 876 | uint32_t irq_mask = INTR_STATUS__LOAD_COMP, |
893 | irq_status = 0, addr = 0x0, cmd = 0x0; | 877 | irq_status = 0, addr = 0x0, cmd = 0x0; |
894 | 878 | ||
895 | denali->page = page; | 879 | denali->page = page; |
@@ -904,7 +888,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | |||
904 | irq_status = wait_for_irq(denali, irq_mask); | 888 | irq_status = wait_for_irq(denali, irq_mask); |
905 | 889 | ||
906 | if (irq_status == 0) | 890 | if (irq_status == 0) |
907 | dev_err(&denali->dev->dev, "page on OOB timeout %d\n", | 891 | dev_err(denali->dev, "page on OOB timeout %d\n", |
908 | denali->page); | 892 | denali->page); |
909 | 893 | ||
910 | /* We set the device back to MAIN_ACCESS here as I observed | 894 | /* We set the device back to MAIN_ACCESS here as I observed |
@@ -944,7 +928,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, | |||
944 | { | 928 | { |
945 | bool check_erased_page = false; | 929 | bool check_erased_page = false; |
946 | 930 | ||
947 | if (irq_status & INTR_STATUS0__ECC_ERR) { | 931 | if (irq_status & INTR_STATUS__ECC_ERR) { |
948 | /* read the ECC errors. we'll ignore them for now */ | 932 | /* read the ECC errors. we'll ignore them for now */ |
949 | uint32_t err_address = 0, err_correction_info = 0; | 933 | uint32_t err_address = 0, err_correction_info = 0; |
950 | uint32_t err_byte = 0, err_sector = 0, err_device = 0; | 934 | uint32_t err_byte = 0, err_sector = 0, err_device = 0; |
@@ -995,7 +979,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, | |||
995 | * for a while for this interrupt | 979 | * for a while for this interrupt |
996 | * */ | 980 | * */ |
997 | while (!(read_interrupt_status(denali) & | 981 | while (!(read_interrupt_status(denali) & |
998 | INTR_STATUS0__ECC_TRANSACTION_DONE)) | 982 | INTR_STATUS__ECC_TRANSACTION_DONE)) |
999 | cpu_relax(); | 983 | cpu_relax(); |
1000 | clear_interrupts(denali); | 984 | clear_interrupts(denali); |
1001 | denali_set_intr_modes(denali, true); | 985 | denali_set_intr_modes(denali, true); |
@@ -1045,14 +1029,13 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1045 | const uint8_t *buf, bool raw_xfer) | 1029 | const uint8_t *buf, bool raw_xfer) |
1046 | { | 1030 | { |
1047 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1031 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1048 | struct pci_dev *pci_dev = denali->dev; | ||
1049 | 1032 | ||
1050 | dma_addr_t addr = denali->buf.dma_buf; | 1033 | dma_addr_t addr = denali->buf.dma_buf; |
1051 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; | 1034 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; |
1052 | 1035 | ||
1053 | uint32_t irq_status = 0; | 1036 | uint32_t irq_status = 0; |
1054 | uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP | | 1037 | uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP | |
1055 | INTR_STATUS0__PROGRAM_FAIL; | 1038 | INTR_STATUS__PROGRAM_FAIL; |
1056 | 1039 | ||
1057 | /* if it is a raw xfer, we want to disable ecc, and send | 1040 | /* if it is a raw xfer, we want to disable ecc, and send |
1058 | * the spare area. | 1041 | * the spare area. |
@@ -1071,7 +1054,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1071 | mtd->oobsize); | 1054 | mtd->oobsize); |
1072 | } | 1055 | } |
1073 | 1056 | ||
1074 | pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_TODEVICE); | 1057 | dma_sync_single_for_device(denali->dev, addr, size, DMA_TO_DEVICE); |
1075 | 1058 | ||
1076 | clear_interrupts(denali); | 1059 | clear_interrupts(denali); |
1077 | denali_enable_dma(denali, true); | 1060 | denali_enable_dma(denali, true); |
@@ -1082,16 +1065,16 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1082 | irq_status = wait_for_irq(denali, irq_mask); | 1065 | irq_status = wait_for_irq(denali, irq_mask); |
1083 | 1066 | ||
1084 | if (irq_status == 0) { | 1067 | if (irq_status == 0) { |
1085 | dev_err(&denali->dev->dev, | 1068 | dev_err(denali->dev, |
1086 | "timeout on write_page (type = %d)\n", | 1069 | "timeout on write_page (type = %d)\n", |
1087 | raw_xfer); | 1070 | raw_xfer); |
1088 | denali->status = | 1071 | denali->status = |
1089 | (irq_status & INTR_STATUS0__PROGRAM_FAIL) ? | 1072 | (irq_status & INTR_STATUS__PROGRAM_FAIL) ? |
1090 | NAND_STATUS_FAIL : PASS; | 1073 | NAND_STATUS_FAIL : PASS; |
1091 | } | 1074 | } |
1092 | 1075 | ||
1093 | denali_enable_dma(denali, false); | 1076 | denali_enable_dma(denali, false); |
1094 | pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_TODEVICE); | 1077 | dma_sync_single_for_cpu(denali->dev, addr, size, DMA_TO_DEVICE); |
1095 | } | 1078 | } |
1096 | 1079 | ||
1097 | /* NAND core entry points */ | 1080 | /* NAND core entry points */ |
@@ -1139,18 +1122,17 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1139 | uint8_t *buf, int page) | 1122 | uint8_t *buf, int page) |
1140 | { | 1123 | { |
1141 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1124 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1142 | struct pci_dev *pci_dev = denali->dev; | ||
1143 | 1125 | ||
1144 | dma_addr_t addr = denali->buf.dma_buf; | 1126 | dma_addr_t addr = denali->buf.dma_buf; |
1145 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; | 1127 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; |
1146 | 1128 | ||
1147 | uint32_t irq_status = 0; | 1129 | uint32_t irq_status = 0; |
1148 | uint32_t irq_mask = INTR_STATUS0__ECC_TRANSACTION_DONE | | 1130 | uint32_t irq_mask = INTR_STATUS__ECC_TRANSACTION_DONE | |
1149 | INTR_STATUS0__ECC_ERR; | 1131 | INTR_STATUS__ECC_ERR; |
1150 | bool check_erased_page = false; | 1132 | bool check_erased_page = false; |
1151 | 1133 | ||
1152 | if (page != denali->page) { | 1134 | if (page != denali->page) { |
1153 | dev_err(&denali->dev->dev, "IN %s: page %d is not" | 1135 | dev_err(denali->dev, "IN %s: page %d is not" |
1154 | " equal to denali->page %d, investigate!!", | 1136 | " equal to denali->page %d, investigate!!", |
1155 | __func__, page, denali->page); | 1137 | __func__, page, denali->page); |
1156 | BUG(); | 1138 | BUG(); |
@@ -1159,7 +1141,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1159 | setup_ecc_for_xfer(denali, true, false); | 1141 | setup_ecc_for_xfer(denali, true, false); |
1160 | 1142 | ||
1161 | denali_enable_dma(denali, true); | 1143 | denali_enable_dma(denali, true); |
1162 | pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_FROMDEVICE); | 1144 | dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE); |
1163 | 1145 | ||
1164 | clear_interrupts(denali); | 1146 | clear_interrupts(denali); |
1165 | denali_setup_dma(denali, DENALI_READ); | 1147 | denali_setup_dma(denali, DENALI_READ); |
@@ -1167,7 +1149,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1167 | /* wait for operation to complete */ | 1149 | /* wait for operation to complete */ |
1168 | irq_status = wait_for_irq(denali, irq_mask); | 1150 | irq_status = wait_for_irq(denali, irq_mask); |
1169 | 1151 | ||
1170 | pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE); | 1152 | dma_sync_single_for_cpu(denali->dev, addr, size, DMA_FROM_DEVICE); |
1171 | 1153 | ||
1172 | memcpy(buf, denali->buf.buf, mtd->writesize); | 1154 | memcpy(buf, denali->buf.buf, mtd->writesize); |
1173 | 1155 | ||
@@ -1192,16 +1174,15 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1192 | uint8_t *buf, int page) | 1174 | uint8_t *buf, int page) |
1193 | { | 1175 | { |
1194 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1176 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1195 | struct pci_dev *pci_dev = denali->dev; | ||
1196 | 1177 | ||
1197 | dma_addr_t addr = denali->buf.dma_buf; | 1178 | dma_addr_t addr = denali->buf.dma_buf; |
1198 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; | 1179 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; |
1199 | 1180 | ||
1200 | uint32_t irq_status = 0; | 1181 | uint32_t irq_status = 0; |
1201 | uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP; | 1182 | uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP; |
1202 | 1183 | ||
1203 | if (page != denali->page) { | 1184 | if (page != denali->page) { |
1204 | dev_err(&denali->dev->dev, "IN %s: page %d is not" | 1185 | dev_err(denali->dev, "IN %s: page %d is not" |
1205 | " equal to denali->page %d, investigate!!", | 1186 | " equal to denali->page %d, investigate!!", |
1206 | __func__, page, denali->page); | 1187 | __func__, page, denali->page); |
1207 | BUG(); | 1188 | BUG(); |
@@ -1210,7 +1191,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1210 | setup_ecc_for_xfer(denali, false, true); | 1191 | setup_ecc_for_xfer(denali, false, true); |
1211 | denali_enable_dma(denali, true); | 1192 | denali_enable_dma(denali, true); |
1212 | 1193 | ||
1213 | pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_FROMDEVICE); | 1194 | dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE); |
1214 | 1195 | ||
1215 | clear_interrupts(denali); | 1196 | clear_interrupts(denali); |
1216 | denali_setup_dma(denali, DENALI_READ); | 1197 | denali_setup_dma(denali, DENALI_READ); |
@@ -1218,7 +1199,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1218 | /* wait for operation to complete */ | 1199 | /* wait for operation to complete */ |
1219 | irq_status = wait_for_irq(denali, irq_mask); | 1200 | irq_status = wait_for_irq(denali, irq_mask); |
1220 | 1201 | ||
1221 | pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE); | 1202 | dma_sync_single_for_cpu(denali->dev, addr, size, DMA_FROM_DEVICE); |
1222 | 1203 | ||
1223 | denali_enable_dma(denali, false); | 1204 | denali_enable_dma(denali, false); |
1224 | 1205 | ||
@@ -1271,10 +1252,10 @@ static void denali_erase(struct mtd_info *mtd, int page) | |||
1271 | index_addr(denali, (uint32_t)cmd, 0x1); | 1252 | index_addr(denali, (uint32_t)cmd, 0x1); |
1272 | 1253 | ||
1273 | /* wait for erase to complete or failure to occur */ | 1254 | /* wait for erase to complete or failure to occur */ |
1274 | irq_status = wait_for_irq(denali, INTR_STATUS0__ERASE_COMP | | 1255 | irq_status = wait_for_irq(denali, INTR_STATUS__ERASE_COMP | |
1275 | INTR_STATUS0__ERASE_FAIL); | 1256 | INTR_STATUS__ERASE_FAIL); |
1276 | 1257 | ||
1277 | denali->status = (irq_status & INTR_STATUS0__ERASE_FAIL) ? | 1258 | denali->status = (irq_status & INTR_STATUS__ERASE_FAIL) ? |
1278 | NAND_STATUS_FAIL : PASS; | 1259 | NAND_STATUS_FAIL : PASS; |
1279 | } | 1260 | } |
1280 | 1261 | ||
@@ -1330,7 +1311,7 @@ static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, | |||
1330 | uint8_t *ecc_code) | 1311 | uint8_t *ecc_code) |
1331 | { | 1312 | { |
1332 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1313 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1333 | dev_err(&denali->dev->dev, | 1314 | dev_err(denali->dev, |
1334 | "denali_ecc_calculate called unexpectedly\n"); | 1315 | "denali_ecc_calculate called unexpectedly\n"); |
1335 | BUG(); | 1316 | BUG(); |
1336 | return -EIO; | 1317 | return -EIO; |
@@ -1340,7 +1321,7 @@ static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data, | |||
1340 | uint8_t *read_ecc, uint8_t *calc_ecc) | 1321 | uint8_t *read_ecc, uint8_t *calc_ecc) |
1341 | { | 1322 | { |
1342 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1323 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1343 | dev_err(&denali->dev->dev, | 1324 | dev_err(denali->dev, |
1344 | "denali_ecc_correct called unexpectedly\n"); | 1325 | "denali_ecc_correct called unexpectedly\n"); |
1345 | BUG(); | 1326 | BUG(); |
1346 | return -EIO; | 1327 | return -EIO; |
@@ -1349,7 +1330,7 @@ static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data, | |||
1349 | static void denali_ecc_hwctl(struct mtd_info *mtd, int mode) | 1330 | static void denali_ecc_hwctl(struct mtd_info *mtd, int mode) |
1350 | { | 1331 | { |
1351 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1332 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1352 | dev_err(&denali->dev->dev, | 1333 | dev_err(denali->dev, |
1353 | "denali_ecc_hwctl called unexpectedly\n"); | 1334 | "denali_ecc_hwctl called unexpectedly\n"); |
1354 | BUG(); | 1335 | BUG(); |
1355 | } | 1336 | } |
@@ -1375,6 +1356,7 @@ static void denali_hw_init(struct denali_nand_info *denali) | |||
1375 | /* Should set value for these registers when init */ | 1356 | /* Should set value for these registers when init */ |
1376 | iowrite32(0, denali->flash_reg + TWO_ROW_ADDR_CYCLES); | 1357 | iowrite32(0, denali->flash_reg + TWO_ROW_ADDR_CYCLES); |
1377 | iowrite32(1, denali->flash_reg + ECC_ENABLE); | 1358 | iowrite32(1, denali->flash_reg + ECC_ENABLE); |
1359 | detect_max_banks(denali); | ||
1378 | denali_nand_timing_set(denali); | 1360 | denali_nand_timing_set(denali); |
1379 | denali_irq_init(denali); | 1361 | denali_irq_init(denali); |
1380 | } | 1362 | } |
@@ -1484,24 +1466,22 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1484 | } | 1466 | } |
1485 | 1467 | ||
1486 | /* Is 32-bit DMA supported? */ | 1468 | /* Is 32-bit DMA supported? */ |
1487 | ret = pci_set_dma_mask(dev, DMA_BIT_MASK(32)); | 1469 | ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32)); |
1488 | |||
1489 | if (ret) { | 1470 | if (ret) { |
1490 | printk(KERN_ERR "Spectra: no usable DMA configuration\n"); | 1471 | printk(KERN_ERR "Spectra: no usable DMA configuration\n"); |
1491 | goto failed_enable_dev; | 1472 | goto failed_enable_dev; |
1492 | } | 1473 | } |
1493 | denali->buf.dma_buf = | 1474 | denali->buf.dma_buf = dma_map_single(&dev->dev, denali->buf.buf, |
1494 | pci_map_single(dev, denali->buf.buf, | 1475 | DENALI_BUF_SIZE, |
1495 | DENALI_BUF_SIZE, | 1476 | DMA_BIDIRECTIONAL); |
1496 | PCI_DMA_BIDIRECTIONAL); | ||
1497 | 1477 | ||
1498 | if (pci_dma_mapping_error(dev, denali->buf.dma_buf)) { | 1478 | if (dma_mapping_error(&dev->dev, denali->buf.dma_buf)) { |
1499 | dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n"); | 1479 | dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n"); |
1500 | goto failed_enable_dev; | 1480 | goto failed_enable_dev; |
1501 | } | 1481 | } |
1502 | 1482 | ||
1503 | pci_set_master(dev); | 1483 | pci_set_master(dev); |
1504 | denali->dev = dev; | 1484 | denali->dev = &dev->dev; |
1505 | denali->mtd.dev.parent = &dev->dev; | 1485 | denali->mtd.dev.parent = &dev->dev; |
1506 | 1486 | ||
1507 | ret = pci_request_regions(dev, DENALI_NAND_NAME); | 1487 | ret = pci_request_regions(dev, DENALI_NAND_NAME); |
@@ -1554,7 +1534,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1554 | /* scan for NAND devices attached to the controller | 1534 | /* scan for NAND devices attached to the controller |
1555 | * this is the first stage in a two step process to register | 1535 | * this is the first stage in a two step process to register |
1556 | * with the nand subsystem */ | 1536 | * with the nand subsystem */ |
1557 | if (nand_scan_ident(&denali->mtd, LLD_MAX_FLASH_BANKS, NULL)) { | 1537 | if (nand_scan_ident(&denali->mtd, denali->max_banks, NULL)) { |
1558 | ret = -ENXIO; | 1538 | ret = -ENXIO; |
1559 | goto failed_req_irq; | 1539 | goto failed_req_irq; |
1560 | } | 1540 | } |
@@ -1664,7 +1644,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1664 | goto failed_req_irq; | 1644 | goto failed_req_irq; |
1665 | } | 1645 | } |
1666 | 1646 | ||
1667 | ret = add_mtd_device(&denali->mtd); | 1647 | ret = mtd_device_register(&denali->mtd, NULL, 0); |
1668 | if (ret) { | 1648 | if (ret) { |
1669 | dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n", | 1649 | dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n", |
1670 | ret); | 1650 | ret); |
@@ -1681,8 +1661,8 @@ failed_remap_reg: | |||
1681 | failed_req_regions: | 1661 | failed_req_regions: |
1682 | pci_release_regions(dev); | 1662 | pci_release_regions(dev); |
1683 | failed_dma_map: | 1663 | failed_dma_map: |
1684 | pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | 1664 | dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE, |
1685 | PCI_DMA_BIDIRECTIONAL); | 1665 | DMA_BIDIRECTIONAL); |
1686 | failed_enable_dev: | 1666 | failed_enable_dev: |
1687 | pci_disable_device(dev); | 1667 | pci_disable_device(dev); |
1688 | failed_alloc_memery: | 1668 | failed_alloc_memery: |
@@ -1696,7 +1676,7 @@ static void denali_pci_remove(struct pci_dev *dev) | |||
1696 | struct denali_nand_info *denali = pci_get_drvdata(dev); | 1676 | struct denali_nand_info *denali = pci_get_drvdata(dev); |
1697 | 1677 | ||
1698 | nand_release(&denali->mtd); | 1678 | nand_release(&denali->mtd); |
1699 | del_mtd_device(&denali->mtd); | 1679 | mtd_device_unregister(&denali->mtd); |
1700 | 1680 | ||
1701 | denali_irq_cleanup(dev->irq, denali); | 1681 | denali_irq_cleanup(dev->irq, denali); |
1702 | 1682 | ||
@@ -1704,8 +1684,8 @@ static void denali_pci_remove(struct pci_dev *dev) | |||
1704 | iounmap(denali->flash_mem); | 1684 | iounmap(denali->flash_mem); |
1705 | pci_release_regions(dev); | 1685 | pci_release_regions(dev); |
1706 | pci_disable_device(dev); | 1686 | pci_disable_device(dev); |
1707 | pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | 1687 | dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE, |
1708 | PCI_DMA_BIDIRECTIONAL); | 1688 | DMA_BIDIRECTIONAL); |
1709 | pci_set_drvdata(dev, NULL); | 1689 | pci_set_drvdata(dev, NULL); |
1710 | kfree(denali); | 1690 | kfree(denali); |
1711 | } | 1691 | } |
@@ -1721,8 +1701,7 @@ static struct pci_driver denali_pci_driver = { | |||
1721 | 1701 | ||
1722 | static int __devinit denali_init(void) | 1702 | static int __devinit denali_init(void) |
1723 | { | 1703 | { |
1724 | printk(KERN_INFO "Spectra MTD driver built on %s @ %s\n", | 1704 | printk(KERN_INFO "Spectra MTD driver\n"); |
1725 | __DATE__, __TIME__); | ||
1726 | return pci_register_driver(&denali_pci_driver); | 1705 | return pci_register_driver(&denali_pci_driver); |
1727 | } | 1706 | } |
1728 | 1707 | ||
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 3918bcb1561e..fabb9d56b39e 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h | |||
@@ -211,185 +211,46 @@ | |||
211 | #define TRANSFER_MODE 0x400 | 211 | #define TRANSFER_MODE 0x400 |
212 | #define TRANSFER_MODE__VALUE 0x0003 | 212 | #define TRANSFER_MODE__VALUE 0x0003 |
213 | 213 | ||
214 | #define INTR_STATUS0 0x410 | 214 | #define INTR_STATUS(__bank) (0x410 + ((__bank) * 0x50)) |
215 | #define INTR_STATUS0__ECC_TRANSACTION_DONE 0x0001 | 215 | #define INTR_EN(__bank) (0x420 + ((__bank) * 0x50)) |
216 | #define INTR_STATUS0__ECC_ERR 0x0002 | 216 | |
217 | #define INTR_STATUS0__DMA_CMD_COMP 0x0004 | 217 | #define INTR_STATUS__ECC_TRANSACTION_DONE 0x0001 |
218 | #define INTR_STATUS0__TIME_OUT 0x0008 | 218 | #define INTR_STATUS__ECC_ERR 0x0002 |
219 | #define INTR_STATUS0__PROGRAM_FAIL 0x0010 | 219 | #define INTR_STATUS__DMA_CMD_COMP 0x0004 |
220 | #define INTR_STATUS0__ERASE_FAIL 0x0020 | 220 | #define INTR_STATUS__TIME_OUT 0x0008 |
221 | #define INTR_STATUS0__LOAD_COMP 0x0040 | 221 | #define INTR_STATUS__PROGRAM_FAIL 0x0010 |
222 | #define INTR_STATUS0__PROGRAM_COMP 0x0080 | 222 | #define INTR_STATUS__ERASE_FAIL 0x0020 |
223 | #define INTR_STATUS0__ERASE_COMP 0x0100 | 223 | #define INTR_STATUS__LOAD_COMP 0x0040 |
224 | #define INTR_STATUS0__PIPE_CPYBCK_CMD_COMP 0x0200 | 224 | #define INTR_STATUS__PROGRAM_COMP 0x0080 |
225 | #define INTR_STATUS0__LOCKED_BLK 0x0400 | 225 | #define INTR_STATUS__ERASE_COMP 0x0100 |
226 | #define INTR_STATUS0__UNSUP_CMD 0x0800 | 226 | #define INTR_STATUS__PIPE_CPYBCK_CMD_COMP 0x0200 |
227 | #define INTR_STATUS0__INT_ACT 0x1000 | 227 | #define INTR_STATUS__LOCKED_BLK 0x0400 |
228 | #define INTR_STATUS0__RST_COMP 0x2000 | 228 | #define INTR_STATUS__UNSUP_CMD 0x0800 |
229 | #define INTR_STATUS0__PIPE_CMD_ERR 0x4000 | 229 | #define INTR_STATUS__INT_ACT 0x1000 |
230 | #define INTR_STATUS0__PAGE_XFER_INC 0x8000 | 230 | #define INTR_STATUS__RST_COMP 0x2000 |
231 | 231 | #define INTR_STATUS__PIPE_CMD_ERR 0x4000 | |
232 | #define INTR_EN0 0x420 | 232 | #define INTR_STATUS__PAGE_XFER_INC 0x8000 |
233 | #define INTR_EN0__ECC_TRANSACTION_DONE 0x0001 | 233 | |
234 | #define INTR_EN0__ECC_ERR 0x0002 | 234 | #define INTR_EN__ECC_TRANSACTION_DONE 0x0001 |
235 | #define INTR_EN0__DMA_CMD_COMP 0x0004 | 235 | #define INTR_EN__ECC_ERR 0x0002 |
236 | #define INTR_EN0__TIME_OUT 0x0008 | 236 | #define INTR_EN__DMA_CMD_COMP 0x0004 |
237 | #define INTR_EN0__PROGRAM_FAIL 0x0010 | 237 | #define INTR_EN__TIME_OUT 0x0008 |
238 | #define INTR_EN0__ERASE_FAIL 0x0020 | 238 | #define INTR_EN__PROGRAM_FAIL 0x0010 |
239 | #define INTR_EN0__LOAD_COMP 0x0040 | 239 | #define INTR_EN__ERASE_FAIL 0x0020 |
240 | #define INTR_EN0__PROGRAM_COMP 0x0080 | 240 | #define INTR_EN__LOAD_COMP 0x0040 |
241 | #define INTR_EN0__ERASE_COMP 0x0100 | 241 | #define INTR_EN__PROGRAM_COMP 0x0080 |
242 | #define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200 | 242 | #define INTR_EN__ERASE_COMP 0x0100 |
243 | #define INTR_EN0__LOCKED_BLK 0x0400 | 243 | #define INTR_EN__PIPE_CPYBCK_CMD_COMP 0x0200 |
244 | #define INTR_EN0__UNSUP_CMD 0x0800 | 244 | #define INTR_EN__LOCKED_BLK 0x0400 |
245 | #define INTR_EN0__INT_ACT 0x1000 | 245 | #define INTR_EN__UNSUP_CMD 0x0800 |
246 | #define INTR_EN0__RST_COMP 0x2000 | 246 | #define INTR_EN__INT_ACT 0x1000 |
247 | #define INTR_EN0__PIPE_CMD_ERR 0x4000 | 247 | #define INTR_EN__RST_COMP 0x2000 |
248 | #define INTR_EN0__PAGE_XFER_INC 0x8000 | 248 | #define INTR_EN__PIPE_CMD_ERR 0x4000 |
249 | 249 | #define INTR_EN__PAGE_XFER_INC 0x8000 | |
250 | #define PAGE_CNT0 0x430 | 250 | |
251 | #define PAGE_CNT0__VALUE 0x00ff | 251 | #define PAGE_CNT(__bank) (0x430 + ((__bank) * 0x50)) |
252 | 252 | #define ERR_PAGE_ADDR(__bank) (0x440 + ((__bank) * 0x50)) | |
253 | #define ERR_PAGE_ADDR0 0x440 | 253 | #define ERR_BLOCK_ADDR(__bank) (0x450 + ((__bank) * 0x50)) |
254 | #define ERR_PAGE_ADDR0__VALUE 0xffff | ||
255 | |||
256 | #define ERR_BLOCK_ADDR0 0x450 | ||
257 | #define ERR_BLOCK_ADDR0__VALUE 0xffff | ||
258 | |||
259 | #define INTR_STATUS1 0x460 | ||
260 | #define INTR_STATUS1__ECC_TRANSACTION_DONE 0x0001 | ||
261 | #define INTR_STATUS1__ECC_ERR 0x0002 | ||
262 | #define INTR_STATUS1__DMA_CMD_COMP 0x0004 | ||
263 | #define INTR_STATUS1__TIME_OUT 0x0008 | ||
264 | #define INTR_STATUS1__PROGRAM_FAIL 0x0010 | ||
265 | #define INTR_STATUS1__ERASE_FAIL 0x0020 | ||
266 | #define INTR_STATUS1__LOAD_COMP 0x0040 | ||
267 | #define INTR_STATUS1__PROGRAM_COMP 0x0080 | ||
268 | #define INTR_STATUS1__ERASE_COMP 0x0100 | ||
269 | #define INTR_STATUS1__PIPE_CPYBCK_CMD_COMP 0x0200 | ||
270 | #define INTR_STATUS1__LOCKED_BLK 0x0400 | ||
271 | #define INTR_STATUS1__UNSUP_CMD 0x0800 | ||
272 | #define INTR_STATUS1__INT_ACT 0x1000 | ||
273 | #define INTR_STATUS1__RST_COMP 0x2000 | ||
274 | #define INTR_STATUS1__PIPE_CMD_ERR 0x4000 | ||
275 | #define INTR_STATUS1__PAGE_XFER_INC 0x8000 | ||
276 | |||
277 | #define INTR_EN1 0x470 | ||
278 | #define INTR_EN1__ECC_TRANSACTION_DONE 0x0001 | ||
279 | #define INTR_EN1__ECC_ERR 0x0002 | ||
280 | #define INTR_EN1__DMA_CMD_COMP 0x0004 | ||
281 | #define INTR_EN1__TIME_OUT 0x0008 | ||
282 | #define INTR_EN1__PROGRAM_FAIL 0x0010 | ||
283 | #define INTR_EN1__ERASE_FAIL 0x0020 | ||
284 | #define INTR_EN1__LOAD_COMP 0x0040 | ||
285 | #define INTR_EN1__PROGRAM_COMP 0x0080 | ||
286 | #define INTR_EN1__ERASE_COMP 0x0100 | ||
287 | #define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200 | ||
288 | #define INTR_EN1__LOCKED_BLK 0x0400 | ||
289 | #define INTR_EN1__UNSUP_CMD 0x0800 | ||
290 | #define INTR_EN1__INT_ACT 0x1000 | ||
291 | #define INTR_EN1__RST_COMP 0x2000 | ||
292 | #define INTR_EN1__PIPE_CMD_ERR 0x4000 | ||
293 | #define INTR_EN1__PAGE_XFER_INC 0x8000 | ||
294 | |||
295 | #define PAGE_CNT1 0x480 | ||
296 | #define PAGE_CNT1__VALUE 0x00ff | ||
297 | |||
298 | #define ERR_PAGE_ADDR1 0x490 | ||
299 | #define ERR_PAGE_ADDR1__VALUE 0xffff | ||
300 | |||
301 | #define ERR_BLOCK_ADDR1 0x4a0 | ||
302 | #define ERR_BLOCK_ADDR1__VALUE 0xffff | ||
303 | |||
304 | #define INTR_STATUS2 0x4b0 | ||
305 | #define INTR_STATUS2__ECC_TRANSACTION_DONE 0x0001 | ||
306 | #define INTR_STATUS2__ECC_ERR 0x0002 | ||
307 | #define INTR_STATUS2__DMA_CMD_COMP 0x0004 | ||
308 | #define INTR_STATUS2__TIME_OUT 0x0008 | ||
309 | #define INTR_STATUS2__PROGRAM_FAIL 0x0010 | ||
310 | #define INTR_STATUS2__ERASE_FAIL 0x0020 | ||
311 | #define INTR_STATUS2__LOAD_COMP 0x0040 | ||
312 | #define INTR_STATUS2__PROGRAM_COMP 0x0080 | ||
313 | #define INTR_STATUS2__ERASE_COMP 0x0100 | ||
314 | #define INTR_STATUS2__PIPE_CPYBCK_CMD_COMP 0x0200 | ||
315 | #define INTR_STATUS2__LOCKED_BLK 0x0400 | ||
316 | #define INTR_STATUS2__UNSUP_CMD 0x0800 | ||
317 | #define INTR_STATUS2__INT_ACT 0x1000 | ||
318 | #define INTR_STATUS2__RST_COMP 0x2000 | ||
319 | #define INTR_STATUS2__PIPE_CMD_ERR 0x4000 | ||
320 | #define INTR_STATUS2__PAGE_XFER_INC 0x8000 | ||
321 | |||
322 | #define INTR_EN2 0x4c0 | ||
323 | #define INTR_EN2__ECC_TRANSACTION_DONE 0x0001 | ||
324 | #define INTR_EN2__ECC_ERR 0x0002 | ||
325 | #define INTR_EN2__DMA_CMD_COMP 0x0004 | ||
326 | #define INTR_EN2__TIME_OUT 0x0008 | ||
327 | #define INTR_EN2__PROGRAM_FAIL 0x0010 | ||
328 | #define INTR_EN2__ERASE_FAIL 0x0020 | ||
329 | #define INTR_EN2__LOAD_COMP 0x0040 | ||
330 | #define INTR_EN2__PROGRAM_COMP 0x0080 | ||
331 | #define INTR_EN2__ERASE_COMP 0x0100 | ||
332 | #define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200 | ||
333 | #define INTR_EN2__LOCKED_BLK 0x0400 | ||
334 | #define INTR_EN2__UNSUP_CMD 0x0800 | ||
335 | #define INTR_EN2__INT_ACT 0x1000 | ||
336 | #define INTR_EN2__RST_COMP 0x2000 | ||
337 | #define INTR_EN2__PIPE_CMD_ERR 0x4000 | ||
338 | #define INTR_EN2__PAGE_XFER_INC 0x8000 | ||
339 | |||
340 | #define PAGE_CNT2 0x4d0 | ||
341 | #define PAGE_CNT2__VALUE 0x00ff | ||
342 | |||
343 | #define ERR_PAGE_ADDR2 0x4e0 | ||
344 | #define ERR_PAGE_ADDR2__VALUE 0xffff | ||
345 | |||
346 | #define ERR_BLOCK_ADDR2 0x4f0 | ||
347 | #define ERR_BLOCK_ADDR2__VALUE 0xffff | ||
348 | |||
349 | #define INTR_STATUS3 0x500 | ||
350 | #define INTR_STATUS3__ECC_TRANSACTION_DONE 0x0001 | ||
351 | #define INTR_STATUS3__ECC_ERR 0x0002 | ||
352 | #define INTR_STATUS3__DMA_CMD_COMP 0x0004 | ||
353 | #define INTR_STATUS3__TIME_OUT 0x0008 | ||
354 | #define INTR_STATUS3__PROGRAM_FAIL 0x0010 | ||
355 | #define INTR_STATUS3__ERASE_FAIL 0x0020 | ||
356 | #define INTR_STATUS3__LOAD_COMP 0x0040 | ||
357 | #define INTR_STATUS3__PROGRAM_COMP 0x0080 | ||
358 | #define INTR_STATUS3__ERASE_COMP 0x0100 | ||
359 | #define INTR_STATUS3__PIPE_CPYBCK_CMD_COMP 0x0200 | ||
360 | #define INTR_STATUS3__LOCKED_BLK 0x0400 | ||
361 | #define INTR_STATUS3__UNSUP_CMD 0x0800 | ||
362 | #define INTR_STATUS3__INT_ACT 0x1000 | ||
363 | #define INTR_STATUS3__RST_COMP 0x2000 | ||
364 | #define INTR_STATUS3__PIPE_CMD_ERR 0x4000 | ||
365 | #define INTR_STATUS3__PAGE_XFER_INC 0x8000 | ||
366 | |||
367 | #define INTR_EN3 0x510 | ||
368 | #define INTR_EN3__ECC_TRANSACTION_DONE 0x0001 | ||
369 | #define INTR_EN3__ECC_ERR 0x0002 | ||
370 | #define INTR_EN3__DMA_CMD_COMP 0x0004 | ||
371 | #define INTR_EN3__TIME_OUT 0x0008 | ||
372 | #define INTR_EN3__PROGRAM_FAIL 0x0010 | ||
373 | #define INTR_EN3__ERASE_FAIL 0x0020 | ||
374 | #define INTR_EN3__LOAD_COMP 0x0040 | ||
375 | #define INTR_EN3__PROGRAM_COMP 0x0080 | ||
376 | #define INTR_EN3__ERASE_COMP 0x0100 | ||
377 | #define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200 | ||
378 | #define INTR_EN3__LOCKED_BLK 0x0400 | ||
379 | #define INTR_EN3__UNSUP_CMD 0x0800 | ||
380 | #define INTR_EN3__INT_ACT 0x1000 | ||
381 | #define INTR_EN3__RST_COMP 0x2000 | ||
382 | #define INTR_EN3__PIPE_CMD_ERR 0x4000 | ||
383 | #define INTR_EN3__PAGE_XFER_INC 0x8000 | ||
384 | |||
385 | #define PAGE_CNT3 0x520 | ||
386 | #define PAGE_CNT3__VALUE 0x00ff | ||
387 | |||
388 | #define ERR_PAGE_ADDR3 0x530 | ||
389 | #define ERR_PAGE_ADDR3__VALUE 0xffff | ||
390 | |||
391 | #define ERR_BLOCK_ADDR3 0x540 | ||
392 | #define ERR_BLOCK_ADDR3__VALUE 0xffff | ||
393 | 254 | ||
394 | #define DATA_INTR 0x550 | 255 | #define DATA_INTR 0x550 |
395 | #define DATA_INTR__WRITE_SPACE_AV 0x0001 | 256 | #define DATA_INTR__WRITE_SPACE_AV 0x0001 |
@@ -484,141 +345,23 @@ | |||
484 | #define PTN_INTR_EN__ACCESS_ERROR_BANK3 0x0010 | 345 | #define PTN_INTR_EN__ACCESS_ERROR_BANK3 0x0010 |
485 | #define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020 | 346 | #define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020 |
486 | 347 | ||
487 | #define PERM_SRC_ID_0 0x830 | 348 | #define PERM_SRC_ID(__bank) (0x830 + ((__bank) * 0x40)) |
488 | #define PERM_SRC_ID_0__SRCID 0x00ff | 349 | #define PERM_SRC_ID__SRCID 0x00ff |
489 | #define PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE 0x0800 | 350 | #define PERM_SRC_ID__DIRECT_ACCESS_ACTIVE 0x0800 |
490 | #define PERM_SRC_ID_0__WRITE_ACTIVE 0x2000 | 351 | #define PERM_SRC_ID__WRITE_ACTIVE 0x2000 |
491 | #define PERM_SRC_ID_0__READ_ACTIVE 0x4000 | 352 | #define PERM_SRC_ID__READ_ACTIVE 0x4000 |
492 | #define PERM_SRC_ID_0__PARTITION_VALID 0x8000 | 353 | #define PERM_SRC_ID__PARTITION_VALID 0x8000 |
493 | 354 | ||
494 | #define MIN_BLK_ADDR_0 0x840 | 355 | #define MIN_BLK_ADDR(__bank) (0x840 + ((__bank) * 0x40)) |
495 | #define MIN_BLK_ADDR_0__VALUE 0xffff | 356 | #define MIN_BLK_ADDR__VALUE 0xffff |
496 | 357 | ||
497 | #define MAX_BLK_ADDR_0 0x850 | 358 | #define MAX_BLK_ADDR(__bank) (0x850 + ((__bank) * 0x40)) |
498 | #define MAX_BLK_ADDR_0__VALUE 0xffff | 359 | #define MAX_BLK_ADDR__VALUE 0xffff |
499 | 360 | ||
500 | #define MIN_MAX_BANK_0 0x860 | 361 | #define MIN_MAX_BANK(__bank) (0x860 + ((__bank) * 0x40)) |
501 | #define MIN_MAX_BANK_0__MIN_VALUE 0x0003 | 362 | #define MIN_MAX_BANK__MIN_VALUE 0x0003 |
502 | #define MIN_MAX_BANK_0__MAX_VALUE 0x000c | 363 | #define MIN_MAX_BANK__MAX_VALUE 0x000c |
503 | |||
504 | #define PERM_SRC_ID_1 0x870 | ||
505 | #define PERM_SRC_ID_1__SRCID 0x00ff | ||
506 | #define PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE 0x0800 | ||
507 | #define PERM_SRC_ID_1__WRITE_ACTIVE 0x2000 | ||
508 | #define PERM_SRC_ID_1__READ_ACTIVE 0x4000 | ||
509 | #define PERM_SRC_ID_1__PARTITION_VALID 0x8000 | ||
510 | |||
511 | #define MIN_BLK_ADDR_1 0x880 | ||
512 | #define MIN_BLK_ADDR_1__VALUE 0xffff | ||
513 | |||
514 | #define MAX_BLK_ADDR_1 0x890 | ||
515 | #define MAX_BLK_ADDR_1__VALUE 0xffff | ||
516 | |||
517 | #define MIN_MAX_BANK_1 0x8a0 | ||
518 | #define MIN_MAX_BANK_1__MIN_VALUE 0x0003 | ||
519 | #define MIN_MAX_BANK_1__MAX_VALUE 0x000c | ||
520 | |||
521 | #define PERM_SRC_ID_2 0x8b0 | ||
522 | #define PERM_SRC_ID_2__SRCID 0x00ff | ||
523 | #define PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE 0x0800 | ||
524 | #define PERM_SRC_ID_2__WRITE_ACTIVE 0x2000 | ||
525 | #define PERM_SRC_ID_2__READ_ACTIVE 0x4000 | ||
526 | #define PERM_SRC_ID_2__PARTITION_VALID 0x8000 | ||
527 | |||
528 | #define MIN_BLK_ADDR_2 0x8c0 | ||
529 | #define MIN_BLK_ADDR_2__VALUE 0xffff | ||
530 | |||
531 | #define MAX_BLK_ADDR_2 0x8d0 | ||
532 | #define MAX_BLK_ADDR_2__VALUE 0xffff | ||
533 | |||
534 | #define MIN_MAX_BANK_2 0x8e0 | ||
535 | #define MIN_MAX_BANK_2__MIN_VALUE 0x0003 | ||
536 | #define MIN_MAX_BANK_2__MAX_VALUE 0x000c | ||
537 | |||
538 | #define PERM_SRC_ID_3 0x8f0 | ||
539 | #define PERM_SRC_ID_3__SRCID 0x00ff | ||
540 | #define PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE 0x0800 | ||
541 | #define PERM_SRC_ID_3__WRITE_ACTIVE 0x2000 | ||
542 | #define PERM_SRC_ID_3__READ_ACTIVE 0x4000 | ||
543 | #define PERM_SRC_ID_3__PARTITION_VALID 0x8000 | ||
544 | |||
545 | #define MIN_BLK_ADDR_3 0x900 | ||
546 | #define MIN_BLK_ADDR_3__VALUE 0xffff | ||
547 | |||
548 | #define MAX_BLK_ADDR_3 0x910 | ||
549 | #define MAX_BLK_ADDR_3__VALUE 0xffff | ||
550 | |||
551 | #define MIN_MAX_BANK_3 0x920 | ||
552 | #define MIN_MAX_BANK_3__MIN_VALUE 0x0003 | ||
553 | #define MIN_MAX_BANK_3__MAX_VALUE 0x000c | ||
554 | |||
555 | #define PERM_SRC_ID_4 0x930 | ||
556 | #define PERM_SRC_ID_4__SRCID 0x00ff | ||
557 | #define PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE 0x0800 | ||
558 | #define PERM_SRC_ID_4__WRITE_ACTIVE 0x2000 | ||
559 | #define PERM_SRC_ID_4__READ_ACTIVE 0x4000 | ||
560 | #define PERM_SRC_ID_4__PARTITION_VALID 0x8000 | ||
561 | |||
562 | #define MIN_BLK_ADDR_4 0x940 | ||
563 | #define MIN_BLK_ADDR_4__VALUE 0xffff | ||
564 | |||
565 | #define MAX_BLK_ADDR_4 0x950 | ||
566 | #define MAX_BLK_ADDR_4__VALUE 0xffff | ||
567 | |||
568 | #define MIN_MAX_BANK_4 0x960 | ||
569 | #define MIN_MAX_BANK_4__MIN_VALUE 0x0003 | ||
570 | #define MIN_MAX_BANK_4__MAX_VALUE 0x000c | ||
571 | |||
572 | #define PERM_SRC_ID_5 0x970 | ||
573 | #define PERM_SRC_ID_5__SRCID 0x00ff | ||
574 | #define PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE 0x0800 | ||
575 | #define PERM_SRC_ID_5__WRITE_ACTIVE 0x2000 | ||
576 | #define PERM_SRC_ID_5__READ_ACTIVE 0x4000 | ||
577 | #define PERM_SRC_ID_5__PARTITION_VALID 0x8000 | ||
578 | |||
579 | #define MIN_BLK_ADDR_5 0x980 | ||
580 | #define MIN_BLK_ADDR_5__VALUE 0xffff | ||
581 | |||
582 | #define MAX_BLK_ADDR_5 0x990 | ||
583 | #define MAX_BLK_ADDR_5__VALUE 0xffff | ||
584 | |||
585 | #define MIN_MAX_BANK_5 0x9a0 | ||
586 | #define MIN_MAX_BANK_5__MIN_VALUE 0x0003 | ||
587 | #define MIN_MAX_BANK_5__MAX_VALUE 0x000c | ||
588 | |||
589 | #define PERM_SRC_ID_6 0x9b0 | ||
590 | #define PERM_SRC_ID_6__SRCID 0x00ff | ||
591 | #define PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE 0x0800 | ||
592 | #define PERM_SRC_ID_6__WRITE_ACTIVE 0x2000 | ||
593 | #define PERM_SRC_ID_6__READ_ACTIVE 0x4000 | ||
594 | #define PERM_SRC_ID_6__PARTITION_VALID 0x8000 | ||
595 | |||
596 | #define MIN_BLK_ADDR_6 0x9c0 | ||
597 | #define MIN_BLK_ADDR_6__VALUE 0xffff | ||
598 | |||
599 | #define MAX_BLK_ADDR_6 0x9d0 | ||
600 | #define MAX_BLK_ADDR_6__VALUE 0xffff | ||
601 | |||
602 | #define MIN_MAX_BANK_6 0x9e0 | ||
603 | #define MIN_MAX_BANK_6__MIN_VALUE 0x0003 | ||
604 | #define MIN_MAX_BANK_6__MAX_VALUE 0x000c | ||
605 | |||
606 | #define PERM_SRC_ID_7 0x9f0 | ||
607 | #define PERM_SRC_ID_7__SRCID 0x00ff | ||
608 | #define PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE 0x0800 | ||
609 | #define PERM_SRC_ID_7__WRITE_ACTIVE 0x2000 | ||
610 | #define PERM_SRC_ID_7__READ_ACTIVE 0x4000 | ||
611 | #define PERM_SRC_ID_7__PARTITION_VALID 0x8000 | ||
612 | 364 | ||
613 | #define MIN_BLK_ADDR_7 0xa00 | ||
614 | #define MIN_BLK_ADDR_7__VALUE 0xffff | ||
615 | |||
616 | #define MAX_BLK_ADDR_7 0xa10 | ||
617 | #define MAX_BLK_ADDR_7__VALUE 0xffff | ||
618 | |||
619 | #define MIN_MAX_BANK_7 0xa20 | ||
620 | #define MIN_MAX_BANK_7__MIN_VALUE 0x0003 | ||
621 | #define MIN_MAX_BANK_7__MAX_VALUE 0x000c | ||
622 | 365 | ||
623 | /* ffsdefs.h */ | 366 | /* ffsdefs.h */ |
624 | #define CLEAR 0 /*use this to clear a field instead of "fail"*/ | 367 | #define CLEAR 0 /*use this to clear a field instead of "fail"*/ |
@@ -711,7 +454,6 @@ | |||
711 | #define READ_WRITE_ENABLE_HIGH_COUNT 22 | 454 | #define READ_WRITE_ENABLE_HIGH_COUNT 22 |
712 | 455 | ||
713 | #define ECC_SECTOR_SIZE 512 | 456 | #define ECC_SECTOR_SIZE 512 |
714 | #define LLD_MAX_FLASH_BANKS 4 | ||
715 | 457 | ||
716 | #define DENALI_BUF_SIZE (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) | 458 | #define DENALI_BUF_SIZE (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) |
717 | 459 | ||
@@ -732,7 +474,7 @@ struct denali_nand_info { | |||
732 | int status; | 474 | int status; |
733 | int platform; | 475 | int platform; |
734 | struct nand_buf buf; | 476 | struct nand_buf buf; |
735 | struct pci_dev *dev; | 477 | struct device *dev; |
736 | int total_used_banks; | 478 | int total_used_banks; |
737 | uint32_t block; /* stored for future use */ | 479 | uint32_t block; /* stored for future use */ |
738 | uint16_t page; | 480 | uint16_t page; |
@@ -751,6 +493,7 @@ struct denali_nand_info { | |||
751 | uint32_t totalblks; | 493 | uint32_t totalblks; |
752 | uint32_t blksperchip; | 494 | uint32_t blksperchip; |
753 | uint32_t bbtskipbytes; | 495 | uint32_t bbtskipbytes; |
496 | uint32_t max_banks; | ||
754 | }; | 497 | }; |
755 | 498 | ||
756 | #endif /*_LLD_NAND_*/ | 499 | #endif /*_LLD_NAND_*/ |
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 657b9f4b6f9b..7837728d02ff 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -1360,11 +1360,9 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd) | |||
1360 | At least as nand_bbt.c is currently written. */ | 1360 | At least as nand_bbt.c is currently written. */ |
1361 | if ((ret = nand_scan_bbt(mtd, NULL))) | 1361 | if ((ret = nand_scan_bbt(mtd, NULL))) |
1362 | return ret; | 1362 | return ret; |
1363 | add_mtd_device(mtd); | 1363 | mtd_device_register(mtd, NULL, 0); |
1364 | #ifdef CONFIG_MTD_PARTITIONS | ||
1365 | if (!no_autopart) | 1364 | if (!no_autopart) |
1366 | add_mtd_partitions(mtd, parts, numparts); | 1365 | mtd_device_register(mtd, parts, numparts); |
1367 | #endif | ||
1368 | return 0; | 1366 | return 0; |
1369 | } | 1367 | } |
1370 | 1368 | ||
@@ -1419,11 +1417,9 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) | |||
1419 | autopartitioning, but I want to give it more thought. */ | 1417 | autopartitioning, but I want to give it more thought. */ |
1420 | if (!numparts) | 1418 | if (!numparts) |
1421 | return -EIO; | 1419 | return -EIO; |
1422 | add_mtd_device(mtd); | 1420 | mtd_device_register(mtd, NULL, 0); |
1423 | #ifdef CONFIG_MTD_PARTITIONS | ||
1424 | if (!no_autopart) | 1421 | if (!no_autopart) |
1425 | add_mtd_partitions(mtd, parts, numparts); | 1422 | mtd_device_register(mtd, parts, numparts); |
1426 | #endif | ||
1427 | return 0; | 1423 | return 0; |
1428 | } | 1424 | } |
1429 | 1425 | ||
@@ -1678,9 +1674,9 @@ static int __init doc_probe(unsigned long physadr) | |||
1678 | /* DBB note: i believe nand_release is necessary here, as | 1674 | /* DBB note: i believe nand_release is necessary here, as |
1679 | buffers may have been allocated in nand_base. Check with | 1675 | buffers may have been allocated in nand_base. Check with |
1680 | Thomas. FIX ME! */ | 1676 | Thomas. FIX ME! */ |
1681 | /* nand_release will call del_mtd_device, but we haven't yet | 1677 | /* nand_release will call mtd_device_unregister, but we |
1682 | added it. This is handled without incident by | 1678 | haven't yet added it. This is handled without incident by |
1683 | del_mtd_device, as far as I can tell. */ | 1679 | mtd_device_unregister, as far as I can tell. */ |
1684 | nand_release(mtd); | 1680 | nand_release(mtd); |
1685 | kfree(mtd); | 1681 | kfree(mtd); |
1686 | goto fail; | 1682 | goto fail; |
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c index 86366bfba9f8..8400d0f6dada 100644 --- a/drivers/mtd/nand/edb7312.c +++ b/drivers/mtd/nand/edb7312.c | |||
@@ -55,7 +55,6 @@ static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE; | |||
55 | static void __iomem *ep7312_pxdr = (void __iomem *)EP7312_PXDR; | 55 | static void __iomem *ep7312_pxdr = (void __iomem *)EP7312_PXDR; |
56 | static void __iomem *ep7312_pxddr = (void __iomem *)EP7312_PXDDR; | 56 | static void __iomem *ep7312_pxddr = (void __iomem *)EP7312_PXDDR; |
57 | 57 | ||
58 | #ifdef CONFIG_MTD_PARTITIONS | ||
59 | /* | 58 | /* |
60 | * Define static partitions for flash device | 59 | * Define static partitions for flash device |
61 | */ | 60 | */ |
@@ -67,8 +66,6 @@ static struct mtd_partition partition_info[] = { | |||
67 | 66 | ||
68 | #define NUM_PARTITIONS 1 | 67 | #define NUM_PARTITIONS 1 |
69 | 68 | ||
70 | #endif | ||
71 | |||
72 | /* | 69 | /* |
73 | * hardware specific access to control-lines | 70 | * hardware specific access to control-lines |
74 | * | 71 | * |
@@ -101,9 +98,7 @@ static int ep7312_device_ready(struct mtd_info *mtd) | |||
101 | return 1; | 98 | return 1; |
102 | } | 99 | } |
103 | 100 | ||
104 | #ifdef CONFIG_MTD_PARTITIONS | ||
105 | const char *part_probes[] = { "cmdlinepart", NULL }; | 101 | const char *part_probes[] = { "cmdlinepart", NULL }; |
106 | #endif | ||
107 | 102 | ||
108 | /* | 103 | /* |
109 | * Main initialization routine | 104 | * Main initialization routine |
@@ -162,14 +157,12 @@ static int __init ep7312_init(void) | |||
162 | kfree(ep7312_mtd); | 157 | kfree(ep7312_mtd); |
163 | return -ENXIO; | 158 | return -ENXIO; |
164 | } | 159 | } |
165 | #ifdef CONFIG_MTD_PARTITIONS | ||
166 | ep7312_mtd->name = "edb7312-nand"; | 160 | ep7312_mtd->name = "edb7312-nand"; |
167 | mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0); | 161 | mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0); |
168 | if (mtd_parts_nb > 0) | 162 | if (mtd_parts_nb > 0) |
169 | part_type = "command line"; | 163 | part_type = "command line"; |
170 | else | 164 | else |
171 | mtd_parts_nb = 0; | 165 | mtd_parts_nb = 0; |
172 | #endif | ||
173 | if (mtd_parts_nb == 0) { | 166 | if (mtd_parts_nb == 0) { |
174 | mtd_parts = partition_info; | 167 | mtd_parts = partition_info; |
175 | mtd_parts_nb = NUM_PARTITIONS; | 168 | mtd_parts_nb = NUM_PARTITIONS; |
@@ -178,7 +171,7 @@ static int __init ep7312_init(void) | |||
178 | 171 | ||
179 | /* Register the partitions */ | 172 | /* Register the partitions */ |
180 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | 173 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); |
181 | add_mtd_partitions(ep7312_mtd, mtd_parts, mtd_parts_nb); | 174 | mtd_device_register(ep7312_mtd, mtd_parts, mtd_parts_nb); |
182 | 175 | ||
183 | /* Return happy */ | 176 | /* Return happy */ |
184 | return 0; | 177 | return 0; |
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 537e380b8dcb..0bb254c7d2b1 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
@@ -841,12 +841,9 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev) | |||
841 | struct fsl_elbc_mtd *priv; | 841 | struct fsl_elbc_mtd *priv; |
842 | struct resource res; | 842 | struct resource res; |
843 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl; | 843 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl; |
844 | |||
845 | #ifdef CONFIG_MTD_PARTITIONS | ||
846 | static const char *part_probe_types[] | 844 | static const char *part_probe_types[] |
847 | = { "cmdlinepart", "RedBoot", NULL }; | 845 | = { "cmdlinepart", "RedBoot", NULL }; |
848 | struct mtd_partition *parts; | 846 | struct mtd_partition *parts; |
849 | #endif | ||
850 | int ret; | 847 | int ret; |
851 | int bank; | 848 | int bank; |
852 | struct device *dev; | 849 | struct device *dev; |
@@ -935,26 +932,19 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev) | |||
935 | if (ret) | 932 | if (ret) |
936 | goto err; | 933 | goto err; |
937 | 934 | ||
938 | #ifdef CONFIG_MTD_PARTITIONS | ||
939 | /* First look for RedBoot table or partitions on the command | 935 | /* First look for RedBoot table or partitions on the command |
940 | * line, these take precedence over device tree information */ | 936 | * line, these take precedence over device tree information */ |
941 | ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, 0); | 937 | ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, 0); |
942 | if (ret < 0) | 938 | if (ret < 0) |
943 | goto err; | 939 | goto err; |
944 | 940 | ||
945 | #ifdef CONFIG_MTD_OF_PARTS | ||
946 | if (ret == 0) { | 941 | if (ret == 0) { |
947 | ret = of_mtd_parse_partitions(priv->dev, node, &parts); | 942 | ret = of_mtd_parse_partitions(priv->dev, node, &parts); |
948 | if (ret < 0) | 943 | if (ret < 0) |
949 | goto err; | 944 | goto err; |
950 | } | 945 | } |
951 | #endif | ||
952 | 946 | ||
953 | if (ret > 0) | 947 | mtd_device_register(&priv->mtd, parts, ret); |
954 | add_mtd_partitions(&priv->mtd, parts, ret); | ||
955 | else | ||
956 | #endif | ||
957 | add_mtd_device(&priv->mtd); | ||
958 | 948 | ||
959 | printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n", | 949 | printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n", |
960 | (unsigned long long)res.start, priv->bank); | 950 | (unsigned long long)res.start, priv->bank); |
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 073ee026a17c..23752fd5bc59 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c | |||
@@ -33,10 +33,7 @@ struct fsl_upm_nand { | |||
33 | struct mtd_info mtd; | 33 | struct mtd_info mtd; |
34 | struct nand_chip chip; | 34 | struct nand_chip chip; |
35 | int last_ctrl; | 35 | int last_ctrl; |
36 | #ifdef CONFIG_MTD_PARTITIONS | ||
37 | struct mtd_partition *parts; | 36 | struct mtd_partition *parts; |
38 | #endif | ||
39 | |||
40 | struct fsl_upm upm; | 37 | struct fsl_upm upm; |
41 | uint8_t upm_addr_offset; | 38 | uint8_t upm_addr_offset; |
42 | uint8_t upm_cmd_offset; | 39 | uint8_t upm_cmd_offset; |
@@ -161,9 +158,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun, | |||
161 | { | 158 | { |
162 | int ret; | 159 | int ret; |
163 | struct device_node *flash_np; | 160 | struct device_node *flash_np; |
164 | #ifdef CONFIG_MTD_PARTITIONS | ||
165 | static const char *part_types[] = { "cmdlinepart", NULL, }; | 161 | static const char *part_types[] = { "cmdlinepart", NULL, }; |
166 | #endif | ||
167 | 162 | ||
168 | fun->chip.IO_ADDR_R = fun->io_base; | 163 | fun->chip.IO_ADDR_R = fun->io_base; |
169 | fun->chip.IO_ADDR_W = fun->io_base; | 164 | fun->chip.IO_ADDR_W = fun->io_base; |
@@ -197,7 +192,6 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun, | |||
197 | if (ret) | 192 | if (ret) |
198 | goto err; | 193 | goto err; |
199 | 194 | ||
200 | #ifdef CONFIG_MTD_PARTITIONS | ||
201 | ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0); | 195 | ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0); |
202 | 196 | ||
203 | #ifdef CONFIG_MTD_OF_PARTS | 197 | #ifdef CONFIG_MTD_OF_PARTS |
@@ -207,11 +201,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun, | |||
207 | goto err; | 201 | goto err; |
208 | } | 202 | } |
209 | #endif | 203 | #endif |
210 | if (ret > 0) | 204 | ret = mtd_device_register(&fun->mtd, fun->parts, ret); |
211 | ret = add_mtd_partitions(&fun->mtd, fun->parts, ret); | ||
212 | else | ||
213 | #endif | ||
214 | ret = add_mtd_device(&fun->mtd); | ||
215 | err: | 205 | err: |
216 | of_node_put(flash_np); | 206 | of_node_put(flash_np); |
217 | return ret; | 207 | return ret; |
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 0d45ef3883e8..e9b275ac381c 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c | |||
@@ -120,8 +120,6 @@ static struct fsmc_eccplace fsmc_ecc4_sp_place = { | |||
120 | } | 120 | } |
121 | }; | 121 | }; |
122 | 122 | ||
123 | |||
124 | #ifdef CONFIG_MTD_PARTITIONS | ||
125 | /* | 123 | /* |
126 | * Default partition tables to be used if the partition information not | 124 | * Default partition tables to be used if the partition information not |
127 | * provided through platform data. | 125 | * provided through platform data. |
@@ -182,7 +180,6 @@ static struct mtd_partition partition_info_128KB_blk[] = { | |||
182 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 180 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
183 | const char *part_probes[] = { "cmdlinepart", NULL }; | 181 | const char *part_probes[] = { "cmdlinepart", NULL }; |
184 | #endif | 182 | #endif |
185 | #endif | ||
186 | 183 | ||
187 | /** | 184 | /** |
188 | * struct fsmc_nand_data - structure for FSMC NAND device state | 185 | * struct fsmc_nand_data - structure for FSMC NAND device state |
@@ -719,7 +716,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
719 | * platform data, | 716 | * platform data, |
720 | * default partition information present in driver. | 717 | * default partition information present in driver. |
721 | */ | 718 | */ |
722 | #ifdef CONFIG_MTD_PARTITIONS | ||
723 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 719 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
724 | /* | 720 | /* |
725 | * Check if partition info passed via command line | 721 | * Check if partition info passed via command line |
@@ -777,19 +773,10 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
777 | } | 773 | } |
778 | #endif | 774 | #endif |
779 | 775 | ||
780 | if (host->partitions) { | 776 | ret = mtd_device_register(&host->mtd, host->partitions, |
781 | ret = add_mtd_partitions(&host->mtd, host->partitions, | 777 | host->nr_partitions); |
782 | host->nr_partitions); | 778 | if (ret) |
783 | if (ret) | ||
784 | goto err_probe; | ||
785 | } | ||
786 | #else | ||
787 | dev_info(&pdev->dev, "Registering %s as whole device\n", mtd->name); | ||
788 | if (!add_mtd_device(mtd)) { | ||
789 | ret = -ENXIO; | ||
790 | goto err_probe; | 779 | goto err_probe; |
791 | } | ||
792 | #endif | ||
793 | 780 | ||
794 | platform_set_drvdata(pdev, host); | 781 | platform_set_drvdata(pdev, host); |
795 | dev_info(&pdev->dev, "FSMC NAND driver registration successful\n"); | 782 | dev_info(&pdev->dev, "FSMC NAND driver registration successful\n"); |
@@ -835,11 +822,7 @@ static int fsmc_nand_remove(struct platform_device *pdev) | |||
835 | platform_set_drvdata(pdev, NULL); | 822 | platform_set_drvdata(pdev, NULL); |
836 | 823 | ||
837 | if (host) { | 824 | if (host) { |
838 | #ifdef CONFIG_MTD_PARTITIONS | 825 | mtd_device_unregister(&host->mtd); |
839 | del_mtd_partitions(&host->mtd); | ||
840 | #else | ||
841 | del_mtd_device(&host->mtd); | ||
842 | #endif | ||
843 | clk_disable(host->clk); | 826 | clk_disable(host->clk); |
844 | clk_put(host->clk); | 827 | clk_put(host->clk); |
845 | 828 | ||
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index 0cde618bcc1e..2c2060b2800e 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c | |||
@@ -316,8 +316,8 @@ static int __devinit gpio_nand_probe(struct platform_device *dev) | |||
316 | gpiomtd->plat.adjust_parts(&gpiomtd->plat, | 316 | gpiomtd->plat.adjust_parts(&gpiomtd->plat, |
317 | gpiomtd->mtd_info.size); | 317 | gpiomtd->mtd_info.size); |
318 | 318 | ||
319 | add_mtd_partitions(&gpiomtd->mtd_info, gpiomtd->plat.parts, | 319 | mtd_device_register(&gpiomtd->mtd_info, gpiomtd->plat.parts, |
320 | gpiomtd->plat.num_parts); | 320 | gpiomtd->plat.num_parts); |
321 | platform_set_drvdata(dev, gpiomtd); | 321 | platform_set_drvdata(dev, gpiomtd); |
322 | 322 | ||
323 | return 0; | 323 | return 0; |
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c index f8ce79b446ed..02a03e67109c 100644 --- a/drivers/mtd/nand/h1910.c +++ b/drivers/mtd/nand/h1910.c | |||
@@ -38,7 +38,6 @@ static struct mtd_info *h1910_nand_mtd = NULL; | |||
38 | * Module stuff | 38 | * Module stuff |
39 | */ | 39 | */ |
40 | 40 | ||
41 | #ifdef CONFIG_MTD_PARTITIONS | ||
42 | /* | 41 | /* |
43 | * Define static partitions for flash device | 42 | * Define static partitions for flash device |
44 | */ | 43 | */ |
@@ -50,8 +49,6 @@ static struct mtd_partition partition_info[] = { | |||
50 | 49 | ||
51 | #define NUM_PARTITIONS 1 | 50 | #define NUM_PARTITIONS 1 |
52 | 51 | ||
53 | #endif | ||
54 | |||
55 | /* | 52 | /* |
56 | * hardware specific access to control-lines | 53 | * hardware specific access to control-lines |
57 | * | 54 | * |
@@ -154,7 +151,7 @@ static int __init h1910_init(void) | |||
154 | 151 | ||
155 | /* Register the partitions */ | 152 | /* Register the partitions */ |
156 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | 153 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); |
157 | add_mtd_partitions(h1910_nand_mtd, mtd_parts, mtd_parts_nb); | 154 | mtd_device_register(h1910_nand_mtd, mtd_parts, mtd_parts_nb); |
158 | 155 | ||
159 | /* Return happy */ | 156 | /* Return happy */ |
160 | return 0; | 157 | return 0; |
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index cea38a5d4ac5..6e813daed068 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c | |||
@@ -299,10 +299,8 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) | |||
299 | struct nand_chip *chip; | 299 | struct nand_chip *chip; |
300 | struct mtd_info *mtd; | 300 | struct mtd_info *mtd; |
301 | struct jz_nand_platform_data *pdata = pdev->dev.platform_data; | 301 | struct jz_nand_platform_data *pdata = pdev->dev.platform_data; |
302 | #ifdef CONFIG_MTD_PARTITIONS | ||
303 | struct mtd_partition *partition_info; | 302 | struct mtd_partition *partition_info; |
304 | int num_partitions = 0; | 303 | int num_partitions = 0; |
305 | #endif | ||
306 | 304 | ||
307 | nand = kzalloc(sizeof(*nand), GFP_KERNEL); | 305 | nand = kzalloc(sizeof(*nand), GFP_KERNEL); |
308 | if (!nand) { | 306 | if (!nand) { |
@@ -375,7 +373,6 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) | |||
375 | goto err_gpio_free; | 373 | goto err_gpio_free; |
376 | } | 374 | } |
377 | 375 | ||
378 | #ifdef CONFIG_MTD_PARTITIONS | ||
379 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 376 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
380 | num_partitions = parse_mtd_partitions(mtd, part_probes, | 377 | num_partitions = parse_mtd_partitions(mtd, part_probes, |
381 | &partition_info, 0); | 378 | &partition_info, 0); |
@@ -384,12 +381,7 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) | |||
384 | num_partitions = pdata->num_partitions; | 381 | num_partitions = pdata->num_partitions; |
385 | partition_info = pdata->partitions; | 382 | partition_info = pdata->partitions; |
386 | } | 383 | } |
387 | 384 | ret = mtd_device_register(mtd, partition_info, num_partitions); | |
388 | if (num_partitions > 0) | ||
389 | ret = add_mtd_partitions(mtd, partition_info, num_partitions); | ||
390 | else | ||
391 | #endif | ||
392 | ret = add_mtd_device(mtd); | ||
393 | 385 | ||
394 | if (ret) { | 386 | if (ret) { |
395 | dev_err(&pdev->dev, "Failed to add mtd device\n"); | 387 | dev_err(&pdev->dev, "Failed to add mtd device\n"); |
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 0b81b5b499d1..2f7c930872f9 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c | |||
@@ -131,9 +131,7 @@ struct mpc5121_nfc_prv { | |||
131 | 131 | ||
132 | static void mpc5121_nfc_done(struct mtd_info *mtd); | 132 | static void mpc5121_nfc_done(struct mtd_info *mtd); |
133 | 133 | ||
134 | #ifdef CONFIG_MTD_PARTITIONS | ||
135 | static const char *mpc5121_nfc_pprobes[] = { "cmdlinepart", NULL }; | 134 | static const char *mpc5121_nfc_pprobes[] = { "cmdlinepart", NULL }; |
136 | #endif | ||
137 | 135 | ||
138 | /* Read NFC register */ | 136 | /* Read NFC register */ |
139 | static inline u16 nfc_read(struct mtd_info *mtd, uint reg) | 137 | static inline u16 nfc_read(struct mtd_info *mtd, uint reg) |
@@ -658,9 +656,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op) | |||
658 | struct mpc5121_nfc_prv *prv; | 656 | struct mpc5121_nfc_prv *prv; |
659 | struct resource res; | 657 | struct resource res; |
660 | struct mtd_info *mtd; | 658 | struct mtd_info *mtd; |
661 | #ifdef CONFIG_MTD_PARTITIONS | ||
662 | struct mtd_partition *parts; | 659 | struct mtd_partition *parts; |
663 | #endif | ||
664 | struct nand_chip *chip; | 660 | struct nand_chip *chip; |
665 | unsigned long regs_paddr, regs_size; | 661 | unsigned long regs_paddr, regs_size; |
666 | const __be32 *chips_no; | 662 | const __be32 *chips_no; |
@@ -841,7 +837,6 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op) | |||
841 | dev_set_drvdata(dev, mtd); | 837 | dev_set_drvdata(dev, mtd); |
842 | 838 | ||
843 | /* Register device in MTD */ | 839 | /* Register device in MTD */ |
844 | #ifdef CONFIG_MTD_PARTITIONS | ||
845 | retval = parse_mtd_partitions(mtd, mpc5121_nfc_pprobes, &parts, 0); | 840 | retval = parse_mtd_partitions(mtd, mpc5121_nfc_pprobes, &parts, 0); |
846 | #ifdef CONFIG_MTD_OF_PARTS | 841 | #ifdef CONFIG_MTD_OF_PARTS |
847 | if (retval == 0) | 842 | if (retval == 0) |
@@ -854,12 +849,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op) | |||
854 | goto error; | 849 | goto error; |
855 | } | 850 | } |
856 | 851 | ||
857 | if (retval > 0) | 852 | retval = mtd_device_register(mtd, parts, retval); |
858 | retval = add_mtd_partitions(mtd, parts, retval); | ||
859 | else | ||
860 | #endif | ||
861 | retval = add_mtd_device(mtd); | ||
862 | |||
863 | if (retval) { | 853 | if (retval) { |
864 | dev_err(dev, "Error adding MTD device!\n"); | 854 | dev_err(dev, "Error adding MTD device!\n"); |
865 | devm_free_irq(dev, prv->irq, mtd); | 855 | devm_free_irq(dev, prv->irq, mtd); |
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 42a95fb41504..90df34c4d26c 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -56,8 +56,14 @@ | |||
56 | #define NFC_V1_V2_WRPROT (host->regs + 0x12) | 56 | #define NFC_V1_V2_WRPROT (host->regs + 0x12) |
57 | #define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14) | 57 | #define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14) |
58 | #define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16) | 58 | #define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16) |
59 | #define NFC_V21_UNLOCKSTART_BLKADDR (host->regs + 0x20) | 59 | #define NFC_V21_UNLOCKSTART_BLKADDR0 (host->regs + 0x20) |
60 | #define NFC_V21_UNLOCKEND_BLKADDR (host->regs + 0x22) | 60 | #define NFC_V21_UNLOCKSTART_BLKADDR1 (host->regs + 0x24) |
61 | #define NFC_V21_UNLOCKSTART_BLKADDR2 (host->regs + 0x28) | ||
62 | #define NFC_V21_UNLOCKSTART_BLKADDR3 (host->regs + 0x2c) | ||
63 | #define NFC_V21_UNLOCKEND_BLKADDR0 (host->regs + 0x22) | ||
64 | #define NFC_V21_UNLOCKEND_BLKADDR1 (host->regs + 0x26) | ||
65 | #define NFC_V21_UNLOCKEND_BLKADDR2 (host->regs + 0x2a) | ||
66 | #define NFC_V21_UNLOCKEND_BLKADDR3 (host->regs + 0x2e) | ||
61 | #define NFC_V1_V2_NF_WRPRST (host->regs + 0x18) | 67 | #define NFC_V1_V2_NF_WRPRST (host->regs + 0x18) |
62 | #define NFC_V1_V2_CONFIG1 (host->regs + 0x1a) | 68 | #define NFC_V1_V2_CONFIG1 (host->regs + 0x1a) |
63 | #define NFC_V1_V2_CONFIG2 (host->regs + 0x1c) | 69 | #define NFC_V1_V2_CONFIG2 (host->regs + 0x1c) |
@@ -152,6 +158,7 @@ struct mxc_nand_host { | |||
152 | int clk_act; | 158 | int clk_act; |
153 | int irq; | 159 | int irq; |
154 | int eccsize; | 160 | int eccsize; |
161 | int active_cs; | ||
155 | 162 | ||
156 | struct completion op_completion; | 163 | struct completion op_completion; |
157 | 164 | ||
@@ -236,9 +243,7 @@ static struct nand_ecclayout nandv2_hw_eccoob_4k = { | |||
236 | } | 243 | } |
237 | }; | 244 | }; |
238 | 245 | ||
239 | #ifdef CONFIG_MTD_PARTITIONS | ||
240 | static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL }; | 246 | static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL }; |
241 | #endif | ||
242 | 247 | ||
243 | static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | 248 | static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) |
244 | { | 249 | { |
@@ -445,7 +450,7 @@ static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops) | |||
445 | for (i = 0; i < bufs; i++) { | 450 | for (i = 0; i < bufs; i++) { |
446 | 451 | ||
447 | /* NANDFC buffer 0 is used for page read/write */ | 452 | /* NANDFC buffer 0 is used for page read/write */ |
448 | writew(i, NFC_V1_V2_BUF_ADDR); | 453 | writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR); |
449 | 454 | ||
450 | writew(ops, NFC_V1_V2_CONFIG2); | 455 | writew(ops, NFC_V1_V2_CONFIG2); |
451 | 456 | ||
@@ -470,7 +475,7 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) | |||
470 | struct nand_chip *this = &host->nand; | 475 | struct nand_chip *this = &host->nand; |
471 | 476 | ||
472 | /* NANDFC buffer 0 is used for device ID output */ | 477 | /* NANDFC buffer 0 is used for device ID output */ |
473 | writew(0x0, NFC_V1_V2_BUF_ADDR); | 478 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); |
474 | 479 | ||
475 | writew(NFC_ID, NFC_V1_V2_CONFIG2); | 480 | writew(NFC_ID, NFC_V1_V2_CONFIG2); |
476 | 481 | ||
@@ -505,7 +510,7 @@ static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host) | |||
505 | uint32_t store; | 510 | uint32_t store; |
506 | uint16_t ret; | 511 | uint16_t ret; |
507 | 512 | ||
508 | writew(0x0, NFC_V1_V2_BUF_ADDR); | 513 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); |
509 | 514 | ||
510 | /* | 515 | /* |
511 | * The device status is stored in main_area0. To | 516 | * The device status is stored in main_area0. To |
@@ -686,24 +691,24 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) | |||
686 | struct nand_chip *nand_chip = mtd->priv; | 691 | struct nand_chip *nand_chip = mtd->priv; |
687 | struct mxc_nand_host *host = nand_chip->priv; | 692 | struct mxc_nand_host *host = nand_chip->priv; |
688 | 693 | ||
689 | switch (chip) { | 694 | if (chip == -1) { |
690 | case -1: | ||
691 | /* Disable the NFC clock */ | 695 | /* Disable the NFC clock */ |
692 | if (host->clk_act) { | 696 | if (host->clk_act) { |
693 | clk_disable(host->clk); | 697 | clk_disable(host->clk); |
694 | host->clk_act = 0; | 698 | host->clk_act = 0; |
695 | } | 699 | } |
696 | break; | 700 | return; |
697 | case 0: | 701 | } |
702 | |||
703 | if (!host->clk_act) { | ||
698 | /* Enable the NFC clock */ | 704 | /* Enable the NFC clock */ |
699 | if (!host->clk_act) { | 705 | clk_enable(host->clk); |
700 | clk_enable(host->clk); | 706 | host->clk_act = 1; |
701 | host->clk_act = 1; | 707 | } |
702 | } | ||
703 | break; | ||
704 | 708 | ||
705 | default: | 709 | if (nfc_is_v21()) { |
706 | break; | 710 | host->active_cs = chip; |
711 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); | ||
707 | } | 712 | } |
708 | } | 713 | } |
709 | 714 | ||
@@ -834,8 +839,14 @@ static void preset_v1_v2(struct mtd_info *mtd) | |||
834 | 839 | ||
835 | /* Blocks to be unlocked */ | 840 | /* Blocks to be unlocked */ |
836 | if (nfc_is_v21()) { | 841 | if (nfc_is_v21()) { |
837 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR); | 842 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0); |
838 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR); | 843 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1); |
844 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2); | ||
845 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3); | ||
846 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0); | ||
847 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1); | ||
848 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2); | ||
849 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3); | ||
839 | } else if (nfc_is_v1()) { | 850 | } else if (nfc_is_v1()) { |
840 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); | 851 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); |
841 | writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR); | 852 | writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR); |
@@ -1200,7 +1211,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1200 | irq_control_v1_v2(host, 1); | 1211 | irq_control_v1_v2(host, 1); |
1201 | 1212 | ||
1202 | /* first scan to find the device and get the page size */ | 1213 | /* first scan to find the device and get the page size */ |
1203 | if (nand_scan_ident(mtd, 1, NULL)) { | 1214 | if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) { |
1204 | err = -ENXIO; | 1215 | err = -ENXIO; |
1205 | goto escan; | 1216 | goto escan; |
1206 | } | 1217 | } |
@@ -1220,18 +1231,15 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1220 | } | 1231 | } |
1221 | 1232 | ||
1222 | /* Register the partitions */ | 1233 | /* Register the partitions */ |
1223 | #ifdef CONFIG_MTD_PARTITIONS | ||
1224 | nr_parts = | 1234 | nr_parts = |
1225 | parse_mtd_partitions(mtd, part_probes, &host->parts, 0); | 1235 | parse_mtd_partitions(mtd, part_probes, &host->parts, 0); |
1226 | if (nr_parts > 0) | 1236 | if (nr_parts > 0) |
1227 | add_mtd_partitions(mtd, host->parts, nr_parts); | 1237 | mtd_device_register(mtd, host->parts, nr_parts); |
1228 | else if (pdata->parts) | 1238 | else if (pdata->parts) |
1229 | add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); | 1239 | mtd_device_register(mtd, pdata->parts, pdata->nr_parts); |
1230 | else | 1240 | else { |
1231 | #endif | ||
1232 | { | ||
1233 | pr_info("Registering %s as whole device\n", mtd->name); | 1241 | pr_info("Registering %s as whole device\n", mtd->name); |
1234 | add_mtd_device(mtd); | 1242 | mtd_device_register(mtd, NULL, 0); |
1235 | } | 1243 | } |
1236 | 1244 | ||
1237 | platform_set_drvdata(pdev, host); | 1245 | platform_set_drvdata(pdev, host); |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index c54a4cbac6bc..a46e9bb847bd 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -47,10 +47,7 @@ | |||
47 | #include <linux/bitops.h> | 47 | #include <linux/bitops.h> |
48 | #include <linux/leds.h> | 48 | #include <linux/leds.h> |
49 | #include <linux/io.h> | 49 | #include <linux/io.h> |
50 | |||
51 | #ifdef CONFIG_MTD_PARTITIONS | ||
52 | #include <linux/mtd/partitions.h> | 50 | #include <linux/mtd/partitions.h> |
53 | #endif | ||
54 | 51 | ||
55 | /* Define default oob placement schemes for large and small page devices */ | 52 | /* Define default oob placement schemes for large and small page devices */ |
56 | static struct nand_ecclayout nand_oob_8 = { | 53 | static struct nand_ecclayout nand_oob_8 = { |
@@ -976,9 +973,6 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
976 | ret = __nand_unlock(mtd, ofs, len, 0); | 973 | ret = __nand_unlock(mtd, ofs, len, 0); |
977 | 974 | ||
978 | out: | 975 | out: |
979 | /* de-select the NAND device */ | ||
980 | chip->select_chip(mtd, -1); | ||
981 | |||
982 | nand_release_device(mtd); | 976 | nand_release_device(mtd); |
983 | 977 | ||
984 | return ret; | 978 | return ret; |
@@ -1046,9 +1040,6 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
1046 | ret = __nand_unlock(mtd, ofs, len, 0x1); | 1040 | ret = __nand_unlock(mtd, ofs, len, 0x1); |
1047 | 1041 | ||
1048 | out: | 1042 | out: |
1049 | /* de-select the NAND device */ | ||
1050 | chip->select_chip(mtd, -1); | ||
1051 | |||
1052 | nand_release_device(mtd); | 1043 | nand_release_device(mtd); |
1053 | 1044 | ||
1054 | return ret; | 1045 | return ret; |
@@ -3112,6 +3103,8 @@ ident_done: | |||
3112 | chip->chip_shift += 32 - 1; | 3103 | chip->chip_shift += 32 - 1; |
3113 | } | 3104 | } |
3114 | 3105 | ||
3106 | chip->badblockbits = 8; | ||
3107 | |||
3115 | /* Set the bad block position */ | 3108 | /* Set the bad block position */ |
3116 | if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16)) | 3109 | if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16)) |
3117 | chip->badblockpos = NAND_LARGE_BADBLOCK_POS; | 3110 | chip->badblockpos = NAND_LARGE_BADBLOCK_POS; |
@@ -3539,12 +3532,7 @@ void nand_release(struct mtd_info *mtd) | |||
3539 | if (chip->ecc.mode == NAND_ECC_SOFT_BCH) | 3532 | if (chip->ecc.mode == NAND_ECC_SOFT_BCH) |
3540 | nand_bch_free((struct nand_bch_control *)chip->ecc.priv); | 3533 | nand_bch_free((struct nand_bch_control *)chip->ecc.priv); |
3541 | 3534 | ||
3542 | #ifdef CONFIG_MTD_PARTITIONS | 3535 | mtd_device_unregister(mtd); |
3543 | /* Deregister partitions */ | ||
3544 | del_mtd_partitions(mtd); | ||
3545 | #endif | ||
3546 | /* Deregister the device */ | ||
3547 | del_mtd_device(mtd); | ||
3548 | 3536 | ||
3549 | /* Free bad block table memory */ | 3537 | /* Free bad block table memory */ |
3550 | kfree(chip->bbt); | 3538 | kfree(chip->bbt); |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index af46428286fe..ccbeaa1e4a8e 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -1276,20 +1276,6 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs) | |||
1276 | * while scanning a device for factory marked good / bad blocks. */ | 1276 | * while scanning a device for factory marked good / bad blocks. */ |
1277 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | 1277 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; |
1278 | 1278 | ||
1279 | static struct nand_bbt_descr smallpage_flashbased = { | ||
1280 | .options = NAND_BBT_SCAN2NDPAGE, | ||
1281 | .offs = NAND_SMALL_BADBLOCK_POS, | ||
1282 | .len = 1, | ||
1283 | .pattern = scan_ff_pattern | ||
1284 | }; | ||
1285 | |||
1286 | static struct nand_bbt_descr largepage_flashbased = { | ||
1287 | .options = NAND_BBT_SCAN2NDPAGE, | ||
1288 | .offs = NAND_LARGE_BADBLOCK_POS, | ||
1289 | .len = 2, | ||
1290 | .pattern = scan_ff_pattern | ||
1291 | }; | ||
1292 | |||
1293 | static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 }; | 1279 | static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 }; |
1294 | 1280 | ||
1295 | static struct nand_bbt_descr agand_flashbased = { | 1281 | static struct nand_bbt_descr agand_flashbased = { |
@@ -1355,10 +1341,6 @@ static struct nand_bbt_descr bbt_mirror_no_bbt_descr = { | |||
1355 | * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when | 1341 | * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when |
1356 | * passed to this function. | 1342 | * passed to this function. |
1357 | * | 1343 | * |
1358 | * TODO: Handle other flags, replace other static structs | ||
1359 | * (e.g. handle NAND_BBT_FLASH for flash-based BBT, | ||
1360 | * replace smallpage_flashbased) | ||
1361 | * | ||
1362 | */ | 1344 | */ |
1363 | static int nand_create_default_bbt_descr(struct nand_chip *this) | 1345 | static int nand_create_default_bbt_descr(struct nand_chip *this) |
1364 | { | 1346 | { |
@@ -1422,15 +1404,14 @@ int nand_default_bbt(struct mtd_info *mtd) | |||
1422 | this->bbt_md = &bbt_mirror_descr; | 1404 | this->bbt_md = &bbt_mirror_descr; |
1423 | } | 1405 | } |
1424 | } | 1406 | } |
1425 | if (!this->badblock_pattern) { | ||
1426 | this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased; | ||
1427 | } | ||
1428 | } else { | 1407 | } else { |
1429 | this->bbt_td = NULL; | 1408 | this->bbt_td = NULL; |
1430 | this->bbt_md = NULL; | 1409 | this->bbt_md = NULL; |
1431 | if (!this->badblock_pattern) | ||
1432 | nand_create_default_bbt_descr(this); | ||
1433 | } | 1410 | } |
1411 | |||
1412 | if (!this->badblock_pattern) | ||
1413 | nand_create_default_bbt_descr(this); | ||
1414 | |||
1434 | return nand_scan_bbt(mtd, this->badblock_pattern); | 1415 | return nand_scan_bbt(mtd, this->badblock_pattern); |
1435 | } | 1416 | } |
1436 | 1417 | ||
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 893d95bfea48..357e8c5252a8 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -2383,7 +2383,9 @@ static int __init ns_init_module(void) | |||
2383 | goto err_exit; | 2383 | goto err_exit; |
2384 | 2384 | ||
2385 | /* Register NAND partitions */ | 2385 | /* Register NAND partitions */ |
2386 | if ((retval = add_mtd_partitions(nsmtd, &nand->partitions[0], nand->nbparts)) != 0) | 2386 | retval = mtd_device_register(nsmtd, &nand->partitions[0], |
2387 | nand->nbparts); | ||
2388 | if (retval != 0) | ||
2387 | goto err_exit; | 2389 | goto err_exit; |
2388 | 2390 | ||
2389 | return 0; | 2391 | return 0; |
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index bbe6d451290d..ea2dea8a9c88 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/of_platform.h> | 33 | #include <linux/of_platform.h> |
34 | #include <asm/io.h> | 34 | #include <asm/io.h> |
35 | 35 | ||
36 | #define NDFC_MAX_CS 4 | ||
36 | 37 | ||
37 | struct ndfc_controller { | 38 | struct ndfc_controller { |
38 | struct platform_device *ofdev; | 39 | struct platform_device *ofdev; |
@@ -41,17 +42,16 @@ struct ndfc_controller { | |||
41 | struct nand_chip chip; | 42 | struct nand_chip chip; |
42 | int chip_select; | 43 | int chip_select; |
43 | struct nand_hw_control ndfc_control; | 44 | struct nand_hw_control ndfc_control; |
44 | #ifdef CONFIG_MTD_PARTITIONS | ||
45 | struct mtd_partition *parts; | 45 | struct mtd_partition *parts; |
46 | #endif | ||
47 | }; | 46 | }; |
48 | 47 | ||
49 | static struct ndfc_controller ndfc_ctrl; | 48 | static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS]; |
50 | 49 | ||
51 | static void ndfc_select_chip(struct mtd_info *mtd, int chip) | 50 | static void ndfc_select_chip(struct mtd_info *mtd, int chip) |
52 | { | 51 | { |
53 | uint32_t ccr; | 52 | uint32_t ccr; |
54 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 53 | struct nand_chip *nchip = mtd->priv; |
54 | struct ndfc_controller *ndfc = nchip->priv; | ||
55 | 55 | ||
56 | ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); | 56 | ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); |
57 | if (chip >= 0) { | 57 | if (chip >= 0) { |
@@ -64,7 +64,8 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip) | |||
64 | 64 | ||
65 | static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) | 65 | static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) |
66 | { | 66 | { |
67 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 67 | struct nand_chip *chip = mtd->priv; |
68 | struct ndfc_controller *ndfc = chip->priv; | ||
68 | 69 | ||
69 | if (cmd == NAND_CMD_NONE) | 70 | if (cmd == NAND_CMD_NONE) |
70 | return; | 71 | return; |
@@ -77,7 +78,8 @@ static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) | |||
77 | 78 | ||
78 | static int ndfc_ready(struct mtd_info *mtd) | 79 | static int ndfc_ready(struct mtd_info *mtd) |
79 | { | 80 | { |
80 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 81 | struct nand_chip *chip = mtd->priv; |
82 | struct ndfc_controller *ndfc = chip->priv; | ||
81 | 83 | ||
82 | return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; | 84 | return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; |
83 | } | 85 | } |
@@ -85,7 +87,8 @@ static int ndfc_ready(struct mtd_info *mtd) | |||
85 | static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) | 87 | static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) |
86 | { | 88 | { |
87 | uint32_t ccr; | 89 | uint32_t ccr; |
88 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 90 | struct nand_chip *chip = mtd->priv; |
91 | struct ndfc_controller *ndfc = chip->priv; | ||
89 | 92 | ||
90 | ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); | 93 | ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); |
91 | ccr |= NDFC_CCR_RESET_ECC; | 94 | ccr |= NDFC_CCR_RESET_ECC; |
@@ -96,7 +99,8 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) | |||
96 | static int ndfc_calculate_ecc(struct mtd_info *mtd, | 99 | static int ndfc_calculate_ecc(struct mtd_info *mtd, |
97 | const u_char *dat, u_char *ecc_code) | 100 | const u_char *dat, u_char *ecc_code) |
98 | { | 101 | { |
99 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 102 | struct nand_chip *chip = mtd->priv; |
103 | struct ndfc_controller *ndfc = chip->priv; | ||
100 | uint32_t ecc; | 104 | uint32_t ecc; |
101 | uint8_t *p = (uint8_t *)&ecc; | 105 | uint8_t *p = (uint8_t *)&ecc; |
102 | 106 | ||
@@ -119,7 +123,8 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd, | |||
119 | */ | 123 | */ |
120 | static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | 124 | static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) |
121 | { | 125 | { |
122 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 126 | struct nand_chip *chip = mtd->priv; |
127 | struct ndfc_controller *ndfc = chip->priv; | ||
123 | uint32_t *p = (uint32_t *) buf; | 128 | uint32_t *p = (uint32_t *) buf; |
124 | 129 | ||
125 | for(;len > 0; len -= 4) | 130 | for(;len > 0; len -= 4) |
@@ -128,7 +133,8 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |||
128 | 133 | ||
129 | static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | 134 | static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
130 | { | 135 | { |
131 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 136 | struct nand_chip *chip = mtd->priv; |
137 | struct ndfc_controller *ndfc = chip->priv; | ||
132 | uint32_t *p = (uint32_t *) buf; | 138 | uint32_t *p = (uint32_t *) buf; |
133 | 139 | ||
134 | for(;len > 0; len -= 4) | 140 | for(;len > 0; len -= 4) |
@@ -137,7 +143,8 @@ static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
137 | 143 | ||
138 | static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | 144 | static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
139 | { | 145 | { |
140 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 146 | struct nand_chip *chip = mtd->priv; |
147 | struct ndfc_controller *ndfc = chip->priv; | ||
141 | uint32_t *p = (uint32_t *) buf; | 148 | uint32_t *p = (uint32_t *) buf; |
142 | 149 | ||
143 | for(;len > 0; len -= 4) | 150 | for(;len > 0; len -= 4) |
@@ -152,13 +159,11 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
152 | static int ndfc_chip_init(struct ndfc_controller *ndfc, | 159 | static int ndfc_chip_init(struct ndfc_controller *ndfc, |
153 | struct device_node *node) | 160 | struct device_node *node) |
154 | { | 161 | { |
155 | #ifdef CONFIG_MTD_PARTITIONS | ||
156 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 162 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
157 | static const char *part_types[] = { "cmdlinepart", NULL }; | 163 | static const char *part_types[] = { "cmdlinepart", NULL }; |
158 | #else | 164 | #else |
159 | static const char *part_types[] = { NULL }; | 165 | static const char *part_types[] = { NULL }; |
160 | #endif | 166 | #endif |
161 | #endif | ||
162 | struct device_node *flash_np; | 167 | struct device_node *flash_np; |
163 | struct nand_chip *chip = &ndfc->chip; | 168 | struct nand_chip *chip = &ndfc->chip; |
164 | int ret; | 169 | int ret; |
@@ -179,6 +184,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, | |||
179 | chip->ecc.mode = NAND_ECC_HW; | 184 | chip->ecc.mode = NAND_ECC_HW; |
180 | chip->ecc.size = 256; | 185 | chip->ecc.size = 256; |
181 | chip->ecc.bytes = 3; | 186 | chip->ecc.bytes = 3; |
187 | chip->priv = ndfc; | ||
182 | 188 | ||
183 | ndfc->mtd.priv = chip; | 189 | ndfc->mtd.priv = chip; |
184 | ndfc->mtd.owner = THIS_MODULE; | 190 | ndfc->mtd.owner = THIS_MODULE; |
@@ -198,25 +204,18 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, | |||
198 | if (ret) | 204 | if (ret) |
199 | goto err; | 205 | goto err; |
200 | 206 | ||
201 | #ifdef CONFIG_MTD_PARTITIONS | ||
202 | ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0); | 207 | ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0); |
203 | if (ret < 0) | 208 | if (ret < 0) |
204 | goto err; | 209 | goto err; |
205 | 210 | ||
206 | #ifdef CONFIG_MTD_OF_PARTS | ||
207 | if (ret == 0) { | 211 | if (ret == 0) { |
208 | ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np, | 212 | ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np, |
209 | &ndfc->parts); | 213 | &ndfc->parts); |
210 | if (ret < 0) | 214 | if (ret < 0) |
211 | goto err; | 215 | goto err; |
212 | } | 216 | } |
213 | #endif | ||
214 | 217 | ||
215 | if (ret > 0) | 218 | ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret); |
216 | ret = add_mtd_partitions(&ndfc->mtd, ndfc->parts, ret); | ||
217 | else | ||
218 | #endif | ||
219 | ret = add_mtd_device(&ndfc->mtd); | ||
220 | 219 | ||
221 | err: | 220 | err: |
222 | of_node_put(flash_np); | 221 | of_node_put(flash_np); |
@@ -227,15 +226,10 @@ err: | |||
227 | 226 | ||
228 | static int __devinit ndfc_probe(struct platform_device *ofdev) | 227 | static int __devinit ndfc_probe(struct platform_device *ofdev) |
229 | { | 228 | { |
230 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 229 | struct ndfc_controller *ndfc; |
231 | const __be32 *reg; | 230 | const __be32 *reg; |
232 | u32 ccr; | 231 | u32 ccr; |
233 | int err, len; | 232 | int err, len, cs; |
234 | |||
235 | spin_lock_init(&ndfc->ndfc_control.lock); | ||
236 | init_waitqueue_head(&ndfc->ndfc_control.wq); | ||
237 | ndfc->ofdev = ofdev; | ||
238 | dev_set_drvdata(&ofdev->dev, ndfc); | ||
239 | 233 | ||
240 | /* Read the reg property to get the chip select */ | 234 | /* Read the reg property to get the chip select */ |
241 | reg = of_get_property(ofdev->dev.of_node, "reg", &len); | 235 | reg = of_get_property(ofdev->dev.of_node, "reg", &len); |
@@ -243,7 +237,20 @@ static int __devinit ndfc_probe(struct platform_device *ofdev) | |||
243 | dev_err(&ofdev->dev, "unable read reg property (%d)\n", len); | 237 | dev_err(&ofdev->dev, "unable read reg property (%d)\n", len); |
244 | return -ENOENT; | 238 | return -ENOENT; |
245 | } | 239 | } |
246 | ndfc->chip_select = be32_to_cpu(reg[0]); | 240 | |
241 | cs = be32_to_cpu(reg[0]); | ||
242 | if (cs >= NDFC_MAX_CS) { | ||
243 | dev_err(&ofdev->dev, "invalid CS number (%d)\n", cs); | ||
244 | return -EINVAL; | ||
245 | } | ||
246 | |||
247 | ndfc = &ndfc_ctrl[cs]; | ||
248 | ndfc->chip_select = cs; | ||
249 | |||
250 | spin_lock_init(&ndfc->ndfc_control.lock); | ||
251 | init_waitqueue_head(&ndfc->ndfc_control.wq); | ||
252 | ndfc->ofdev = ofdev; | ||
253 | dev_set_drvdata(&ofdev->dev, ndfc); | ||
247 | 254 | ||
248 | ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0); | 255 | ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0); |
249 | if (!ndfc->ndfcbase) { | 256 | if (!ndfc->ndfcbase) { |
diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c index a045a4a581b6..b6a5c86ab31e 100644 --- a/drivers/mtd/nand/nomadik_nand.c +++ b/drivers/mtd/nand/nomadik_nand.c | |||
@@ -158,12 +158,7 @@ static int nomadik_nand_probe(struct platform_device *pdev) | |||
158 | goto err_unmap; | 158 | goto err_unmap; |
159 | } | 159 | } |
160 | 160 | ||
161 | #ifdef CONFIG_MTD_PARTITIONS | 161 | mtd_device_register(&host->mtd, pdata->parts, pdata->nparts); |
162 | add_mtd_partitions(&host->mtd, pdata->parts, pdata->nparts); | ||
163 | #else | ||
164 | pr_info("Registering %s as whole device\n", mtd->name); | ||
165 | add_mtd_device(mtd); | ||
166 | #endif | ||
167 | 162 | ||
168 | platform_set_drvdata(pdev, host); | 163 | platform_set_drvdata(pdev, host); |
169 | return 0; | 164 | return 0; |
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index 6eddf7361ed7..9c30a0b03171 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c | |||
@@ -321,8 +321,8 @@ static int __devinit nuc900_nand_probe(struct platform_device *pdev) | |||
321 | goto fail3; | 321 | goto fail3; |
322 | } | 322 | } |
323 | 323 | ||
324 | add_mtd_partitions(&(nuc900_nand->mtd), partitions, | 324 | mtd_device_register(&(nuc900_nand->mtd), partitions, |
325 | ARRAY_SIZE(partitions)); | 325 | ARRAY_SIZE(partitions)); |
326 | 326 | ||
327 | platform_set_drvdata(pdev, nuc900_nand); | 327 | platform_set_drvdata(pdev, nuc900_nand); |
328 | 328 | ||
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index da9a351c9d79..0db2c0e7656a 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -94,9 +94,7 @@ | |||
94 | #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0) | 94 | #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0) |
95 | #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) | 95 | #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) |
96 | 96 | ||
97 | #ifdef CONFIG_MTD_PARTITIONS | ||
98 | static const char *part_probes[] = { "cmdlinepart", NULL }; | 97 | static const char *part_probes[] = { "cmdlinepart", NULL }; |
99 | #endif | ||
100 | 98 | ||
101 | /* oob info generated runtime depending on ecc algorithm and layout selected */ | 99 | /* oob info generated runtime depending on ecc algorithm and layout selected */ |
102 | static struct nand_ecclayout omap_oobinfo; | 100 | static struct nand_ecclayout omap_oobinfo; |
@@ -263,11 +261,10 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) | |||
263 | if (ret) { | 261 | if (ret) { |
264 | /* PFPW engine is busy, use cpu copy method */ | 262 | /* PFPW engine is busy, use cpu copy method */ |
265 | if (info->nand.options & NAND_BUSWIDTH_16) | 263 | if (info->nand.options & NAND_BUSWIDTH_16) |
266 | omap_read_buf16(mtd, buf, len); | 264 | omap_read_buf16(mtd, (u_char *)p, len); |
267 | else | 265 | else |
268 | omap_read_buf8(mtd, buf, len); | 266 | omap_read_buf8(mtd, (u_char *)p, len); |
269 | } else { | 267 | } else { |
270 | p = (u32 *) buf; | ||
271 | do { | 268 | do { |
272 | r_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT); | 269 | r_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT); |
273 | r_count = r_count >> 2; | 270 | r_count = r_count >> 2; |
@@ -293,7 +290,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd, | |||
293 | struct omap_nand_info, mtd); | 290 | struct omap_nand_info, mtd); |
294 | uint32_t w_count = 0; | 291 | uint32_t w_count = 0; |
295 | int i = 0, ret = 0; | 292 | int i = 0, ret = 0; |
296 | u16 *p; | 293 | u16 *p = (u16 *)buf; |
297 | unsigned long tim, limit; | 294 | unsigned long tim, limit; |
298 | 295 | ||
299 | /* take care of subpage writes */ | 296 | /* take care of subpage writes */ |
@@ -309,11 +306,10 @@ static void omap_write_buf_pref(struct mtd_info *mtd, | |||
309 | if (ret) { | 306 | if (ret) { |
310 | /* PFPW engine is busy, use cpu copy method */ | 307 | /* PFPW engine is busy, use cpu copy method */ |
311 | if (info->nand.options & NAND_BUSWIDTH_16) | 308 | if (info->nand.options & NAND_BUSWIDTH_16) |
312 | omap_write_buf16(mtd, buf, len); | 309 | omap_write_buf16(mtd, (u_char *)p, len); |
313 | else | 310 | else |
314 | omap_write_buf8(mtd, buf, len); | 311 | omap_write_buf8(mtd, (u_char *)p, len); |
315 | } else { | 312 | } else { |
316 | p = (u16 *) buf; | ||
317 | while (len) { | 313 | while (len) { |
318 | w_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT); | 314 | w_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT); |
319 | w_count = w_count >> 1; | 315 | w_count = w_count >> 1; |
@@ -1073,9 +1069,9 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) | |||
1073 | /* DIP switches on some boards change between 8 and 16 bit | 1069 | /* DIP switches on some boards change between 8 and 16 bit |
1074 | * bus widths for flash. Try the other width if the first try fails. | 1070 | * bus widths for flash. Try the other width if the first try fails. |
1075 | */ | 1071 | */ |
1076 | if (nand_scan(&info->mtd, 1)) { | 1072 | if (nand_scan_ident(&info->mtd, 1, NULL)) { |
1077 | info->nand.options ^= NAND_BUSWIDTH_16; | 1073 | info->nand.options ^= NAND_BUSWIDTH_16; |
1078 | if (nand_scan(&info->mtd, 1)) { | 1074 | if (nand_scan_ident(&info->mtd, 1, NULL)) { |
1079 | err = -ENXIO; | 1075 | err = -ENXIO; |
1080 | goto out_release_mem_region; | 1076 | goto out_release_mem_region; |
1081 | } | 1077 | } |
@@ -1101,15 +1097,19 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) | |||
1101 | info->nand.ecc.layout = &omap_oobinfo; | 1097 | info->nand.ecc.layout = &omap_oobinfo; |
1102 | } | 1098 | } |
1103 | 1099 | ||
1104 | #ifdef CONFIG_MTD_PARTITIONS | 1100 | /* second phase scan */ |
1101 | if (nand_scan_tail(&info->mtd)) { | ||
1102 | err = -ENXIO; | ||
1103 | goto out_release_mem_region; | ||
1104 | } | ||
1105 | |||
1105 | err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); | 1106 | err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); |
1106 | if (err > 0) | 1107 | if (err > 0) |
1107 | add_mtd_partitions(&info->mtd, info->parts, err); | 1108 | mtd_device_register(&info->mtd, info->parts, err); |
1108 | else if (pdata->parts) | 1109 | else if (pdata->parts) |
1109 | add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts); | 1110 | mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts); |
1110 | else | 1111 | else |
1111 | #endif | 1112 | mtd_device_register(&info->mtd, NULL, 0); |
1112 | add_mtd_device(&info->mtd); | ||
1113 | 1113 | ||
1114 | platform_set_drvdata(pdev, &info->mtd); | 1114 | platform_set_drvdata(pdev, &info->mtd); |
1115 | 1115 | ||
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index da6e75343052..7794d0680f91 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
@@ -21,9 +21,7 @@ | |||
21 | #include <mach/hardware.h> | 21 | #include <mach/hardware.h> |
22 | #include <plat/orion_nand.h> | 22 | #include <plat/orion_nand.h> |
23 | 23 | ||
24 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
25 | static const char *part_probes[] = { "cmdlinepart", NULL }; | 24 | static const char *part_probes[] = { "cmdlinepart", NULL }; |
26 | #endif | ||
27 | 25 | ||
28 | static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | 26 | static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) |
29 | { | 27 | { |
@@ -83,10 +81,8 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
83 | struct resource *res; | 81 | struct resource *res; |
84 | void __iomem *io_base; | 82 | void __iomem *io_base; |
85 | int ret = 0; | 83 | int ret = 0; |
86 | #ifdef CONFIG_MTD_PARTITIONS | ||
87 | struct mtd_partition *partitions = NULL; | 84 | struct mtd_partition *partitions = NULL; |
88 | int num_part = 0; | 85 | int num_part = 0; |
89 | #endif | ||
90 | 86 | ||
91 | nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL); | 87 | nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL); |
92 | if (!nc) { | 88 | if (!nc) { |
@@ -136,7 +132,6 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
136 | goto no_dev; | 132 | goto no_dev; |
137 | } | 133 | } |
138 | 134 | ||
139 | #ifdef CONFIG_MTD_PARTITIONS | ||
140 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 135 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
141 | mtd->name = "orion_nand"; | 136 | mtd->name = "orion_nand"; |
142 | num_part = parse_mtd_partitions(mtd, part_probes, &partitions, 0); | 137 | num_part = parse_mtd_partitions(mtd, part_probes, &partitions, 0); |
@@ -147,14 +142,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
147 | partitions = board->parts; | 142 | partitions = board->parts; |
148 | } | 143 | } |
149 | 144 | ||
150 | if (partitions && num_part > 0) | 145 | ret = mtd_device_register(mtd, partitions, num_part); |
151 | ret = add_mtd_partitions(mtd, partitions, num_part); | ||
152 | else | ||
153 | ret = add_mtd_device(mtd); | ||
154 | #else | ||
155 | ret = add_mtd_device(mtd); | ||
156 | #endif | ||
157 | |||
158 | if (ret) { | 146 | if (ret) { |
159 | nand_release(mtd); | 147 | nand_release(mtd); |
160 | goto no_dev; | 148 | goto no_dev; |
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 20bfe5f15afd..b1aa41b8a4eb 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c | |||
@@ -163,7 +163,7 @@ static int __devinit pasemi_nand_probe(struct platform_device *ofdev) | |||
163 | goto out_lpc; | 163 | goto out_lpc; |
164 | } | 164 | } |
165 | 165 | ||
166 | if (add_mtd_device(pasemi_nand_mtd)) { | 166 | if (mtd_device_register(pasemi_nand_mtd, NULL, 0)) { |
167 | printk(KERN_ERR "pasemi_nand: Unable to register MTD device\n"); | 167 | printk(KERN_ERR "pasemi_nand: Unable to register MTD device\n"); |
168 | err = -ENODEV; | 168 | err = -ENODEV; |
169 | goto out_lpc; | 169 | goto out_lpc; |
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index caf5a736340a..633c04bf76f6 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
@@ -21,10 +21,8 @@ struct plat_nand_data { | |||
21 | struct nand_chip chip; | 21 | struct nand_chip chip; |
22 | struct mtd_info mtd; | 22 | struct mtd_info mtd; |
23 | void __iomem *io_base; | 23 | void __iomem *io_base; |
24 | #ifdef CONFIG_MTD_PARTITIONS | ||
25 | int nr_parts; | 24 | int nr_parts; |
26 | struct mtd_partition *parts; | 25 | struct mtd_partition *parts; |
27 | #endif | ||
28 | }; | 26 | }; |
29 | 27 | ||
30 | /* | 28 | /* |
@@ -101,13 +99,12 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
101 | goto out; | 99 | goto out; |
102 | } | 100 | } |
103 | 101 | ||
104 | #ifdef CONFIG_MTD_PARTITIONS | ||
105 | if (pdata->chip.part_probe_types) { | 102 | if (pdata->chip.part_probe_types) { |
106 | err = parse_mtd_partitions(&data->mtd, | 103 | err = parse_mtd_partitions(&data->mtd, |
107 | pdata->chip.part_probe_types, | 104 | pdata->chip.part_probe_types, |
108 | &data->parts, 0); | 105 | &data->parts, 0); |
109 | if (err > 0) { | 106 | if (err > 0) { |
110 | add_mtd_partitions(&data->mtd, data->parts, err); | 107 | mtd_device_register(&data->mtd, data->parts, err); |
111 | return 0; | 108 | return 0; |
112 | } | 109 | } |
113 | } | 110 | } |
@@ -115,11 +112,10 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
115 | pdata->chip.set_parts(data->mtd.size, &pdata->chip); | 112 | pdata->chip.set_parts(data->mtd.size, &pdata->chip); |
116 | if (pdata->chip.partitions) { | 113 | if (pdata->chip.partitions) { |
117 | data->parts = pdata->chip.partitions; | 114 | data->parts = pdata->chip.partitions; |
118 | err = add_mtd_partitions(&data->mtd, data->parts, | 115 | err = mtd_device_register(&data->mtd, data->parts, |
119 | pdata->chip.nr_partitions); | 116 | pdata->chip.nr_partitions); |
120 | } else | 117 | } else |
121 | #endif | 118 | err = mtd_device_register(&data->mtd, NULL, 0); |
122 | err = add_mtd_device(&data->mtd); | ||
123 | 119 | ||
124 | if (!err) | 120 | if (!err) |
125 | return err; | 121 | return err; |
@@ -149,10 +145,8 @@ static int __devexit plat_nand_remove(struct platform_device *pdev) | |||
149 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 145 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
150 | 146 | ||
151 | nand_release(&data->mtd); | 147 | nand_release(&data->mtd); |
152 | #ifdef CONFIG_MTD_PARTITIONS | ||
153 | if (data->parts && data->parts != pdata->chip.partitions) | 148 | if (data->parts && data->parts != pdata->chip.partitions) |
154 | kfree(data->parts); | 149 | kfree(data->parts); |
155 | #endif | ||
156 | if (pdata->ctrl.remove) | 150 | if (pdata->ctrl.remove) |
157 | pdata->ctrl.remove(pdev); | 151 | pdata->ctrl.remove(pdev); |
158 | iounmap(data->io_base); | 152 | iounmap(data->io_base); |
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c index cc8658431851..3bbb796b451c 100644 --- a/drivers/mtd/nand/ppchameleonevb.c +++ b/drivers/mtd/nand/ppchameleonevb.c | |||
@@ -73,7 +73,6 @@ __setup("ppchameleon_fio_pbase=", ppchameleon_fio_pbase); | |||
73 | __setup("ppchameleonevb_fio_pbase=", ppchameleonevb_fio_pbase); | 73 | __setup("ppchameleonevb_fio_pbase=", ppchameleonevb_fio_pbase); |
74 | #endif | 74 | #endif |
75 | 75 | ||
76 | #ifdef CONFIG_MTD_PARTITIONS | ||
77 | /* | 76 | /* |
78 | * Define static partitions for flash devices | 77 | * Define static partitions for flash devices |
79 | */ | 78 | */ |
@@ -101,7 +100,6 @@ static struct mtd_partition partition_info_evb[] = { | |||
101 | #define NUM_PARTITIONS 1 | 100 | #define NUM_PARTITIONS 1 |
102 | 101 | ||
103 | extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, const char *mtd_id); | 102 | extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, const char *mtd_id); |
104 | #endif | ||
105 | 103 | ||
106 | /* | 104 | /* |
107 | * hardware specific access to control-lines | 105 | * hardware specific access to control-lines |
@@ -189,10 +187,8 @@ static int ppchameleonevb_device_ready(struct mtd_info *minfo) | |||
189 | } | 187 | } |
190 | #endif | 188 | #endif |
191 | 189 | ||
192 | #ifdef CONFIG_MTD_PARTITIONS | ||
193 | const char *part_probes[] = { "cmdlinepart", NULL }; | 190 | const char *part_probes[] = { "cmdlinepart", NULL }; |
194 | const char *part_probes_evb[] = { "cmdlinepart", NULL }; | 191 | const char *part_probes_evb[] = { "cmdlinepart", NULL }; |
195 | #endif | ||
196 | 192 | ||
197 | /* | 193 | /* |
198 | * Main initialization routine | 194 | * Main initialization routine |
@@ -284,14 +280,13 @@ static int __init ppchameleonevb_init(void) | |||
284 | this->chip_delay = NAND_SMALL_DELAY_US; | 280 | this->chip_delay = NAND_SMALL_DELAY_US; |
285 | #endif | 281 | #endif |
286 | 282 | ||
287 | #ifdef CONFIG_MTD_PARTITIONS | ||
288 | ppchameleon_mtd->name = "ppchameleon-nand"; | 283 | ppchameleon_mtd->name = "ppchameleon-nand"; |
289 | mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0); | 284 | mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0); |
290 | if (mtd_parts_nb > 0) | 285 | if (mtd_parts_nb > 0) |
291 | part_type = "command line"; | 286 | part_type = "command line"; |
292 | else | 287 | else |
293 | mtd_parts_nb = 0; | 288 | mtd_parts_nb = 0; |
294 | #endif | 289 | |
295 | if (mtd_parts_nb == 0) { | 290 | if (mtd_parts_nb == 0) { |
296 | if (ppchameleon_mtd->size == NAND_SMALL_SIZE) | 291 | if (ppchameleon_mtd->size == NAND_SMALL_SIZE) |
297 | mtd_parts = partition_info_me; | 292 | mtd_parts = partition_info_me; |
@@ -303,7 +298,7 @@ static int __init ppchameleonevb_init(void) | |||
303 | 298 | ||
304 | /* Register the partitions */ | 299 | /* Register the partitions */ |
305 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | 300 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); |
306 | add_mtd_partitions(ppchameleon_mtd, mtd_parts, mtd_parts_nb); | 301 | mtd_device_register(ppchameleon_mtd, mtd_parts, mtd_parts_nb); |
307 | 302 | ||
308 | nand_evb_init: | 303 | nand_evb_init: |
309 | /**************************** | 304 | /**************************** |
@@ -385,14 +380,14 @@ static int __init ppchameleonevb_init(void) | |||
385 | iounmap(ppchameleon_fio_base); | 380 | iounmap(ppchameleon_fio_base); |
386 | return -ENXIO; | 381 | return -ENXIO; |
387 | } | 382 | } |
388 | #ifdef CONFIG_MTD_PARTITIONS | 383 | |
389 | ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME; | 384 | ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME; |
390 | mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0); | 385 | mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0); |
391 | if (mtd_parts_nb > 0) | 386 | if (mtd_parts_nb > 0) |
392 | part_type = "command line"; | 387 | part_type = "command line"; |
393 | else | 388 | else |
394 | mtd_parts_nb = 0; | 389 | mtd_parts_nb = 0; |
395 | #endif | 390 | |
396 | if (mtd_parts_nb == 0) { | 391 | if (mtd_parts_nb == 0) { |
397 | mtd_parts = partition_info_evb; | 392 | mtd_parts = partition_info_evb; |
398 | mtd_parts_nb = NUM_PARTITIONS; | 393 | mtd_parts_nb = NUM_PARTITIONS; |
@@ -401,7 +396,7 @@ static int __init ppchameleonevb_init(void) | |||
401 | 396 | ||
402 | /* Register the partitions */ | 397 | /* Register the partitions */ |
403 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | 398 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); |
404 | add_mtd_partitions(ppchameleonevb_mtd, mtd_parts, mtd_parts_nb); | 399 | mtd_device_register(ppchameleonevb_mtd, mtd_parts, mtd_parts_nb); |
405 | 400 | ||
406 | /* Return happy */ | 401 | /* Return happy */ |
407 | return 0; | 402 | return 0; |
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index ff0701276d65..1fb3b3a80581 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -1119,10 +1119,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
1119 | clk_put(info->clk); | 1119 | clk_put(info->clk); |
1120 | 1120 | ||
1121 | if (mtd) { | 1121 | if (mtd) { |
1122 | del_mtd_device(mtd); | 1122 | mtd_device_unregister(mtd); |
1123 | #ifdef CONFIG_MTD_PARTITIONS | ||
1124 | del_mtd_partitions(mtd); | ||
1125 | #endif | ||
1126 | kfree(mtd); | 1123 | kfree(mtd); |
1127 | } | 1124 | } |
1128 | return 0; | 1125 | return 0; |
@@ -1149,7 +1146,6 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1149 | return -ENODEV; | 1146 | return -ENODEV; |
1150 | } | 1147 | } |
1151 | 1148 | ||
1152 | #ifdef CONFIG_MTD_PARTITIONS | ||
1153 | if (mtd_has_cmdlinepart()) { | 1149 | if (mtd_has_cmdlinepart()) { |
1154 | const char *probes[] = { "cmdlinepart", NULL }; | 1150 | const char *probes[] = { "cmdlinepart", NULL }; |
1155 | struct mtd_partition *parts; | 1151 | struct mtd_partition *parts; |
@@ -1158,13 +1154,10 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1158 | nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0); | 1154 | nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0); |
1159 | 1155 | ||
1160 | if (nr_parts) | 1156 | if (nr_parts) |
1161 | return add_mtd_partitions(info->mtd, parts, nr_parts); | 1157 | return mtd_device_register(info->mtd, parts, nr_parts); |
1162 | } | 1158 | } |
1163 | 1159 | ||
1164 | return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts); | 1160 | return mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts); |
1165 | #else | ||
1166 | return 0; | ||
1167 | #endif | ||
1168 | } | 1161 | } |
1169 | 1162 | ||
1170 | #ifdef CONFIG_PM | 1163 | #ifdef CONFIG_PM |
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c index 67440b5beef8..c9f9127ff770 100644 --- a/drivers/mtd/nand/rtc_from4.c +++ b/drivers/mtd/nand/rtc_from4.c | |||
@@ -580,7 +580,8 @@ static int __init rtc_from4_init(void) | |||
580 | #endif | 580 | #endif |
581 | 581 | ||
582 | /* Register the partitions */ | 582 | /* Register the partitions */ |
583 | ret = add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS); | 583 | ret = mtd_device_register(rtc_from4_mtd, partition_info, |
584 | NUM_PARTITIONS); | ||
584 | if (ret) | 585 | if (ret) |
585 | goto err_3; | 586 | goto err_3; |
586 | 587 | ||
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 33d832dddfdd..4405468f196b 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -55,7 +55,7 @@ static int hardware_ecc = 0; | |||
55 | #endif | 55 | #endif |
56 | 56 | ||
57 | #ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP | 57 | #ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP |
58 | static int clock_stop = 1; | 58 | static const int clock_stop = 1; |
59 | #else | 59 | #else |
60 | static const int clock_stop = 0; | 60 | static const int clock_stop = 0; |
61 | #endif | 61 | #endif |
@@ -96,6 +96,12 @@ enum s3c_cpu_type { | |||
96 | TYPE_S3C2440, | 96 | TYPE_S3C2440, |
97 | }; | 97 | }; |
98 | 98 | ||
99 | enum s3c_nand_clk_state { | ||
100 | CLOCK_DISABLE = 0, | ||
101 | CLOCK_ENABLE, | ||
102 | CLOCK_SUSPEND, | ||
103 | }; | ||
104 | |||
99 | /* overview of the s3c2410 nand state */ | 105 | /* overview of the s3c2410 nand state */ |
100 | 106 | ||
101 | /** | 107 | /** |
@@ -111,6 +117,7 @@ enum s3c_cpu_type { | |||
111 | * @mtd_count: The number of MTDs created from this controller. | 117 | * @mtd_count: The number of MTDs created from this controller. |
112 | * @save_sel: The contents of @sel_reg to be saved over suspend. | 118 | * @save_sel: The contents of @sel_reg to be saved over suspend. |
113 | * @clk_rate: The clock rate from @clk. | 119 | * @clk_rate: The clock rate from @clk. |
120 | * @clk_state: The current clock state. | ||
114 | * @cpu_type: The exact type of this controller. | 121 | * @cpu_type: The exact type of this controller. |
115 | */ | 122 | */ |
116 | struct s3c2410_nand_info { | 123 | struct s3c2410_nand_info { |
@@ -129,6 +136,7 @@ struct s3c2410_nand_info { | |||
129 | int mtd_count; | 136 | int mtd_count; |
130 | unsigned long save_sel; | 137 | unsigned long save_sel; |
131 | unsigned long clk_rate; | 138 | unsigned long clk_rate; |
139 | enum s3c_nand_clk_state clk_state; | ||
132 | 140 | ||
133 | enum s3c_cpu_type cpu_type; | 141 | enum s3c_cpu_type cpu_type; |
134 | 142 | ||
@@ -159,11 +167,33 @@ static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev) | |||
159 | return dev->dev.platform_data; | 167 | return dev->dev.platform_data; |
160 | } | 168 | } |
161 | 169 | ||
162 | static inline int allow_clk_stop(struct s3c2410_nand_info *info) | 170 | static inline int allow_clk_suspend(struct s3c2410_nand_info *info) |
163 | { | 171 | { |
164 | return clock_stop; | 172 | return clock_stop; |
165 | } | 173 | } |
166 | 174 | ||
175 | /** | ||
176 | * s3c2410_nand_clk_set_state - Enable, disable or suspend NAND clock. | ||
177 | * @info: The controller instance. | ||
178 | * @new_state: State to which clock should be set. | ||
179 | */ | ||
180 | static void s3c2410_nand_clk_set_state(struct s3c2410_nand_info *info, | ||
181 | enum s3c_nand_clk_state new_state) | ||
182 | { | ||
183 | if (!allow_clk_suspend(info) && new_state == CLOCK_SUSPEND) | ||
184 | return; | ||
185 | |||
186 | if (info->clk_state == CLOCK_ENABLE) { | ||
187 | if (new_state != CLOCK_ENABLE) | ||
188 | clk_disable(info->clk); | ||
189 | } else { | ||
190 | if (new_state == CLOCK_ENABLE) | ||
191 | clk_enable(info->clk); | ||
192 | } | ||
193 | |||
194 | info->clk_state = new_state; | ||
195 | } | ||
196 | |||
167 | /* timing calculations */ | 197 | /* timing calculations */ |
168 | 198 | ||
169 | #define NS_IN_KHZ 1000000 | 199 | #define NS_IN_KHZ 1000000 |
@@ -333,8 +363,8 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) | |||
333 | nmtd = this->priv; | 363 | nmtd = this->priv; |
334 | info = nmtd->info; | 364 | info = nmtd->info; |
335 | 365 | ||
336 | if (chip != -1 && allow_clk_stop(info)) | 366 | if (chip != -1) |
337 | clk_enable(info->clk); | 367 | s3c2410_nand_clk_set_state(info, CLOCK_ENABLE); |
338 | 368 | ||
339 | cur = readl(info->sel_reg); | 369 | cur = readl(info->sel_reg); |
340 | 370 | ||
@@ -356,8 +386,8 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) | |||
356 | 386 | ||
357 | writel(cur, info->sel_reg); | 387 | writel(cur, info->sel_reg); |
358 | 388 | ||
359 | if (chip == -1 && allow_clk_stop(info)) | 389 | if (chip == -1) |
360 | clk_disable(info->clk); | 390 | s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND); |
361 | } | 391 | } |
362 | 392 | ||
363 | /* s3c2410_nand_hwcontrol | 393 | /* s3c2410_nand_hwcontrol |
@@ -694,8 +724,7 @@ static int s3c24xx_nand_remove(struct platform_device *pdev) | |||
694 | /* free the common resources */ | 724 | /* free the common resources */ |
695 | 725 | ||
696 | if (info->clk != NULL && !IS_ERR(info->clk)) { | 726 | if (info->clk != NULL && !IS_ERR(info->clk)) { |
697 | if (!allow_clk_stop(info)) | 727 | s3c2410_nand_clk_set_state(info, CLOCK_DISABLE); |
698 | clk_disable(info->clk); | ||
699 | clk_put(info->clk); | 728 | clk_put(info->clk); |
700 | } | 729 | } |
701 | 730 | ||
@@ -715,7 +744,6 @@ static int s3c24xx_nand_remove(struct platform_device *pdev) | |||
715 | return 0; | 744 | return 0; |
716 | } | 745 | } |
717 | 746 | ||
718 | #ifdef CONFIG_MTD_PARTITIONS | ||
719 | const char *part_probes[] = { "cmdlinepart", NULL }; | 747 | const char *part_probes[] = { "cmdlinepart", NULL }; |
720 | static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | 748 | static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, |
721 | struct s3c2410_nand_mtd *mtd, | 749 | struct s3c2410_nand_mtd *mtd, |
@@ -725,7 +753,7 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | |||
725 | int nr_part = 0; | 753 | int nr_part = 0; |
726 | 754 | ||
727 | if (set == NULL) | 755 | if (set == NULL) |
728 | return add_mtd_device(&mtd->mtd); | 756 | return mtd_device_register(&mtd->mtd, NULL, 0); |
729 | 757 | ||
730 | mtd->mtd.name = set->name; | 758 | mtd->mtd.name = set->name; |
731 | nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0); | 759 | nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0); |
@@ -735,19 +763,8 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | |||
735 | part_info = set->partitions; | 763 | part_info = set->partitions; |
736 | } | 764 | } |
737 | 765 | ||
738 | if (nr_part > 0 && part_info) | 766 | return mtd_device_register(&mtd->mtd, part_info, nr_part); |
739 | return add_mtd_partitions(&mtd->mtd, part_info, nr_part); | ||
740 | |||
741 | return add_mtd_device(&mtd->mtd); | ||
742 | } | ||
743 | #else | ||
744 | static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | ||
745 | struct s3c2410_nand_mtd *mtd, | ||
746 | struct s3c2410_nand_set *set) | ||
747 | { | ||
748 | return add_mtd_device(&mtd->mtd); | ||
749 | } | 767 | } |
750 | #endif | ||
751 | 768 | ||
752 | /** | 769 | /** |
753 | * s3c2410_nand_init_chip - initialise a single instance of an chip | 770 | * s3c2410_nand_init_chip - initialise a single instance of an chip |
@@ -947,7 +964,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev) | |||
947 | goto exit_error; | 964 | goto exit_error; |
948 | } | 965 | } |
949 | 966 | ||
950 | clk_enable(info->clk); | 967 | s3c2410_nand_clk_set_state(info, CLOCK_ENABLE); |
951 | 968 | ||
952 | /* allocate and map the resource */ | 969 | /* allocate and map the resource */ |
953 | 970 | ||
@@ -1026,9 +1043,9 @@ static int s3c24xx_nand_probe(struct platform_device *pdev) | |||
1026 | goto exit_error; | 1043 | goto exit_error; |
1027 | } | 1044 | } |
1028 | 1045 | ||
1029 | if (allow_clk_stop(info)) { | 1046 | if (allow_clk_suspend(info)) { |
1030 | dev_info(&pdev->dev, "clock idle support enabled\n"); | 1047 | dev_info(&pdev->dev, "clock idle support enabled\n"); |
1031 | clk_disable(info->clk); | 1048 | s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND); |
1032 | } | 1049 | } |
1033 | 1050 | ||
1034 | pr_debug("initialised ok\n"); | 1051 | pr_debug("initialised ok\n"); |
@@ -1059,8 +1076,7 @@ static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm) | |||
1059 | 1076 | ||
1060 | writel(info->save_sel | info->sel_bit, info->sel_reg); | 1077 | writel(info->save_sel | info->sel_bit, info->sel_reg); |
1061 | 1078 | ||
1062 | if (!allow_clk_stop(info)) | 1079 | s3c2410_nand_clk_set_state(info, CLOCK_DISABLE); |
1063 | clk_disable(info->clk); | ||
1064 | } | 1080 | } |
1065 | 1081 | ||
1066 | return 0; | 1082 | return 0; |
@@ -1072,7 +1088,7 @@ static int s3c24xx_nand_resume(struct platform_device *dev) | |||
1072 | unsigned long sel; | 1088 | unsigned long sel; |
1073 | 1089 | ||
1074 | if (info) { | 1090 | if (info) { |
1075 | clk_enable(info->clk); | 1091 | s3c2410_nand_clk_set_state(info, CLOCK_ENABLE); |
1076 | s3c2410_nand_inithw(info); | 1092 | s3c2410_nand_inithw(info); |
1077 | 1093 | ||
1078 | /* Restore the state of the nFCE line. */ | 1094 | /* Restore the state of the nFCE line. */ |
@@ -1082,8 +1098,7 @@ static int s3c24xx_nand_resume(struct platform_device *dev) | |||
1082 | sel |= info->save_sel & info->sel_bit; | 1098 | sel |= info->save_sel & info->sel_bit; |
1083 | writel(sel, info->sel_reg); | 1099 | writel(sel, info->sel_reg); |
1084 | 1100 | ||
1085 | if (allow_clk_stop(info)) | 1101 | s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND); |
1086 | clk_disable(info->clk); | ||
1087 | } | 1102 | } |
1088 | 1103 | ||
1089 | return 0; | 1104 | return 0; |
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index 81bbb5ee148d..93b1f74321c2 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c | |||
@@ -867,7 +867,7 @@ static int __devinit flctl_probe(struct platform_device *pdev) | |||
867 | if (ret) | 867 | if (ret) |
868 | goto err; | 868 | goto err; |
869 | 869 | ||
870 | add_mtd_partitions(flctl_mtd, pdata->parts, pdata->nr_parts); | 870 | mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts); |
871 | 871 | ||
872 | return 0; | 872 | return 0; |
873 | 873 | ||
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 54ec7542a7b7..19e24ed089ea 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c | |||
@@ -103,9 +103,7 @@ static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, | |||
103 | return readb(sharpsl->io + ECCCNTR) != 0; | 103 | return readb(sharpsl->io + ECCCNTR) != 0; |
104 | } | 104 | } |
105 | 105 | ||
106 | #ifdef CONFIG_MTD_PARTITIONS | ||
107 | static const char *part_probes[] = { "cmdlinepart", NULL }; | 106 | static const char *part_probes[] = { "cmdlinepart", NULL }; |
108 | #endif | ||
109 | 107 | ||
110 | /* | 108 | /* |
111 | * Main initialization routine | 109 | * Main initialization routine |
@@ -113,10 +111,8 @@ static const char *part_probes[] = { "cmdlinepart", NULL }; | |||
113 | static int __devinit sharpsl_nand_probe(struct platform_device *pdev) | 111 | static int __devinit sharpsl_nand_probe(struct platform_device *pdev) |
114 | { | 112 | { |
115 | struct nand_chip *this; | 113 | struct nand_chip *this; |
116 | #ifdef CONFIG_MTD_PARTITIONS | ||
117 | struct mtd_partition *sharpsl_partition_info; | 114 | struct mtd_partition *sharpsl_partition_info; |
118 | int nr_partitions; | 115 | int nr_partitions; |
119 | #endif | ||
120 | struct resource *r; | 116 | struct resource *r; |
121 | int err = 0; | 117 | int err = 0; |
122 | struct sharpsl_nand *sharpsl; | 118 | struct sharpsl_nand *sharpsl; |
@@ -188,18 +184,14 @@ static int __devinit sharpsl_nand_probe(struct platform_device *pdev) | |||
188 | 184 | ||
189 | /* Register the partitions */ | 185 | /* Register the partitions */ |
190 | sharpsl->mtd.name = "sharpsl-nand"; | 186 | sharpsl->mtd.name = "sharpsl-nand"; |
191 | #ifdef CONFIG_MTD_PARTITIONS | ||
192 | nr_partitions = parse_mtd_partitions(&sharpsl->mtd, part_probes, &sharpsl_partition_info, 0); | 187 | nr_partitions = parse_mtd_partitions(&sharpsl->mtd, part_probes, &sharpsl_partition_info, 0); |
193 | if (nr_partitions <= 0) { | 188 | if (nr_partitions <= 0) { |
194 | nr_partitions = data->nr_partitions; | 189 | nr_partitions = data->nr_partitions; |
195 | sharpsl_partition_info = data->partitions; | 190 | sharpsl_partition_info = data->partitions; |
196 | } | 191 | } |
197 | 192 | ||
198 | if (nr_partitions > 0) | 193 | err = mtd_device_register(&sharpsl->mtd, sharpsl_partition_info, |
199 | err = add_mtd_partitions(&sharpsl->mtd, sharpsl_partition_info, nr_partitions); | 194 | nr_partitions); |
200 | else | ||
201 | #endif | ||
202 | err = add_mtd_device(&sharpsl->mtd); | ||
203 | if (err) | 195 | if (err) |
204 | goto err_add; | 196 | goto err_add; |
205 | 197 | ||
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c index 57cc80cd01a3..b6332e83b289 100644 --- a/drivers/mtd/nand/sm_common.c +++ b/drivers/mtd/nand/sm_common.c | |||
@@ -139,7 +139,7 @@ int sm_register_device(struct mtd_info *mtd, int smartmedia) | |||
139 | if (ret) | 139 | if (ret) |
140 | return ret; | 140 | return ret; |
141 | 141 | ||
142 | return add_mtd_device(mtd); | 142 | return mtd_device_register(mtd, NULL, 0); |
143 | } | 143 | } |
144 | EXPORT_SYMBOL_GPL(sm_register_device); | 144 | EXPORT_SYMBOL_GPL(sm_register_device); |
145 | 145 | ||
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index a853548986f0..ca2d0555729e 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c | |||
@@ -155,9 +155,7 @@ static int socrates_nand_device_ready(struct mtd_info *mtd) | |||
155 | return 1; | 155 | return 1; |
156 | } | 156 | } |
157 | 157 | ||
158 | #ifdef CONFIG_MTD_PARTITIONS | ||
159 | static const char *part_probes[] = { "cmdlinepart", NULL }; | 158 | static const char *part_probes[] = { "cmdlinepart", NULL }; |
160 | #endif | ||
161 | 159 | ||
162 | /* | 160 | /* |
163 | * Probe for the NAND device. | 161 | * Probe for the NAND device. |
@@ -168,11 +166,8 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev) | |||
168 | struct mtd_info *mtd; | 166 | struct mtd_info *mtd; |
169 | struct nand_chip *nand_chip; | 167 | struct nand_chip *nand_chip; |
170 | int res; | 168 | int res; |
171 | |||
172 | #ifdef CONFIG_MTD_PARTITIONS | ||
173 | struct mtd_partition *partitions = NULL; | 169 | struct mtd_partition *partitions = NULL; |
174 | int num_partitions = 0; | 170 | int num_partitions = 0; |
175 | #endif | ||
176 | 171 | ||
177 | /* Allocate memory for the device structure (and zero it) */ | 172 | /* Allocate memory for the device structure (and zero it) */ |
178 | host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL); | 173 | host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL); |
@@ -230,7 +225,6 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev) | |||
230 | goto out; | 225 | goto out; |
231 | } | 226 | } |
232 | 227 | ||
233 | #ifdef CONFIG_MTD_PARTITIONS | ||
234 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 228 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
235 | num_partitions = parse_mtd_partitions(mtd, part_probes, | 229 | num_partitions = parse_mtd_partitions(mtd, part_probes, |
236 | &partitions, 0); | 230 | &partitions, 0); |
@@ -240,7 +234,6 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev) | |||
240 | } | 234 | } |
241 | #endif | 235 | #endif |
242 | 236 | ||
243 | #ifdef CONFIG_MTD_OF_PARTS | ||
244 | if (num_partitions == 0) { | 237 | if (num_partitions == 0) { |
245 | num_partitions = of_mtd_parse_partitions(&ofdev->dev, | 238 | num_partitions = of_mtd_parse_partitions(&ofdev->dev, |
246 | ofdev->dev.of_node, | 239 | ofdev->dev.of_node, |
@@ -250,19 +243,12 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev) | |||
250 | goto release; | 243 | goto release; |
251 | } | 244 | } |
252 | } | 245 | } |
253 | #endif | ||
254 | if (partitions && (num_partitions > 0)) | ||
255 | res = add_mtd_partitions(mtd, partitions, num_partitions); | ||
256 | else | ||
257 | #endif | ||
258 | res = add_mtd_device(mtd); | ||
259 | 246 | ||
247 | res = mtd_device_register(mtd, partitions, num_partitions); | ||
260 | if (!res) | 248 | if (!res) |
261 | return res; | 249 | return res; |
262 | 250 | ||
263 | #ifdef CONFIG_MTD_PARTITIONS | ||
264 | release: | 251 | release: |
265 | #endif | ||
266 | nand_release(mtd); | 252 | nand_release(mtd); |
267 | 253 | ||
268 | out: | 254 | out: |
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c index 0cc6d0acb8fe..bef76cd7c24c 100644 --- a/drivers/mtd/nand/spia.c +++ b/drivers/mtd/nand/spia.c | |||
@@ -149,7 +149,7 @@ static int __init spia_init(void) | |||
149 | } | 149 | } |
150 | 150 | ||
151 | /* Register the partitions */ | 151 | /* Register the partitions */ |
152 | add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS); | 152 | mtd_device_register(spia_mtd, partition_info, NUM_PARTITIONS); |
153 | 153 | ||
154 | /* Return happy */ | 154 | /* Return happy */ |
155 | return 0; | 155 | return 0; |
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index c004e474631b..11e8371b5683 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c | |||
@@ -381,10 +381,8 @@ static int tmio_probe(struct platform_device *dev) | |||
381 | struct tmio_nand *tmio; | 381 | struct tmio_nand *tmio; |
382 | struct mtd_info *mtd; | 382 | struct mtd_info *mtd; |
383 | struct nand_chip *nand_chip; | 383 | struct nand_chip *nand_chip; |
384 | #ifdef CONFIG_MTD_PARTITIONS | ||
385 | struct mtd_partition *parts; | 384 | struct mtd_partition *parts; |
386 | int nbparts = 0; | 385 | int nbparts = 0; |
387 | #endif | ||
388 | int retval; | 386 | int retval; |
389 | 387 | ||
390 | if (data == NULL) | 388 | if (data == NULL) |
@@ -463,7 +461,6 @@ static int tmio_probe(struct platform_device *dev) | |||
463 | goto err_scan; | 461 | goto err_scan; |
464 | } | 462 | } |
465 | /* Register the partitions */ | 463 | /* Register the partitions */ |
466 | #ifdef CONFIG_MTD_PARTITIONS | ||
467 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 464 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
468 | nbparts = parse_mtd_partitions(mtd, part_probes, &parts, 0); | 465 | nbparts = parse_mtd_partitions(mtd, part_probes, &parts, 0); |
469 | #endif | 466 | #endif |
@@ -472,12 +469,7 @@ static int tmio_probe(struct platform_device *dev) | |||
472 | nbparts = data->num_partitions; | 469 | nbparts = data->num_partitions; |
473 | } | 470 | } |
474 | 471 | ||
475 | if (nbparts) | 472 | retval = mtd_device_register(mtd, parts, nbparts); |
476 | retval = add_mtd_partitions(mtd, parts, nbparts); | ||
477 | else | ||
478 | #endif | ||
479 | retval = add_mtd_device(mtd); | ||
480 | |||
481 | if (!retval) | 473 | if (!retval) |
482 | return retval; | 474 | return retval; |
483 | 475 | ||
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c index ca270a4881a4..bfba4e39a6c5 100644 --- a/drivers/mtd/nand/txx9ndfmc.c +++ b/drivers/mtd/nand/txx9ndfmc.c | |||
@@ -74,9 +74,7 @@ struct txx9ndfmc_drvdata { | |||
74 | unsigned char hold; /* in gbusclock */ | 74 | unsigned char hold; /* in gbusclock */ |
75 | unsigned char spw; /* in gbusclock */ | 75 | unsigned char spw; /* in gbusclock */ |
76 | struct nand_hw_control hw_control; | 76 | struct nand_hw_control hw_control; |
77 | #ifdef CONFIG_MTD_PARTITIONS | ||
78 | struct mtd_partition *parts[MAX_TXX9NDFMC_DEV]; | 77 | struct mtd_partition *parts[MAX_TXX9NDFMC_DEV]; |
79 | #endif | ||
80 | }; | 78 | }; |
81 | 79 | ||
82 | static struct platform_device *mtd_to_platdev(struct mtd_info *mtd) | 80 | static struct platform_device *mtd_to_platdev(struct mtd_info *mtd) |
@@ -289,9 +287,7 @@ static int txx9ndfmc_nand_scan(struct mtd_info *mtd) | |||
289 | static int __init txx9ndfmc_probe(struct platform_device *dev) | 287 | static int __init txx9ndfmc_probe(struct platform_device *dev) |
290 | { | 288 | { |
291 | struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; | 289 | struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; |
292 | #ifdef CONFIG_MTD_PARTITIONS | ||
293 | static const char *probes[] = { "cmdlinepart", NULL }; | 290 | static const char *probes[] = { "cmdlinepart", NULL }; |
294 | #endif | ||
295 | int hold, spw; | 291 | int hold, spw; |
296 | int i; | 292 | int i; |
297 | struct txx9ndfmc_drvdata *drvdata; | 293 | struct txx9ndfmc_drvdata *drvdata; |
@@ -337,9 +333,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) | |||
337 | struct txx9ndfmc_priv *txx9_priv; | 333 | struct txx9ndfmc_priv *txx9_priv; |
338 | struct nand_chip *chip; | 334 | struct nand_chip *chip; |
339 | struct mtd_info *mtd; | 335 | struct mtd_info *mtd; |
340 | #ifdef CONFIG_MTD_PARTITIONS | ||
341 | int nr_parts; | 336 | int nr_parts; |
342 | #endif | ||
343 | 337 | ||
344 | if (!(plat->ch_mask & (1 << i))) | 338 | if (!(plat->ch_mask & (1 << i))) |
345 | continue; | 339 | continue; |
@@ -399,13 +393,9 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) | |||
399 | } | 393 | } |
400 | mtd->name = txx9_priv->mtdname; | 394 | mtd->name = txx9_priv->mtdname; |
401 | 395 | ||
402 | #ifdef CONFIG_MTD_PARTITIONS | ||
403 | nr_parts = parse_mtd_partitions(mtd, probes, | 396 | nr_parts = parse_mtd_partitions(mtd, probes, |
404 | &drvdata->parts[i], 0); | 397 | &drvdata->parts[i], 0); |
405 | if (nr_parts > 0) | 398 | mtd_device_register(mtd, drvdata->parts[i], nr_parts); |
406 | add_mtd_partitions(mtd, drvdata->parts[i], nr_parts); | ||
407 | #endif | ||
408 | add_mtd_device(mtd); | ||
409 | drvdata->mtds[i] = mtd; | 399 | drvdata->mtds[i] = mtd; |
410 | } | 400 | } |
411 | 401 | ||
@@ -431,9 +421,7 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev) | |||
431 | txx9_priv = chip->priv; | 421 | txx9_priv = chip->priv; |
432 | 422 | ||
433 | nand_release(mtd); | 423 | nand_release(mtd); |
434 | #ifdef CONFIG_MTD_PARTITIONS | ||
435 | kfree(drvdata->parts[i]); | 424 | kfree(drvdata->parts[i]); |
436 | #endif | ||
437 | kfree(txx9_priv->mtdname); | 425 | kfree(txx9_priv->mtdname); |
438 | kfree(txx9_priv); | 426 | kfree(txx9_priv); |
439 | } | 427 | } |
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 4f426195f8db..772ad2966619 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig | |||
@@ -1,7 +1,6 @@ | |||
1 | menuconfig MTD_ONENAND | 1 | menuconfig MTD_ONENAND |
2 | tristate "OneNAND Device Support" | 2 | tristate "OneNAND Device Support" |
3 | depends on MTD | 3 | depends on MTD |
4 | select MTD_PARTITIONS | ||
5 | help | 4 | help |
6 | This enables support for accessing all type of OneNAND flash | 5 | This enables support for accessing all type of OneNAND flash |
7 | devices. For further information see | 6 | devices. For further information see |
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index ac08750748a3..2d70d354d846 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c | |||
@@ -30,9 +30,7 @@ | |||
30 | */ | 30 | */ |
31 | #define DRIVER_NAME "onenand-flash" | 31 | #define DRIVER_NAME "onenand-flash" |
32 | 32 | ||
33 | #ifdef CONFIG_MTD_PARTITIONS | ||
34 | static const char *part_probes[] = { "cmdlinepart", NULL, }; | 33 | static const char *part_probes[] = { "cmdlinepart", NULL, }; |
35 | #endif | ||
36 | 34 | ||
37 | struct onenand_info { | 35 | struct onenand_info { |
38 | struct mtd_info mtd; | 36 | struct mtd_info mtd; |
@@ -75,15 +73,13 @@ static int __devinit generic_onenand_probe(struct platform_device *pdev) | |||
75 | goto out_iounmap; | 73 | goto out_iounmap; |
76 | } | 74 | } |
77 | 75 | ||
78 | #ifdef CONFIG_MTD_PARTITIONS | ||
79 | err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); | 76 | err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); |
80 | if (err > 0) | 77 | if (err > 0) |
81 | add_mtd_partitions(&info->mtd, info->parts, err); | 78 | mtd_device_register(&info->mtd, info->parts, err); |
82 | else if (err <= 0 && pdata && pdata->parts) | 79 | else if (err <= 0 && pdata && pdata->parts) |
83 | add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts); | 80 | mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts); |
84 | else | 81 | else |
85 | #endif | 82 | err = mtd_device_register(&info->mtd, NULL, 0); |
86 | err = add_mtd_device(&info->mtd); | ||
87 | 83 | ||
88 | platform_set_drvdata(pdev, info); | 84 | platform_set_drvdata(pdev, info); |
89 | 85 | ||
@@ -108,11 +104,7 @@ static int __devexit generic_onenand_remove(struct platform_device *pdev) | |||
108 | platform_set_drvdata(pdev, NULL); | 104 | platform_set_drvdata(pdev, NULL); |
109 | 105 | ||
110 | if (info) { | 106 | if (info) { |
111 | if (info->parts) | 107 | mtd_device_unregister(&info->mtd); |
112 | del_mtd_partitions(&info->mtd); | ||
113 | else | ||
114 | del_mtd_device(&info->mtd); | ||
115 | |||
116 | onenand_release(&info->mtd); | 108 | onenand_release(&info->mtd); |
117 | release_mem_region(res->start, size); | 109 | release_mem_region(res->start, size); |
118 | iounmap(info->onenand.base); | 110 | iounmap(info->onenand.base); |
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 1fcb41adab07..a916dec29215 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c | |||
@@ -67,9 +67,7 @@ struct omap2_onenand { | |||
67 | struct regulator *regulator; | 67 | struct regulator *regulator; |
68 | }; | 68 | }; |
69 | 69 | ||
70 | #ifdef CONFIG_MTD_PARTITIONS | ||
71 | static const char *part_probes[] = { "cmdlinepart", NULL, }; | 70 | static const char *part_probes[] = { "cmdlinepart", NULL, }; |
72 | #endif | ||
73 | 71 | ||
74 | static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) | 72 | static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) |
75 | { | 73 | { |
@@ -755,15 +753,13 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) | |||
755 | if ((r = onenand_scan(&c->mtd, 1)) < 0) | 753 | if ((r = onenand_scan(&c->mtd, 1)) < 0) |
756 | goto err_release_regulator; | 754 | goto err_release_regulator; |
757 | 755 | ||
758 | #ifdef CONFIG_MTD_PARTITIONS | ||
759 | r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0); | 756 | r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0); |
760 | if (r > 0) | 757 | if (r > 0) |
761 | r = add_mtd_partitions(&c->mtd, c->parts, r); | 758 | r = mtd_device_register(&c->mtd, c->parts, r); |
762 | else if (pdata->parts != NULL) | 759 | else if (pdata->parts != NULL) |
763 | r = add_mtd_partitions(&c->mtd, pdata->parts, pdata->nr_parts); | 760 | r = mtd_device_register(&c->mtd, pdata->parts, pdata->nr_parts); |
764 | else | 761 | else |
765 | #endif | 762 | r = mtd_device_register(&c->mtd, NULL, 0); |
766 | r = add_mtd_device(&c->mtd); | ||
767 | if (r) | 763 | if (r) |
768 | goto err_release_onenand; | 764 | goto err_release_onenand; |
769 | 765 | ||
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 56a8b2005bda..ac9e959802a7 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
@@ -65,11 +65,11 @@ MODULE_PARM_DESC(otp, "Corresponding behaviour of OneNAND in OTP" | |||
65 | " : 2 -> 1st Block lock" | 65 | " : 2 -> 1st Block lock" |
66 | " : 3 -> BOTH OTP Block and 1st Block lock"); | 66 | " : 3 -> BOTH OTP Block and 1st Block lock"); |
67 | 67 | ||
68 | /** | 68 | /* |
69 | * onenand_oob_128 - oob info for Flex-Onenand with 4KB page | 69 | * flexonenand_oob_128 - oob info for Flex-Onenand with 4KB page |
70 | * For now, we expose only 64 out of 80 ecc bytes | 70 | * For now, we expose only 64 out of 80 ecc bytes |
71 | */ | 71 | */ |
72 | static struct nand_ecclayout onenand_oob_128 = { | 72 | static struct nand_ecclayout flexonenand_oob_128 = { |
73 | .eccbytes = 64, | 73 | .eccbytes = 64, |
74 | .eccpos = { | 74 | .eccpos = { |
75 | 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, | 75 | 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, |
@@ -86,6 +86,35 @@ static struct nand_ecclayout onenand_oob_128 = { | |||
86 | } | 86 | } |
87 | }; | 87 | }; |
88 | 88 | ||
89 | /* | ||
90 | * onenand_oob_128 - oob info for OneNAND with 4KB page | ||
91 | * | ||
92 | * Based on specification: | ||
93 | * 4Gb M-die OneNAND Flash (KFM4G16Q4M, KFN8G16Q4M). Rev. 1.3, Apr. 2010 | ||
94 | * | ||
95 | * For eccpos we expose only 64 bytes out of 72 (see struct nand_ecclayout) | ||
96 | * | ||
97 | * oobfree uses the spare area fields marked as | ||
98 | * "Managed by internal ECC logic for Logical Sector Number area" | ||
99 | */ | ||
100 | static struct nand_ecclayout onenand_oob_128 = { | ||
101 | .eccbytes = 64, | ||
102 | .eccpos = { | ||
103 | 7, 8, 9, 10, 11, 12, 13, 14, 15, | ||
104 | 23, 24, 25, 26, 27, 28, 29, 30, 31, | ||
105 | 39, 40, 41, 42, 43, 44, 45, 46, 47, | ||
106 | 55, 56, 57, 58, 59, 60, 61, 62, 63, | ||
107 | 71, 72, 73, 74, 75, 76, 77, 78, 79, | ||
108 | 87, 88, 89, 90, 91, 92, 93, 94, 95, | ||
109 | 103, 104, 105, 106, 107, 108, 109, 110, 111, | ||
110 | 119 | ||
111 | }, | ||
112 | .oobfree = { | ||
113 | {2, 3}, {18, 3}, {34, 3}, {50, 3}, | ||
114 | {66, 3}, {82, 3}, {98, 3}, {114, 3} | ||
115 | } | ||
116 | }; | ||
117 | |||
89 | /** | 118 | /** |
90 | * onenand_oob_64 - oob info for large (2KB) page | 119 | * onenand_oob_64 - oob info for large (2KB) page |
91 | */ | 120 | */ |
@@ -2424,7 +2453,7 @@ static int onenand_block_by_block_erase(struct mtd_info *mtd, | |||
2424 | len -= block_size; | 2453 | len -= block_size; |
2425 | addr += block_size; | 2454 | addr += block_size; |
2426 | 2455 | ||
2427 | if (addr == region_end) { | 2456 | if (region && addr == region_end) { |
2428 | if (!len) | 2457 | if (!len) |
2429 | break; | 2458 | break; |
2430 | region++; | 2459 | region++; |
@@ -4018,8 +4047,13 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
4018 | */ | 4047 | */ |
4019 | switch (mtd->oobsize) { | 4048 | switch (mtd->oobsize) { |
4020 | case 128: | 4049 | case 128: |
4021 | this->ecclayout = &onenand_oob_128; | 4050 | if (FLEXONENAND(this)) { |
4022 | mtd->subpage_sft = 0; | 4051 | this->ecclayout = &flexonenand_oob_128; |
4052 | mtd->subpage_sft = 0; | ||
4053 | } else { | ||
4054 | this->ecclayout = &onenand_oob_128; | ||
4055 | mtd->subpage_sft = 2; | ||
4056 | } | ||
4023 | break; | 4057 | break; |
4024 | case 64: | 4058 | case 64: |
4025 | this->ecclayout = &onenand_oob_64; | 4059 | this->ecclayout = &onenand_oob_64; |
@@ -4108,12 +4142,8 @@ void onenand_release(struct mtd_info *mtd) | |||
4108 | { | 4142 | { |
4109 | struct onenand_chip *this = mtd->priv; | 4143 | struct onenand_chip *this = mtd->priv; |
4110 | 4144 | ||
4111 | #ifdef CONFIG_MTD_PARTITIONS | ||
4112 | /* Deregister partitions */ | 4145 | /* Deregister partitions */ |
4113 | del_mtd_partitions (mtd); | 4146 | mtd_device_unregister(mtd); |
4114 | #endif | ||
4115 | /* Deregister the device */ | ||
4116 | del_mtd_device (mtd); | ||
4117 | 4147 | ||
4118 | /* Free bad block table memory, if allocated */ | 4148 | /* Free bad block table memory, if allocated */ |
4119 | if (this->bbm) { | 4149 | if (this->bbm) { |
diff --git a/drivers/mtd/onenand/onenand_sim.c b/drivers/mtd/onenand/onenand_sim.c index 5ef3bd547772..85399e3accda 100644 --- a/drivers/mtd/onenand/onenand_sim.c +++ b/drivers/mtd/onenand/onenand_sim.c | |||
@@ -539,7 +539,8 @@ static int __init onenand_sim_init(void) | |||
539 | return -ENXIO; | 539 | return -ENXIO; |
540 | } | 540 | } |
541 | 541 | ||
542 | add_mtd_partitions(&info->mtd, info->parts, ARRAY_SIZE(os_partitions)); | 542 | mtd_device_register(&info->mtd, info->parts, |
543 | ARRAY_SIZE(os_partitions)); | ||
543 | 544 | ||
544 | return 0; | 545 | return 0; |
545 | } | 546 | } |
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index a4c74a9ba430..3306b5b3c736 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
@@ -147,9 +147,7 @@ struct s3c_onenand { | |||
147 | struct resource *dma_res; | 147 | struct resource *dma_res; |
148 | unsigned long phys_base; | 148 | unsigned long phys_base; |
149 | struct completion complete; | 149 | struct completion complete; |
150 | #ifdef CONFIG_MTD_PARTITIONS | ||
151 | struct mtd_partition *parts; | 150 | struct mtd_partition *parts; |
152 | #endif | ||
153 | }; | 151 | }; |
154 | 152 | ||
155 | #define CMD_MAP_00(dev, addr) (dev->cmd_map(MAP_00, ((addr) << 1))) | 153 | #define CMD_MAP_00(dev, addr) (dev->cmd_map(MAP_00, ((addr) << 1))) |
@@ -159,9 +157,7 @@ struct s3c_onenand { | |||
159 | 157 | ||
160 | static struct s3c_onenand *onenand; | 158 | static struct s3c_onenand *onenand; |
161 | 159 | ||
162 | #ifdef CONFIG_MTD_PARTITIONS | ||
163 | static const char *part_probes[] = { "cmdlinepart", NULL, }; | 160 | static const char *part_probes[] = { "cmdlinepart", NULL, }; |
164 | #endif | ||
165 | 161 | ||
166 | static inline int s3c_read_reg(int offset) | 162 | static inline int s3c_read_reg(int offset) |
167 | { | 163 | { |
@@ -1021,15 +1017,13 @@ static int s3c_onenand_probe(struct platform_device *pdev) | |||
1021 | if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ) | 1017 | if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ) |
1022 | dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n"); | 1018 | dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n"); |
1023 | 1019 | ||
1024 | #ifdef CONFIG_MTD_PARTITIONS | ||
1025 | err = parse_mtd_partitions(mtd, part_probes, &onenand->parts, 0); | 1020 | err = parse_mtd_partitions(mtd, part_probes, &onenand->parts, 0); |
1026 | if (err > 0) | 1021 | if (err > 0) |
1027 | add_mtd_partitions(mtd, onenand->parts, err); | 1022 | mtd_device_register(mtd, onenand->parts, err); |
1028 | else if (err <= 0 && pdata && pdata->parts) | 1023 | else if (err <= 0 && pdata && pdata->parts) |
1029 | add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); | 1024 | mtd_device_register(mtd, pdata->parts, pdata->nr_parts); |
1030 | else | 1025 | else |
1031 | #endif | 1026 | err = mtd_device_register(mtd, NULL, 0); |
1032 | err = add_mtd_device(mtd); | ||
1033 | 1027 | ||
1034 | platform_set_drvdata(pdev, mtd); | 1028 | platform_set_drvdata(pdev, mtd); |
1035 | 1029 | ||
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index 9aa81584c8a2..941bc3c05d6e 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c | |||
@@ -365,7 +365,7 @@ static int gluebi_create(struct ubi_device_info *di, | |||
365 | vi->vol_id); | 365 | vi->vol_id); |
366 | mutex_unlock(&devices_mutex); | 366 | mutex_unlock(&devices_mutex); |
367 | 367 | ||
368 | if (add_mtd_device(mtd)) { | 368 | if (mtd_device_register(mtd, NULL, 0)) { |
369 | err_msg("cannot add MTD device"); | 369 | err_msg("cannot add MTD device"); |
370 | kfree(mtd->name); | 370 | kfree(mtd->name); |
371 | kfree(gluebi); | 371 | kfree(gluebi); |
@@ -407,7 +407,7 @@ static int gluebi_remove(struct ubi_volume_info *vi) | |||
407 | return err; | 407 | return err; |
408 | 408 | ||
409 | mtd = &gluebi->mtd; | 409 | mtd = &gluebi->mtd; |
410 | err = del_mtd_device(mtd); | 410 | err = mtd_device_unregister(mtd); |
411 | if (err) { | 411 | if (err) { |
412 | err_msg("cannot remove fake MTD device %d, UBI device %d, " | 412 | err_msg("cannot remove fake MTD device %d, UBI device %d, " |
413 | "volume %d, error %d", mtd->index, gluebi->ubi_num, | 413 | "volume %d, error %d", mtd->index, gluebi->ubi_num, |
@@ -524,7 +524,7 @@ static void __exit ubi_gluebi_exit(void) | |||
524 | int err; | 524 | int err; |
525 | struct mtd_info *mtd = &gluebi->mtd; | 525 | struct mtd_info *mtd = &gluebi->mtd; |
526 | 526 | ||
527 | err = del_mtd_device(mtd); | 527 | err = mtd_device_unregister(mtd); |
528 | if (err) | 528 | if (err) |
529 | err_msg("error %d while removing gluebi MTD device %d, " | 529 | err_msg("error %d while removing gluebi MTD device %d, " |
530 | "UBI device %d, volume %d - ignoring", err, | 530 | "UBI device %d, volume %d - ignoring", err, |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6141667c5fb7..17b4dd94da90 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -113,9 +113,11 @@ MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); | |||
113 | module_param(tx_queues, int, 0); | 113 | module_param(tx_queues, int, 0); |
114 | MODULE_PARM_DESC(tx_queues, "Max number of transmit queues (default = 16)"); | 114 | MODULE_PARM_DESC(tx_queues, "Max number of transmit queues (default = 16)"); |
115 | module_param_named(num_grat_arp, num_peer_notif, int, 0644); | 115 | module_param_named(num_grat_arp, num_peer_notif, int, 0644); |
116 | MODULE_PARM_DESC(num_grat_arp, "Number of peer notifications to send on failover event (alias of num_unsol_na)"); | 116 | MODULE_PARM_DESC(num_grat_arp, "Number of peer notifications to send on " |
117 | "failover event (alias of num_unsol_na)"); | ||
117 | module_param_named(num_unsol_na, num_peer_notif, int, 0644); | 118 | module_param_named(num_unsol_na, num_peer_notif, int, 0644); |
118 | MODULE_PARM_DESC(num_unsol_na, "Number of peer notifications to send on failover event (alias of num_grat_arp)"); | 119 | MODULE_PARM_DESC(num_unsol_na, "Number of peer notifications to send on " |
120 | "failover event (alias of num_grat_arp)"); | ||
119 | module_param(miimon, int, 0); | 121 | module_param(miimon, int, 0); |
120 | MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); | 122 | MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); |
121 | module_param(updelay, int, 0); | 123 | module_param(updelay, int, 0); |
@@ -127,7 +129,7 @@ module_param(use_carrier, int, 0); | |||
127 | MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; " | 129 | MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; " |
128 | "0 for off, 1 for on (default)"); | 130 | "0 for off, 1 for on (default)"); |
129 | module_param(mode, charp, 0); | 131 | module_param(mode, charp, 0); |
130 | MODULE_PARM_DESC(mode, "Mode of operation : 0 for balance-rr, " | 132 | MODULE_PARM_DESC(mode, "Mode of operation; 0 for balance-rr, " |
131 | "1 for active-backup, 2 for balance-xor, " | 133 | "1 for active-backup, 2 for balance-xor, " |
132 | "3 for broadcast, 4 for 802.3ad, 5 for balance-tlb, " | 134 | "3 for broadcast, 4 for 802.3ad, 5 for balance-tlb, " |
133 | "6 for balance-alb"); | 135 | "6 for balance-alb"); |
@@ -142,27 +144,35 @@ MODULE_PARM_DESC(primary_reselect, "Reselect primary slave " | |||
142 | "2 for only on active slave " | 144 | "2 for only on active slave " |
143 | "failure"); | 145 | "failure"); |
144 | module_param(lacp_rate, charp, 0); | 146 | module_param(lacp_rate, charp, 0); |
145 | MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner " | 147 | MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner; " |
146 | "(slow/fast)"); | 148 | "0 for slow, 1 for fast"); |
147 | module_param(ad_select, charp, 0); | 149 | module_param(ad_select, charp, 0); |
148 | MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic: stable (0, default), bandwidth (1), count (2)"); | 150 | MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic; " |
151 | "0 for stable (default), 1 for bandwidth, " | ||
152 | "2 for count"); | ||
149 | module_param(xmit_hash_policy, charp, 0); | 153 | module_param(xmit_hash_policy, charp, 0); |
150 | MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method: 0 for layer 2 (default)" | 154 | MODULE_PARM_DESC(xmit_hash_policy, "balance-xor and 802.3ad hashing method; " |
151 | ", 1 for layer 3+4"); | 155 | "0 for layer 2 (default), 1 for layer 3+4, " |
156 | "2 for layer 2+3"); | ||
152 | module_param(arp_interval, int, 0); | 157 | module_param(arp_interval, int, 0); |
153 | MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); | 158 | MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); |
154 | module_param_array(arp_ip_target, charp, NULL, 0); | 159 | module_param_array(arp_ip_target, charp, NULL, 0); |
155 | MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); | 160 | MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); |
156 | module_param(arp_validate, charp, 0); | 161 | module_param(arp_validate, charp, 0); |
157 | MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all"); | 162 | MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes; " |
163 | "0 for none (default), 1 for active, " | ||
164 | "2 for backup, 3 for all"); | ||
158 | module_param(fail_over_mac, charp, 0); | 165 | module_param(fail_over_mac, charp, 0); |
159 | MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to the same MAC. none (default), active or follow"); | 166 | MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to " |
167 | "the same MAC; 0 for none (default), " | ||
168 | "1 for active, 2 for follow"); | ||
160 | module_param(all_slaves_active, int, 0); | 169 | module_param(all_slaves_active, int, 0); |
161 | MODULE_PARM_DESC(all_slaves_active, "Keep all frames received on an interface" | 170 | MODULE_PARM_DESC(all_slaves_active, "Keep all frames received on an interface" |
162 | "by setting active flag for all slaves. " | 171 | "by setting active flag for all slaves; " |
163 | "0 for never (default), 1 for always."); | 172 | "0 for never (default), 1 for always."); |
164 | module_param(resend_igmp, int, 0); | 173 | module_param(resend_igmp, int, 0); |
165 | MODULE_PARM_DESC(resend_igmp, "Number of IGMP membership reports to send on link failure"); | 174 | MODULE_PARM_DESC(resend_igmp, "Number of IGMP membership reports to send on " |
175 | "link failure"); | ||
166 | 176 | ||
167 | /*----------------------------- Global variables ----------------------------*/ | 177 | /*----------------------------- Global variables ----------------------------*/ |
168 | 178 | ||
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 807b6bb200eb..29a4f06fbfcf 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c | |||
@@ -1772,7 +1772,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
1772 | /* obtain emac clock from kernel */ | 1772 | /* obtain emac clock from kernel */ |
1773 | emac_clk = clk_get(&pdev->dev, NULL); | 1773 | emac_clk = clk_get(&pdev->dev, NULL); |
1774 | if (IS_ERR(emac_clk)) { | 1774 | if (IS_ERR(emac_clk)) { |
1775 | printk(KERN_ERR "DaVinci EMAC: Failed to get EMAC clock\n"); | 1775 | dev_err(&pdev->dev, "failed to get EMAC clock\n"); |
1776 | return -EBUSY; | 1776 | return -EBUSY; |
1777 | } | 1777 | } |
1778 | emac_bus_frequency = clk_get_rate(emac_clk); | 1778 | emac_bus_frequency = clk_get_rate(emac_clk); |
@@ -1780,7 +1780,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
1780 | 1780 | ||
1781 | ndev = alloc_etherdev(sizeof(struct emac_priv)); | 1781 | ndev = alloc_etherdev(sizeof(struct emac_priv)); |
1782 | if (!ndev) { | 1782 | if (!ndev) { |
1783 | printk(KERN_ERR "DaVinci EMAC: Error allocating net_device\n"); | 1783 | dev_err(&pdev->dev, "error allocating net_device\n"); |
1784 | clk_put(emac_clk); | 1784 | clk_put(emac_clk); |
1785 | return -ENOMEM; | 1785 | return -ENOMEM; |
1786 | } | 1786 | } |
@@ -1795,7 +1795,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
1795 | 1795 | ||
1796 | pdata = pdev->dev.platform_data; | 1796 | pdata = pdev->dev.platform_data; |
1797 | if (!pdata) { | 1797 | if (!pdata) { |
1798 | printk(KERN_ERR "DaVinci EMAC: No platform data\n"); | 1798 | dev_err(&pdev->dev, "no platform data\n"); |
1799 | return -ENODEV; | 1799 | return -ENODEV; |
1800 | } | 1800 | } |
1801 | 1801 | ||
@@ -1814,7 +1814,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
1814 | /* Get EMAC platform data */ | 1814 | /* Get EMAC platform data */ |
1815 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1815 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1816 | if (!res) { | 1816 | if (!res) { |
1817 | dev_err(emac_dev, "DaVinci EMAC: Error getting res\n"); | 1817 | dev_err(&pdev->dev,"error getting res\n"); |
1818 | rc = -ENOENT; | 1818 | rc = -ENOENT; |
1819 | goto probe_quit; | 1819 | goto probe_quit; |
1820 | } | 1820 | } |
@@ -1822,14 +1822,14 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
1822 | priv->emac_base_phys = res->start + pdata->ctrl_reg_offset; | 1822 | priv->emac_base_phys = res->start + pdata->ctrl_reg_offset; |
1823 | size = res->end - res->start + 1; | 1823 | size = res->end - res->start + 1; |
1824 | if (!request_mem_region(res->start, size, ndev->name)) { | 1824 | if (!request_mem_region(res->start, size, ndev->name)) { |
1825 | dev_err(emac_dev, "DaVinci EMAC: failed request_mem_region() for regs\n"); | 1825 | dev_err(&pdev->dev, "failed request_mem_region() for regs\n"); |
1826 | rc = -ENXIO; | 1826 | rc = -ENXIO; |
1827 | goto probe_quit; | 1827 | goto probe_quit; |
1828 | } | 1828 | } |
1829 | 1829 | ||
1830 | priv->remap_addr = ioremap(res->start, size); | 1830 | priv->remap_addr = ioremap(res->start, size); |
1831 | if (!priv->remap_addr) { | 1831 | if (!priv->remap_addr) { |
1832 | dev_err(emac_dev, "Unable to map IO\n"); | 1832 | dev_err(&pdev->dev, "unable to map IO\n"); |
1833 | rc = -ENOMEM; | 1833 | rc = -ENOMEM; |
1834 | release_mem_region(res->start, size); | 1834 | release_mem_region(res->start, size); |
1835 | goto probe_quit; | 1835 | goto probe_quit; |
@@ -1863,7 +1863,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
1863 | 1863 | ||
1864 | priv->dma = cpdma_ctlr_create(&dma_params); | 1864 | priv->dma = cpdma_ctlr_create(&dma_params); |
1865 | if (!priv->dma) { | 1865 | if (!priv->dma) { |
1866 | dev_err(emac_dev, "DaVinci EMAC: Error initializing DMA\n"); | 1866 | dev_err(&pdev->dev, "error initializing DMA\n"); |
1867 | rc = -ENOMEM; | 1867 | rc = -ENOMEM; |
1868 | goto no_dma; | 1868 | goto no_dma; |
1869 | } | 1869 | } |
@@ -1879,7 +1879,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
1879 | 1879 | ||
1880 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 1880 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
1881 | if (!res) { | 1881 | if (!res) { |
1882 | dev_err(emac_dev, "DaVinci EMAC: Error getting irq res\n"); | 1882 | dev_err(&pdev->dev, "error getting irq res\n"); |
1883 | rc = -ENOENT; | 1883 | rc = -ENOENT; |
1884 | goto no_irq_res; | 1884 | goto no_irq_res; |
1885 | } | 1885 | } |
@@ -1888,8 +1888,8 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
1888 | if (!is_valid_ether_addr(priv->mac_addr)) { | 1888 | if (!is_valid_ether_addr(priv->mac_addr)) { |
1889 | /* Use random MAC if none passed */ | 1889 | /* Use random MAC if none passed */ |
1890 | random_ether_addr(priv->mac_addr); | 1890 | random_ether_addr(priv->mac_addr); |
1891 | printk(KERN_WARNING "%s: using random MAC addr: %pM\n", | 1891 | dev_warn(&pdev->dev, "using random MAC addr: %pM\n", |
1892 | __func__, priv->mac_addr); | 1892 | priv->mac_addr); |
1893 | } | 1893 | } |
1894 | 1894 | ||
1895 | ndev->netdev_ops = &emac_netdev_ops; | 1895 | ndev->netdev_ops = &emac_netdev_ops; |
@@ -1902,7 +1902,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
1902 | SET_NETDEV_DEV(ndev, &pdev->dev); | 1902 | SET_NETDEV_DEV(ndev, &pdev->dev); |
1903 | rc = register_netdev(ndev); | 1903 | rc = register_netdev(ndev); |
1904 | if (rc) { | 1904 | if (rc) { |
1905 | dev_err(emac_dev, "DaVinci EMAC: Error in register_netdev\n"); | 1905 | dev_err(&pdev->dev, "error in register_netdev\n"); |
1906 | rc = -ENODEV; | 1906 | rc = -ENODEV; |
1907 | goto netdev_reg_err; | 1907 | goto netdev_reg_err; |
1908 | } | 1908 | } |
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index a3c0dc9d8b98..9537aaa50c2f 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c | |||
@@ -69,7 +69,7 @@ static const char paranoia_str[] = KERN_ERR | |||
69 | 69 | ||
70 | static const char bc_drvname[] = "baycom_epp"; | 70 | static const char bc_drvname[] = "baycom_epp"; |
71 | static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n" | 71 | static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n" |
72 | "baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n"; | 72 | "baycom_epp: version 0.7\n"; |
73 | 73 | ||
74 | /* --------------------------------------------------------------------- */ | 74 | /* --------------------------------------------------------------------- */ |
75 | 75 | ||
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c index 5f5af9a606f8..279d2296290a 100644 --- a/drivers/net/hamradio/baycom_par.c +++ b/drivers/net/hamradio/baycom_par.c | |||
@@ -102,7 +102,7 @@ | |||
102 | 102 | ||
103 | static const char bc_drvname[] = "baycom_par"; | 103 | static const char bc_drvname[] = "baycom_par"; |
104 | static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" | 104 | static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" |
105 | "baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n"; | 105 | "baycom_par: version 0.9\n"; |
106 | 106 | ||
107 | /* --------------------------------------------------------------------- */ | 107 | /* --------------------------------------------------------------------- */ |
108 | 108 | ||
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c index 3e25f10cabd6..99cdce33df8b 100644 --- a/drivers/net/hamradio/baycom_ser_fdx.c +++ b/drivers/net/hamradio/baycom_ser_fdx.c | |||
@@ -92,7 +92,7 @@ | |||
92 | 92 | ||
93 | static const char bc_drvname[] = "baycom_ser_fdx"; | 93 | static const char bc_drvname[] = "baycom_ser_fdx"; |
94 | static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" | 94 | static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" |
95 | "baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; | 95 | "baycom_ser_fdx: version 0.10\n"; |
96 | 96 | ||
97 | /* --------------------------------------------------------------------- */ | 97 | /* --------------------------------------------------------------------- */ |
98 | 98 | ||
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c index 1686f6dcbbce..d92fe6ca788f 100644 --- a/drivers/net/hamradio/baycom_ser_hdx.c +++ b/drivers/net/hamradio/baycom_ser_hdx.c | |||
@@ -80,7 +80,7 @@ | |||
80 | 80 | ||
81 | static const char bc_drvname[] = "baycom_ser_hdx"; | 81 | static const char bc_drvname[] = "baycom_ser_hdx"; |
82 | static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" | 82 | static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" |
83 | "baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; | 83 | "baycom_ser_hdx: version 0.10\n"; |
84 | 84 | ||
85 | /* --------------------------------------------------------------------- */ | 85 | /* --------------------------------------------------------------------- */ |
86 | 86 | ||
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index 5b37579e84b7..a4a3516b6bbf 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c | |||
@@ -749,7 +749,7 @@ EXPORT_SYMBOL(hdlcdrv_unregister); | |||
749 | static int __init hdlcdrv_init_driver(void) | 749 | static int __init hdlcdrv_init_driver(void) |
750 | { | 750 | { |
751 | printk(KERN_INFO "hdlcdrv: (C) 1996-2000 Thomas Sailer HB9JNX/AE4WA\n"); | 751 | printk(KERN_INFO "hdlcdrv: (C) 1996-2000 Thomas Sailer HB9JNX/AE4WA\n"); |
752 | printk(KERN_INFO "hdlcdrv: version 0.8 compiled " __TIME__ " " __DATE__ "\n"); | 752 | printk(KERN_INFO "hdlcdrv: version 0.8\n"); |
753 | return 0; | 753 | return 0; |
754 | } | 754 | } |
755 | 755 | ||
diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c index e646bfce2d84..b6304486f244 100644 --- a/drivers/net/sfc/mtd.c +++ b/drivers/net/sfc/mtd.c | |||
@@ -216,7 +216,7 @@ static void efx_mtd_remove_partition(struct efx_mtd_partition *part) | |||
216 | int rc; | 216 | int rc; |
217 | 217 | ||
218 | for (;;) { | 218 | for (;;) { |
219 | rc = del_mtd_device(&part->mtd); | 219 | rc = mtd_device_unregister(&part->mtd); |
220 | if (rc != -EBUSY) | 220 | if (rc != -EBUSY) |
221 | break; | 221 | break; |
222 | ssleep(1); | 222 | ssleep(1); |
@@ -268,7 +268,7 @@ static int efx_mtd_probe_device(struct efx_nic *efx, struct efx_mtd *efx_mtd) | |||
268 | part->mtd.write = efx_mtd->ops->write; | 268 | part->mtd.write = efx_mtd->ops->write; |
269 | part->mtd.sync = efx_mtd_sync; | 269 | part->mtd.sync = efx_mtd_sync; |
270 | 270 | ||
271 | if (add_mtd_device(&part->mtd)) | 271 | if (mtd_device_register(&part->mtd, NULL, 0)) |
272 | goto fail; | 272 | goto fail; |
273 | } | 273 | } |
274 | 274 | ||
@@ -280,7 +280,7 @@ fail: | |||
280 | --part; | 280 | --part; |
281 | efx_mtd_remove_partition(part); | 281 | efx_mtd_remove_partition(part); |
282 | } | 282 | } |
283 | /* add_mtd_device() returns 1 if the MTD table is full */ | 283 | /* mtd_device_register() returns 1 if the MTD table is full */ |
284 | return -ENOMEM; | 284 | return -ENOMEM; |
285 | } | 285 | } |
286 | 286 | ||
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index 737b59f1a8dc..9617d3d0ee39 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c | |||
@@ -3242,8 +3242,7 @@ static inline void show_version(void) | |||
3242 | rcsdate++; | 3242 | rcsdate++; |
3243 | tmp = strrchr(rcsdate, ' '); | 3243 | tmp = strrchr(rcsdate, ' '); |
3244 | *tmp = '\0'; | 3244 | *tmp = '\0'; |
3245 | printk(KERN_INFO "Cyclades-PC300 driver %s %s (built %s %s)\n", | 3245 | printk(KERN_INFO "Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate); |
3246 | rcsvers, rcsdate, __DATE__, __TIME__); | ||
3247 | } /* show_version */ | 3246 | } /* show_version */ |
3248 | 3247 | ||
3249 | static const struct net_device_ops cpc_netdev_ops = { | 3248 | static const struct net_device_ops cpc_netdev_ops = { |
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 8b63a691a9ed..65200af29c52 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -670,7 +670,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | |||
670 | 670 | ||
671 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); | 671 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); |
672 | 672 | ||
673 | if (depth != 1 || | 673 | if (depth != 1 || !data || |
674 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) | 674 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) |
675 | return 0; | 675 | return 0; |
676 | 676 | ||
@@ -679,16 +679,16 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | |||
679 | /* Retrieve command line */ | 679 | /* Retrieve command line */ |
680 | p = of_get_flat_dt_prop(node, "bootargs", &l); | 680 | p = of_get_flat_dt_prop(node, "bootargs", &l); |
681 | if (p != NULL && l > 0) | 681 | if (p != NULL && l > 0) |
682 | strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); | 682 | strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); |
683 | 683 | ||
684 | #ifdef CONFIG_CMDLINE | 684 | #ifdef CONFIG_CMDLINE |
685 | #ifndef CONFIG_CMDLINE_FORCE | 685 | #ifndef CONFIG_CMDLINE_FORCE |
686 | if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) | 686 | if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) |
687 | #endif | 687 | #endif |
688 | strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); | 688 | strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); |
689 | #endif /* CONFIG_CMDLINE */ | 689 | #endif /* CONFIG_CMDLINE */ |
690 | 690 | ||
691 | pr_debug("Command line is: %s\n", cmd_line); | 691 | pr_debug("Command line is: %s\n", (char*)data); |
692 | 692 | ||
693 | /* break now */ | 693 | /* break now */ |
694 | return 1; | 694 | return 1; |
diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c index d3d7809af8bf..0dc34f12f92e 100644 --- a/drivers/parport/parport_ip32.c +++ b/drivers/parport/parport_ip32.c | |||
@@ -2203,7 +2203,6 @@ static __exit void parport_ip32_unregister_port(struct parport *p) | |||
2203 | static int __init parport_ip32_init(void) | 2203 | static int __init parport_ip32_init(void) |
2204 | { | 2204 | { |
2205 | pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n"); | 2205 | pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n"); |
2206 | pr_debug1(PPIP32 "Compiled on %s, %s\n", __DATE__, __TIME__); | ||
2207 | this_port = parport_ip32_probe_port(); | 2206 | this_port = parport_ip32_probe_port(); |
2208 | return IS_ERR(this_port) ? PTR_ERR(this_port) : 0; | 2207 | return IS_ERR(this_port) ? PTR_ERR(this_port) : 0; |
2209 | } | 2208 | } |
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 52a462fc6b84..e57b50b38565 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -68,6 +68,13 @@ config BATTERY_DS2760 | |||
68 | help | 68 | help |
69 | Say Y here to enable support for batteries with ds2760 chip. | 69 | Say Y here to enable support for batteries with ds2760 chip. |
70 | 70 | ||
71 | config BATTERY_DS2780 | ||
72 | tristate "DS2780 battery driver" | ||
73 | select W1 | ||
74 | select W1_SLAVE_DS2780 | ||
75 | help | ||
76 | Say Y here to enable support for batteries with ds2780 chip. | ||
77 | |||
71 | config BATTERY_DS2782 | 78 | config BATTERY_DS2782 |
72 | tristate "DS2782/DS2786 standalone gas-gauge" | 79 | tristate "DS2782/DS2786 standalone gas-gauge" |
73 | depends on I2C | 80 | depends on I2C |
@@ -203,6 +210,15 @@ config CHARGER_ISP1704 | |||
203 | Say Y to enable support for USB Charger Detection with | 210 | Say Y to enable support for USB Charger Detection with |
204 | ISP1707/ISP1704 USB transceivers. | 211 | ISP1707/ISP1704 USB transceivers. |
205 | 212 | ||
213 | config CHARGER_MAX8903 | ||
214 | tristate "MAX8903 Battery DC-DC Charger for USB and Adapter Power" | ||
215 | depends on GENERIC_HARDIRQS | ||
216 | help | ||
217 | Say Y to enable support for the MAX8903 DC-DC charger and sysfs. | ||
218 | The driver supports controlling charger-enable and current-limit | ||
219 | pins based on the status of charger connections with interrupt | ||
220 | handlers. | ||
221 | |||
206 | config CHARGER_TWL4030 | 222 | config CHARGER_TWL4030 |
207 | tristate "OMAP TWL4030 BCI charger driver" | 223 | tristate "OMAP TWL4030 BCI charger driver" |
208 | depends on TWL4030_CORE | 224 | depends on TWL4030_CORE |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 8385bfae8728..009a90fa8ac9 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_WM8350_POWER) += wm8350_power.o | |||
15 | obj-$(CONFIG_TEST_POWER) += test_power.o | 15 | obj-$(CONFIG_TEST_POWER) += test_power.o |
16 | 16 | ||
17 | obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o | 17 | obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o |
18 | obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o | ||
18 | obj-$(CONFIG_BATTERY_DS2782) += ds2782_battery.o | 19 | obj-$(CONFIG_BATTERY_DS2782) += ds2782_battery.o |
19 | obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o | 20 | obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o |
20 | obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o | 21 | obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o |
@@ -32,5 +33,6 @@ obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o | |||
32 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o | 33 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o |
33 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o | 34 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o |
34 | obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o | 35 | obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o |
36 | obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o | ||
35 | obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o | 37 | obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o |
36 | obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o | 38 | obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o |
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 59e68dbd028b..bb16f5b7e167 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it> | 4 | * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it> |
5 | * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it> | 5 | * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it> |
6 | * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de> | 6 | * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de> |
7 | * Copyright (C) 2011 Pali Rohár <pali.rohar@gmail.com> | ||
7 | * | 8 | * |
8 | * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. | 9 | * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. |
9 | * | 10 | * |
@@ -76,7 +77,7 @@ struct bq27x00_reg_cache { | |||
76 | int time_to_empty_avg; | 77 | int time_to_empty_avg; |
77 | int time_to_full; | 78 | int time_to_full; |
78 | int charge_full; | 79 | int charge_full; |
79 | int charge_counter; | 80 | int cycle_count; |
80 | int capacity; | 81 | int capacity; |
81 | int flags; | 82 | int flags; |
82 | 83 | ||
@@ -115,7 +116,7 @@ static enum power_supply_property bq27x00_battery_props[] = { | |||
115 | POWER_SUPPLY_PROP_CHARGE_FULL, | 116 | POWER_SUPPLY_PROP_CHARGE_FULL, |
116 | POWER_SUPPLY_PROP_CHARGE_NOW, | 117 | POWER_SUPPLY_PROP_CHARGE_NOW, |
117 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | 118 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, |
118 | POWER_SUPPLY_PROP_CHARGE_COUNTER, | 119 | POWER_SUPPLY_PROP_CYCLE_COUNT, |
119 | POWER_SUPPLY_PROP_ENERGY_NOW, | 120 | POWER_SUPPLY_PROP_ENERGY_NOW, |
120 | }; | 121 | }; |
121 | 122 | ||
@@ -267,7 +268,7 @@ static void bq27x00_update(struct bq27x00_device_info *di) | |||
267 | cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); | 268 | cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); |
268 | cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); | 269 | cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); |
269 | cache.charge_full = bq27x00_battery_read_lmd(di); | 270 | cache.charge_full = bq27x00_battery_read_lmd(di); |
270 | cache.charge_counter = bq27x00_battery_read_cyct(di); | 271 | cache.cycle_count = bq27x00_battery_read_cyct(di); |
271 | 272 | ||
272 | if (!is_bq27500) | 273 | if (!is_bq27500) |
273 | cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false); | 274 | cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false); |
@@ -496,8 +497,8 @@ static int bq27x00_battery_get_property(struct power_supply *psy, | |||
496 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | 497 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: |
497 | ret = bq27x00_simple_value(di->charge_design_full, val); | 498 | ret = bq27x00_simple_value(di->charge_design_full, val); |
498 | break; | 499 | break; |
499 | case POWER_SUPPLY_PROP_CHARGE_COUNTER: | 500 | case POWER_SUPPLY_PROP_CYCLE_COUNT: |
500 | ret = bq27x00_simple_value(di->cache.charge_counter, val); | 501 | ret = bq27x00_simple_value(di->cache.cycle_count, val); |
501 | break; | 502 | break; |
502 | case POWER_SUPPLY_PROP_ENERGY_NOW: | 503 | case POWER_SUPPLY_PROP_ENERGY_NOW: |
503 | ret = bq27x00_battery_energy(di, val); | 504 | ret = bq27x00_battery_energy(di, val); |
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c index e534290f3256..f2c9cc33c0f9 100644 --- a/drivers/power/ds2760_battery.c +++ b/drivers/power/ds2760_battery.c | |||
@@ -86,7 +86,11 @@ static int rated_capacities[] = { | |||
86 | 920, /* NEC */ | 86 | 920, /* NEC */ |
87 | 1440, /* Samsung */ | 87 | 1440, /* Samsung */ |
88 | 1440, /* BYD */ | 88 | 1440, /* BYD */ |
89 | #ifdef CONFIG_MACH_H4700 | ||
90 | 1800, /* HP iPAQ hx4700 3.7V 1800mAh (359113-001) */ | ||
91 | #else | ||
89 | 1440, /* Lishen */ | 92 | 1440, /* Lishen */ |
93 | #endif | ||
90 | 1440, /* NEC */ | 94 | 1440, /* NEC */ |
91 | 2880, /* Samsung */ | 95 | 2880, /* Samsung */ |
92 | 2880, /* BYD */ | 96 | 2880, /* BYD */ |
@@ -186,7 +190,7 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di) | |||
186 | 190 | ||
187 | scale[0] = di->full_active_uAh; | 191 | scale[0] = di->full_active_uAh; |
188 | for (i = 1; i < 5; i++) | 192 | for (i = 1; i < 5; i++) |
189 | scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 2 + i]; | 193 | scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 1 + i]; |
190 | 194 | ||
191 | di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10); | 195 | di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10); |
192 | di->full_active_uAh *= 1000; /* convert to µAh */ | 196 | di->full_active_uAh *= 1000; /* convert to µAh */ |
diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c new file mode 100644 index 000000000000..1fefe82e12e3 --- /dev/null +++ b/drivers/power/ds2780_battery.c | |||
@@ -0,0 +1,853 @@ | |||
1 | /* | ||
2 | * 1-wire client/driver for the Maxim/Dallas DS2780 Stand-Alone Fuel Gauge IC | ||
3 | * | ||
4 | * Copyright (C) 2010 Indesign, LLC | ||
5 | * | ||
6 | * Author: Clifton Barnes <cabarnes@indesign-llc.com> | ||
7 | * | ||
8 | * Based on ds2760_battery and ds2782_battery drivers | ||
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 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/param.h> | ||
19 | #include <linux/pm.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/power_supply.h> | ||
22 | #include <linux/idr.h> | ||
23 | |||
24 | #include "../w1/w1.h" | ||
25 | #include "../w1/slaves/w1_ds2780.h" | ||
26 | |||
27 | /* Current unit measurement in uA for a 1 milli-ohm sense resistor */ | ||
28 | #define DS2780_CURRENT_UNITS 1563 | ||
29 | /* Charge unit measurement in uAh for a 1 milli-ohm sense resistor */ | ||
30 | #define DS2780_CHARGE_UNITS 6250 | ||
31 | /* Number of bytes in user EEPROM space */ | ||
32 | #define DS2780_USER_EEPROM_SIZE (DS2780_EEPROM_BLOCK0_END - \ | ||
33 | DS2780_EEPROM_BLOCK0_START + 1) | ||
34 | /* Number of bytes in parameter EEPROM space */ | ||
35 | #define DS2780_PARAM_EEPROM_SIZE (DS2780_EEPROM_BLOCK1_END - \ | ||
36 | DS2780_EEPROM_BLOCK1_START + 1) | ||
37 | |||
38 | struct ds2780_device_info { | ||
39 | struct device *dev; | ||
40 | struct power_supply bat; | ||
41 | struct device *w1_dev; | ||
42 | }; | ||
43 | |||
44 | enum current_types { | ||
45 | CURRENT_NOW, | ||
46 | CURRENT_AVG, | ||
47 | }; | ||
48 | |||
49 | static const char model[] = "DS2780"; | ||
50 | static const char manufacturer[] = "Maxim/Dallas"; | ||
51 | |||
52 | static inline struct ds2780_device_info *to_ds2780_device_info( | ||
53 | struct power_supply *psy) | ||
54 | { | ||
55 | return container_of(psy, struct ds2780_device_info, bat); | ||
56 | } | ||
57 | |||
58 | static inline struct power_supply *to_power_supply(struct device *dev) | ||
59 | { | ||
60 | return dev_get_drvdata(dev); | ||
61 | } | ||
62 | |||
63 | static inline int ds2780_read8(struct device *dev, u8 *val, int addr) | ||
64 | { | ||
65 | return w1_ds2780_io(dev, val, addr, sizeof(u8), 0); | ||
66 | } | ||
67 | |||
68 | static int ds2780_read16(struct device *dev, s16 *val, int addr) | ||
69 | { | ||
70 | int ret; | ||
71 | u8 raw[2]; | ||
72 | |||
73 | ret = w1_ds2780_io(dev, raw, addr, sizeof(u8) * 2, 0); | ||
74 | if (ret < 0) | ||
75 | return ret; | ||
76 | |||
77 | *val = (raw[0] << 8) | raw[1]; | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static inline int ds2780_read_block(struct device *dev, u8 *val, int addr, | ||
83 | size_t count) | ||
84 | { | ||
85 | return w1_ds2780_io(dev, val, addr, count, 0); | ||
86 | } | ||
87 | |||
88 | static inline int ds2780_write(struct device *dev, u8 *val, int addr, | ||
89 | size_t count) | ||
90 | { | ||
91 | return w1_ds2780_io(dev, val, addr, count, 1); | ||
92 | } | ||
93 | |||
94 | static inline int ds2780_store_eeprom(struct device *dev, int addr) | ||
95 | { | ||
96 | return w1_ds2780_eeprom_cmd(dev, addr, W1_DS2780_COPY_DATA); | ||
97 | } | ||
98 | |||
99 | static inline int ds2780_recall_eeprom(struct device *dev, int addr) | ||
100 | { | ||
101 | return w1_ds2780_eeprom_cmd(dev, addr, W1_DS2780_RECALL_DATA); | ||
102 | } | ||
103 | |||
104 | static int ds2780_save_eeprom(struct ds2780_device_info *dev_info, int reg) | ||
105 | { | ||
106 | int ret; | ||
107 | |||
108 | ret = ds2780_store_eeprom(dev_info->w1_dev, reg); | ||
109 | if (ret < 0) | ||
110 | return ret; | ||
111 | |||
112 | ret = ds2780_recall_eeprom(dev_info->w1_dev, reg); | ||
113 | if (ret < 0) | ||
114 | return ret; | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | /* Set sense resistor value in mhos */ | ||
120 | static int ds2780_set_sense_register(struct ds2780_device_info *dev_info, | ||
121 | u8 conductance) | ||
122 | { | ||
123 | int ret; | ||
124 | |||
125 | ret = ds2780_write(dev_info->w1_dev, &conductance, | ||
126 | DS2780_RSNSP_REG, sizeof(u8)); | ||
127 | if (ret < 0) | ||
128 | return ret; | ||
129 | |||
130 | return ds2780_save_eeprom(dev_info, DS2780_RSNSP_REG); | ||
131 | } | ||
132 | |||
133 | /* Get RSGAIN value from 0 to 1.999 in steps of 0.001 */ | ||
134 | static int ds2780_get_rsgain_register(struct ds2780_device_info *dev_info, | ||
135 | u16 *rsgain) | ||
136 | { | ||
137 | return ds2780_read16(dev_info->w1_dev, rsgain, DS2780_RSGAIN_MSB_REG); | ||
138 | } | ||
139 | |||
140 | /* Set RSGAIN value from 0 to 1.999 in steps of 0.001 */ | ||
141 | static int ds2780_set_rsgain_register(struct ds2780_device_info *dev_info, | ||
142 | u16 rsgain) | ||
143 | { | ||
144 | int ret; | ||
145 | u8 raw[] = {rsgain >> 8, rsgain & 0xFF}; | ||
146 | |||
147 | ret = ds2780_write(dev_info->w1_dev, raw, | ||
148 | DS2780_RSGAIN_MSB_REG, sizeof(u8) * 2); | ||
149 | if (ret < 0) | ||
150 | return ret; | ||
151 | |||
152 | return ds2780_save_eeprom(dev_info, DS2780_RSGAIN_MSB_REG); | ||
153 | } | ||
154 | |||
155 | static int ds2780_get_voltage(struct ds2780_device_info *dev_info, | ||
156 | int *voltage_uV) | ||
157 | { | ||
158 | int ret; | ||
159 | s16 voltage_raw; | ||
160 | |||
161 | /* | ||
162 | * The voltage value is located in 10 bits across the voltage MSB | ||
163 | * and LSB registers in two's compliment form | ||
164 | * Sign bit of the voltage value is in bit 7 of the voltage MSB register | ||
165 | * Bits 9 - 3 of the voltage value are in bits 6 - 0 of the | ||
166 | * voltage MSB register | ||
167 | * Bits 2 - 0 of the voltage value are in bits 7 - 5 of the | ||
168 | * voltage LSB register | ||
169 | */ | ||
170 | ret = ds2780_read16(dev_info->w1_dev, &voltage_raw, | ||
171 | DS2780_VOLT_MSB_REG); | ||
172 | if (ret < 0) | ||
173 | return ret; | ||
174 | |||
175 | /* | ||
176 | * DS2780 reports voltage in units of 4.88mV, but the battery class | ||
177 | * reports in units of uV, so convert by multiplying by 4880. | ||
178 | */ | ||
179 | *voltage_uV = (voltage_raw / 32) * 4880; | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static int ds2780_get_temperature(struct ds2780_device_info *dev_info, | ||
184 | int *temperature) | ||
185 | { | ||
186 | int ret; | ||
187 | s16 temperature_raw; | ||
188 | |||
189 | /* | ||
190 | * The temperature value is located in 10 bits across the temperature | ||
191 | * MSB and LSB registers in two's compliment form | ||
192 | * Sign bit of the temperature value is in bit 7 of the temperature | ||
193 | * MSB register | ||
194 | * Bits 9 - 3 of the temperature value are in bits 6 - 0 of the | ||
195 | * temperature MSB register | ||
196 | * Bits 2 - 0 of the temperature value are in bits 7 - 5 of the | ||
197 | * temperature LSB register | ||
198 | */ | ||
199 | ret = ds2780_read16(dev_info->w1_dev, &temperature_raw, | ||
200 | DS2780_TEMP_MSB_REG); | ||
201 | if (ret < 0) | ||
202 | return ret; | ||
203 | |||
204 | /* | ||
205 | * Temperature is measured in units of 0.125 degrees celcius, the | ||
206 | * power_supply class measures temperature in tenths of degrees | ||
207 | * celsius. The temperature value is stored as a 10 bit number, plus | ||
208 | * sign in the upper bits of a 16 bit register. | ||
209 | */ | ||
210 | *temperature = ((temperature_raw / 32) * 125) / 100; | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int ds2780_get_current(struct ds2780_device_info *dev_info, | ||
215 | enum current_types type, int *current_uA) | ||
216 | { | ||
217 | int ret, sense_res; | ||
218 | s16 current_raw; | ||
219 | u8 sense_res_raw, reg_msb; | ||
220 | |||
221 | /* | ||
222 | * The units of measurement for current are dependent on the value of | ||
223 | * the sense resistor. | ||
224 | */ | ||
225 | ret = ds2780_read8(dev_info->w1_dev, &sense_res_raw, DS2780_RSNSP_REG); | ||
226 | if (ret < 0) | ||
227 | return ret; | ||
228 | |||
229 | if (sense_res_raw == 0) { | ||
230 | dev_err(dev_info->dev, "sense resistor value is 0\n"); | ||
231 | return -ENXIO; | ||
232 | } | ||
233 | sense_res = 1000 / sense_res_raw; | ||
234 | |||
235 | if (type == CURRENT_NOW) | ||
236 | reg_msb = DS2780_CURRENT_MSB_REG; | ||
237 | else if (type == CURRENT_AVG) | ||
238 | reg_msb = DS2780_IAVG_MSB_REG; | ||
239 | else | ||
240 | return -EINVAL; | ||
241 | |||
242 | /* | ||
243 | * The current value is located in 16 bits across the current MSB | ||
244 | * and LSB registers in two's compliment form | ||
245 | * Sign bit of the current value is in bit 7 of the current MSB register | ||
246 | * Bits 14 - 8 of the current value are in bits 6 - 0 of the current | ||
247 | * MSB register | ||
248 | * Bits 7 - 0 of the current value are in bits 7 - 0 of the current | ||
249 | * LSB register | ||
250 | */ | ||
251 | ret = ds2780_read16(dev_info->w1_dev, ¤t_raw, reg_msb); | ||
252 | if (ret < 0) | ||
253 | return ret; | ||
254 | |||
255 | *current_uA = current_raw * (DS2780_CURRENT_UNITS / sense_res); | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int ds2780_get_accumulated_current(struct ds2780_device_info *dev_info, | ||
260 | int *accumulated_current) | ||
261 | { | ||
262 | int ret, sense_res; | ||
263 | s16 current_raw; | ||
264 | u8 sense_res_raw; | ||
265 | |||
266 | /* | ||
267 | * The units of measurement for accumulated current are dependent on | ||
268 | * the value of the sense resistor. | ||
269 | */ | ||
270 | ret = ds2780_read8(dev_info->w1_dev, &sense_res_raw, DS2780_RSNSP_REG); | ||
271 | if (ret < 0) | ||
272 | return ret; | ||
273 | |||
274 | if (sense_res_raw == 0) { | ||
275 | dev_err(dev_info->dev, "sense resistor value is 0\n"); | ||
276 | return -ENXIO; | ||
277 | } | ||
278 | sense_res = 1000 / sense_res_raw; | ||
279 | |||
280 | /* | ||
281 | * The ACR value is located in 16 bits across the ACR MSB and | ||
282 | * LSB registers | ||
283 | * Bits 15 - 8 of the ACR value are in bits 7 - 0 of the ACR | ||
284 | * MSB register | ||
285 | * Bits 7 - 0 of the ACR value are in bits 7 - 0 of the ACR | ||
286 | * LSB register | ||
287 | */ | ||
288 | ret = ds2780_read16(dev_info->w1_dev, ¤t_raw, DS2780_ACR_MSB_REG); | ||
289 | if (ret < 0) | ||
290 | return ret; | ||
291 | |||
292 | *accumulated_current = current_raw * (DS2780_CHARGE_UNITS / sense_res); | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static int ds2780_get_capacity(struct ds2780_device_info *dev_info, | ||
297 | int *capacity) | ||
298 | { | ||
299 | int ret; | ||
300 | u8 raw; | ||
301 | |||
302 | ret = ds2780_read8(dev_info->w1_dev, &raw, DS2780_RARC_REG); | ||
303 | if (ret < 0) | ||
304 | return ret; | ||
305 | |||
306 | *capacity = raw; | ||
307 | return raw; | ||
308 | } | ||
309 | |||
310 | static int ds2780_get_status(struct ds2780_device_info *dev_info, int *status) | ||
311 | { | ||
312 | int ret, current_uA, capacity; | ||
313 | |||
314 | ret = ds2780_get_current(dev_info, CURRENT_NOW, ¤t_uA); | ||
315 | if (ret < 0) | ||
316 | return ret; | ||
317 | |||
318 | ret = ds2780_get_capacity(dev_info, &capacity); | ||
319 | if (ret < 0) | ||
320 | return ret; | ||
321 | |||
322 | if (capacity == 100) | ||
323 | *status = POWER_SUPPLY_STATUS_FULL; | ||
324 | else if (current_uA == 0) | ||
325 | *status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
326 | else if (current_uA < 0) | ||
327 | *status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
328 | else | ||
329 | *status = POWER_SUPPLY_STATUS_CHARGING; | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | static int ds2780_get_charge_now(struct ds2780_device_info *dev_info, | ||
335 | int *charge_now) | ||
336 | { | ||
337 | int ret; | ||
338 | u16 charge_raw; | ||
339 | |||
340 | /* | ||
341 | * The RAAC value is located in 16 bits across the RAAC MSB and | ||
342 | * LSB registers | ||
343 | * Bits 15 - 8 of the RAAC value are in bits 7 - 0 of the RAAC | ||
344 | * MSB register | ||
345 | * Bits 7 - 0 of the RAAC value are in bits 7 - 0 of the RAAC | ||
346 | * LSB register | ||
347 | */ | ||
348 | ret = ds2780_read16(dev_info->w1_dev, &charge_raw, DS2780_RAAC_MSB_REG); | ||
349 | if (ret < 0) | ||
350 | return ret; | ||
351 | |||
352 | *charge_now = charge_raw * 1600; | ||
353 | return 0; | ||
354 | } | ||
355 | |||
356 | static int ds2780_get_control_register(struct ds2780_device_info *dev_info, | ||
357 | u8 *control_reg) | ||
358 | { | ||
359 | return ds2780_read8(dev_info->w1_dev, control_reg, DS2780_CONTROL_REG); | ||
360 | } | ||
361 | |||
362 | static int ds2780_set_control_register(struct ds2780_device_info *dev_info, | ||
363 | u8 control_reg) | ||
364 | { | ||
365 | int ret; | ||
366 | |||
367 | ret = ds2780_write(dev_info->w1_dev, &control_reg, | ||
368 | DS2780_CONTROL_REG, sizeof(u8)); | ||
369 | if (ret < 0) | ||
370 | return ret; | ||
371 | |||
372 | return ds2780_save_eeprom(dev_info, DS2780_CONTROL_REG); | ||
373 | } | ||
374 | |||
375 | static int ds2780_battery_get_property(struct power_supply *psy, | ||
376 | enum power_supply_property psp, | ||
377 | union power_supply_propval *val) | ||
378 | { | ||
379 | int ret = 0; | ||
380 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
381 | |||
382 | switch (psp) { | ||
383 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
384 | ret = ds2780_get_voltage(dev_info, &val->intval); | ||
385 | break; | ||
386 | |||
387 | case POWER_SUPPLY_PROP_TEMP: | ||
388 | ret = ds2780_get_temperature(dev_info, &val->intval); | ||
389 | break; | ||
390 | |||
391 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
392 | val->strval = model; | ||
393 | break; | ||
394 | |||
395 | case POWER_SUPPLY_PROP_MANUFACTURER: | ||
396 | val->strval = manufacturer; | ||
397 | break; | ||
398 | |||
399 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
400 | ret = ds2780_get_current(dev_info, CURRENT_NOW, &val->intval); | ||
401 | break; | ||
402 | |||
403 | case POWER_SUPPLY_PROP_CURRENT_AVG: | ||
404 | ret = ds2780_get_current(dev_info, CURRENT_AVG, &val->intval); | ||
405 | break; | ||
406 | |||
407 | case POWER_SUPPLY_PROP_STATUS: | ||
408 | ret = ds2780_get_status(dev_info, &val->intval); | ||
409 | break; | ||
410 | |||
411 | case POWER_SUPPLY_PROP_CAPACITY: | ||
412 | ret = ds2780_get_capacity(dev_info, &val->intval); | ||
413 | break; | ||
414 | |||
415 | case POWER_SUPPLY_PROP_CHARGE_COUNTER: | ||
416 | ret = ds2780_get_accumulated_current(dev_info, &val->intval); | ||
417 | break; | ||
418 | |||
419 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
420 | ret = ds2780_get_charge_now(dev_info, &val->intval); | ||
421 | break; | ||
422 | |||
423 | default: | ||
424 | ret = -EINVAL; | ||
425 | } | ||
426 | |||
427 | return ret; | ||
428 | } | ||
429 | |||
430 | static enum power_supply_property ds2780_battery_props[] = { | ||
431 | POWER_SUPPLY_PROP_STATUS, | ||
432 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
433 | POWER_SUPPLY_PROP_TEMP, | ||
434 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
435 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
436 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
437 | POWER_SUPPLY_PROP_CURRENT_AVG, | ||
438 | POWER_SUPPLY_PROP_CAPACITY, | ||
439 | POWER_SUPPLY_PROP_CHARGE_COUNTER, | ||
440 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
441 | }; | ||
442 | |||
443 | static ssize_t ds2780_get_pmod_enabled(struct device *dev, | ||
444 | struct device_attribute *attr, | ||
445 | char *buf) | ||
446 | { | ||
447 | int ret; | ||
448 | u8 control_reg; | ||
449 | struct power_supply *psy = to_power_supply(dev); | ||
450 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
451 | |||
452 | /* Get power mode */ | ||
453 | ret = ds2780_get_control_register(dev_info, &control_reg); | ||
454 | if (ret < 0) | ||
455 | return ret; | ||
456 | |||
457 | return sprintf(buf, "%d\n", | ||
458 | !!(control_reg & DS2780_CONTROL_REG_PMOD)); | ||
459 | } | ||
460 | |||
461 | static ssize_t ds2780_set_pmod_enabled(struct device *dev, | ||
462 | struct device_attribute *attr, | ||
463 | const char *buf, | ||
464 | size_t count) | ||
465 | { | ||
466 | int ret; | ||
467 | u8 control_reg, new_setting; | ||
468 | struct power_supply *psy = to_power_supply(dev); | ||
469 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
470 | |||
471 | /* Set power mode */ | ||
472 | ret = ds2780_get_control_register(dev_info, &control_reg); | ||
473 | if (ret < 0) | ||
474 | return ret; | ||
475 | |||
476 | ret = kstrtou8(buf, 0, &new_setting); | ||
477 | if (ret < 0) | ||
478 | return ret; | ||
479 | |||
480 | if ((new_setting != 0) && (new_setting != 1)) { | ||
481 | dev_err(dev_info->dev, "Invalid pmod setting (0 or 1)\n"); | ||
482 | return -EINVAL; | ||
483 | } | ||
484 | |||
485 | if (new_setting) | ||
486 | control_reg |= DS2780_CONTROL_REG_PMOD; | ||
487 | else | ||
488 | control_reg &= ~DS2780_CONTROL_REG_PMOD; | ||
489 | |||
490 | ret = ds2780_set_control_register(dev_info, control_reg); | ||
491 | if (ret < 0) | ||
492 | return ret; | ||
493 | |||
494 | return count; | ||
495 | } | ||
496 | |||
497 | static ssize_t ds2780_get_sense_resistor_value(struct device *dev, | ||
498 | struct device_attribute *attr, | ||
499 | char *buf) | ||
500 | { | ||
501 | int ret; | ||
502 | u8 sense_resistor; | ||
503 | struct power_supply *psy = to_power_supply(dev); | ||
504 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
505 | |||
506 | ret = ds2780_read8(dev_info->w1_dev, &sense_resistor, DS2780_RSNSP_REG); | ||
507 | if (ret < 0) | ||
508 | return ret; | ||
509 | |||
510 | ret = sprintf(buf, "%d\n", sense_resistor); | ||
511 | return ret; | ||
512 | } | ||
513 | |||
514 | static ssize_t ds2780_set_sense_resistor_value(struct device *dev, | ||
515 | struct device_attribute *attr, | ||
516 | const char *buf, | ||
517 | size_t count) | ||
518 | { | ||
519 | int ret; | ||
520 | u8 new_setting; | ||
521 | struct power_supply *psy = to_power_supply(dev); | ||
522 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
523 | |||
524 | ret = kstrtou8(buf, 0, &new_setting); | ||
525 | if (ret < 0) | ||
526 | return ret; | ||
527 | |||
528 | ret = ds2780_set_sense_register(dev_info, new_setting); | ||
529 | if (ret < 0) | ||
530 | return ret; | ||
531 | |||
532 | return count; | ||
533 | } | ||
534 | |||
535 | static ssize_t ds2780_get_rsgain_setting(struct device *dev, | ||
536 | struct device_attribute *attr, | ||
537 | char *buf) | ||
538 | { | ||
539 | int ret; | ||
540 | u16 rsgain; | ||
541 | struct power_supply *psy = to_power_supply(dev); | ||
542 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
543 | |||
544 | ret = ds2780_get_rsgain_register(dev_info, &rsgain); | ||
545 | if (ret < 0) | ||
546 | return ret; | ||
547 | |||
548 | return sprintf(buf, "%d\n", rsgain); | ||
549 | } | ||
550 | |||
551 | static ssize_t ds2780_set_rsgain_setting(struct device *dev, | ||
552 | struct device_attribute *attr, | ||
553 | const char *buf, | ||
554 | size_t count) | ||
555 | { | ||
556 | int ret; | ||
557 | u16 new_setting; | ||
558 | struct power_supply *psy = to_power_supply(dev); | ||
559 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
560 | |||
561 | ret = kstrtou16(buf, 0, &new_setting); | ||
562 | if (ret < 0) | ||
563 | return ret; | ||
564 | |||
565 | /* Gain can only be from 0 to 1.999 in steps of .001 */ | ||
566 | if (new_setting > 1999) { | ||
567 | dev_err(dev_info->dev, "Invalid rsgain setting (0 - 1999)\n"); | ||
568 | return -EINVAL; | ||
569 | } | ||
570 | |||
571 | ret = ds2780_set_rsgain_register(dev_info, new_setting); | ||
572 | if (ret < 0) | ||
573 | return ret; | ||
574 | |||
575 | return count; | ||
576 | } | ||
577 | |||
578 | static ssize_t ds2780_get_pio_pin(struct device *dev, | ||
579 | struct device_attribute *attr, | ||
580 | char *buf) | ||
581 | { | ||
582 | int ret; | ||
583 | u8 sfr; | ||
584 | struct power_supply *psy = to_power_supply(dev); | ||
585 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
586 | |||
587 | ret = ds2780_read8(dev_info->w1_dev, &sfr, DS2780_SFR_REG); | ||
588 | if (ret < 0) | ||
589 | return ret; | ||
590 | |||
591 | ret = sprintf(buf, "%d\n", sfr & DS2780_SFR_REG_PIOSC); | ||
592 | return ret; | ||
593 | } | ||
594 | |||
595 | static ssize_t ds2780_set_pio_pin(struct device *dev, | ||
596 | struct device_attribute *attr, | ||
597 | const char *buf, | ||
598 | size_t count) | ||
599 | { | ||
600 | int ret; | ||
601 | u8 new_setting; | ||
602 | struct power_supply *psy = to_power_supply(dev); | ||
603 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
604 | |||
605 | ret = kstrtou8(buf, 0, &new_setting); | ||
606 | if (ret < 0) | ||
607 | return ret; | ||
608 | |||
609 | if ((new_setting != 0) && (new_setting != 1)) { | ||
610 | dev_err(dev_info->dev, "Invalid pio_pin setting (0 or 1)\n"); | ||
611 | return -EINVAL; | ||
612 | } | ||
613 | |||
614 | ret = ds2780_write(dev_info->w1_dev, &new_setting, | ||
615 | DS2780_SFR_REG, sizeof(u8)); | ||
616 | if (ret < 0) | ||
617 | return ret; | ||
618 | |||
619 | return count; | ||
620 | } | ||
621 | |||
622 | static ssize_t ds2780_read_param_eeprom_bin(struct file *filp, | ||
623 | struct kobject *kobj, | ||
624 | struct bin_attribute *bin_attr, | ||
625 | char *buf, loff_t off, size_t count) | ||
626 | { | ||
627 | struct device *dev = container_of(kobj, struct device, kobj); | ||
628 | struct power_supply *psy = to_power_supply(dev); | ||
629 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
630 | |||
631 | count = min_t(loff_t, count, | ||
632 | DS2780_EEPROM_BLOCK1_END - | ||
633 | DS2780_EEPROM_BLOCK1_START + 1 - off); | ||
634 | |||
635 | return ds2780_read_block(dev_info->w1_dev, buf, | ||
636 | DS2780_EEPROM_BLOCK1_START + off, count); | ||
637 | } | ||
638 | |||
639 | static ssize_t ds2780_write_param_eeprom_bin(struct file *filp, | ||
640 | struct kobject *kobj, | ||
641 | struct bin_attribute *bin_attr, | ||
642 | char *buf, loff_t off, size_t count) | ||
643 | { | ||
644 | struct device *dev = container_of(kobj, struct device, kobj); | ||
645 | struct power_supply *psy = to_power_supply(dev); | ||
646 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
647 | int ret; | ||
648 | |||
649 | count = min_t(loff_t, count, | ||
650 | DS2780_EEPROM_BLOCK1_END - | ||
651 | DS2780_EEPROM_BLOCK1_START + 1 - off); | ||
652 | |||
653 | ret = ds2780_write(dev_info->w1_dev, buf, | ||
654 | DS2780_EEPROM_BLOCK1_START + off, count); | ||
655 | if (ret < 0) | ||
656 | return ret; | ||
657 | |||
658 | ret = ds2780_save_eeprom(dev_info, DS2780_EEPROM_BLOCK1_START); | ||
659 | if (ret < 0) | ||
660 | return ret; | ||
661 | |||
662 | return count; | ||
663 | } | ||
664 | |||
665 | static struct bin_attribute ds2780_param_eeprom_bin_attr = { | ||
666 | .attr = { | ||
667 | .name = "param_eeprom", | ||
668 | .mode = S_IRUGO | S_IWUSR, | ||
669 | }, | ||
670 | .size = DS2780_EEPROM_BLOCK1_END - DS2780_EEPROM_BLOCK1_START + 1, | ||
671 | .read = ds2780_read_param_eeprom_bin, | ||
672 | .write = ds2780_write_param_eeprom_bin, | ||
673 | }; | ||
674 | |||
675 | static ssize_t ds2780_read_user_eeprom_bin(struct file *filp, | ||
676 | struct kobject *kobj, | ||
677 | struct bin_attribute *bin_attr, | ||
678 | char *buf, loff_t off, size_t count) | ||
679 | { | ||
680 | struct device *dev = container_of(kobj, struct device, kobj); | ||
681 | struct power_supply *psy = to_power_supply(dev); | ||
682 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
683 | |||
684 | count = min_t(loff_t, count, | ||
685 | DS2780_EEPROM_BLOCK0_END - | ||
686 | DS2780_EEPROM_BLOCK0_START + 1 - off); | ||
687 | |||
688 | return ds2780_read_block(dev_info->w1_dev, buf, | ||
689 | DS2780_EEPROM_BLOCK0_START + off, count); | ||
690 | |||
691 | } | ||
692 | |||
693 | static ssize_t ds2780_write_user_eeprom_bin(struct file *filp, | ||
694 | struct kobject *kobj, | ||
695 | struct bin_attribute *bin_attr, | ||
696 | char *buf, loff_t off, size_t count) | ||
697 | { | ||
698 | struct device *dev = container_of(kobj, struct device, kobj); | ||
699 | struct power_supply *psy = to_power_supply(dev); | ||
700 | struct ds2780_device_info *dev_info = to_ds2780_device_info(psy); | ||
701 | int ret; | ||
702 | |||
703 | count = min_t(loff_t, count, | ||
704 | DS2780_EEPROM_BLOCK0_END - | ||
705 | DS2780_EEPROM_BLOCK0_START + 1 - off); | ||
706 | |||
707 | ret = ds2780_write(dev_info->w1_dev, buf, | ||
708 | DS2780_EEPROM_BLOCK0_START + off, count); | ||
709 | if (ret < 0) | ||
710 | return ret; | ||
711 | |||
712 | ret = ds2780_save_eeprom(dev_info, DS2780_EEPROM_BLOCK0_START); | ||
713 | if (ret < 0) | ||
714 | return ret; | ||
715 | |||
716 | return count; | ||
717 | } | ||
718 | |||
719 | static struct bin_attribute ds2780_user_eeprom_bin_attr = { | ||
720 | .attr = { | ||
721 | .name = "user_eeprom", | ||
722 | .mode = S_IRUGO | S_IWUSR, | ||
723 | }, | ||
724 | .size = DS2780_EEPROM_BLOCK0_END - DS2780_EEPROM_BLOCK0_START + 1, | ||
725 | .read = ds2780_read_user_eeprom_bin, | ||
726 | .write = ds2780_write_user_eeprom_bin, | ||
727 | }; | ||
728 | |||
729 | static DEVICE_ATTR(pmod_enabled, S_IRUGO | S_IWUSR, ds2780_get_pmod_enabled, | ||
730 | ds2780_set_pmod_enabled); | ||
731 | static DEVICE_ATTR(sense_resistor_value, S_IRUGO | S_IWUSR, | ||
732 | ds2780_get_sense_resistor_value, ds2780_set_sense_resistor_value); | ||
733 | static DEVICE_ATTR(rsgain_setting, S_IRUGO | S_IWUSR, ds2780_get_rsgain_setting, | ||
734 | ds2780_set_rsgain_setting); | ||
735 | static DEVICE_ATTR(pio_pin, S_IRUGO | S_IWUSR, ds2780_get_pio_pin, | ||
736 | ds2780_set_pio_pin); | ||
737 | |||
738 | |||
739 | static struct attribute *ds2780_attributes[] = { | ||
740 | &dev_attr_pmod_enabled.attr, | ||
741 | &dev_attr_sense_resistor_value.attr, | ||
742 | &dev_attr_rsgain_setting.attr, | ||
743 | &dev_attr_pio_pin.attr, | ||
744 | NULL | ||
745 | }; | ||
746 | |||
747 | static const struct attribute_group ds2780_attr_group = { | ||
748 | .attrs = ds2780_attributes, | ||
749 | }; | ||
750 | |||
751 | static int __devinit ds2780_battery_probe(struct platform_device *pdev) | ||
752 | { | ||
753 | int ret = 0; | ||
754 | struct ds2780_device_info *dev_info; | ||
755 | |||
756 | dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL); | ||
757 | if (!dev_info) { | ||
758 | ret = -ENOMEM; | ||
759 | goto fail; | ||
760 | } | ||
761 | |||
762 | platform_set_drvdata(pdev, dev_info); | ||
763 | |||
764 | dev_info->dev = &pdev->dev; | ||
765 | dev_info->w1_dev = pdev->dev.parent; | ||
766 | dev_info->bat.name = dev_name(&pdev->dev); | ||
767 | dev_info->bat.type = POWER_SUPPLY_TYPE_BATTERY; | ||
768 | dev_info->bat.properties = ds2780_battery_props; | ||
769 | dev_info->bat.num_properties = ARRAY_SIZE(ds2780_battery_props); | ||
770 | dev_info->bat.get_property = ds2780_battery_get_property; | ||
771 | |||
772 | ret = power_supply_register(&pdev->dev, &dev_info->bat); | ||
773 | if (ret) { | ||
774 | dev_err(dev_info->dev, "failed to register battery\n"); | ||
775 | goto fail_free_info; | ||
776 | } | ||
777 | |||
778 | ret = sysfs_create_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); | ||
779 | if (ret) { | ||
780 | dev_err(dev_info->dev, "failed to create sysfs group\n"); | ||
781 | goto fail_unregister; | ||
782 | } | ||
783 | |||
784 | ret = sysfs_create_bin_file(&dev_info->bat.dev->kobj, | ||
785 | &ds2780_param_eeprom_bin_attr); | ||
786 | if (ret) { | ||
787 | dev_err(dev_info->dev, | ||
788 | "failed to create param eeprom bin file"); | ||
789 | goto fail_remove_group; | ||
790 | } | ||
791 | |||
792 | ret = sysfs_create_bin_file(&dev_info->bat.dev->kobj, | ||
793 | &ds2780_user_eeprom_bin_attr); | ||
794 | if (ret) { | ||
795 | dev_err(dev_info->dev, | ||
796 | "failed to create user eeprom bin file"); | ||
797 | goto fail_remove_bin_file; | ||
798 | } | ||
799 | |||
800 | return 0; | ||
801 | |||
802 | fail_remove_bin_file: | ||
803 | sysfs_remove_bin_file(&dev_info->bat.dev->kobj, | ||
804 | &ds2780_param_eeprom_bin_attr); | ||
805 | fail_remove_group: | ||
806 | sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); | ||
807 | fail_unregister: | ||
808 | power_supply_unregister(&dev_info->bat); | ||
809 | fail_free_info: | ||
810 | kfree(dev_info); | ||
811 | fail: | ||
812 | return ret; | ||
813 | } | ||
814 | |||
815 | static int __devexit ds2780_battery_remove(struct platform_device *pdev) | ||
816 | { | ||
817 | struct ds2780_device_info *dev_info = platform_get_drvdata(pdev); | ||
818 | |||
819 | /* remove attributes */ | ||
820 | sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); | ||
821 | |||
822 | power_supply_unregister(&dev_info->bat); | ||
823 | |||
824 | kfree(dev_info); | ||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | MODULE_ALIAS("platform:ds2780-battery"); | ||
829 | |||
830 | static struct platform_driver ds2780_battery_driver = { | ||
831 | .driver = { | ||
832 | .name = "ds2780-battery", | ||
833 | }, | ||
834 | .probe = ds2780_battery_probe, | ||
835 | .remove = ds2780_battery_remove, | ||
836 | }; | ||
837 | |||
838 | static int __init ds2780_battery_init(void) | ||
839 | { | ||
840 | return platform_driver_register(&ds2780_battery_driver); | ||
841 | } | ||
842 | |||
843 | static void __exit ds2780_battery_exit(void) | ||
844 | { | ||
845 | platform_driver_unregister(&ds2780_battery_driver); | ||
846 | } | ||
847 | |||
848 | module_init(ds2780_battery_init); | ||
849 | module_exit(ds2780_battery_exit); | ||
850 | |||
851 | MODULE_LICENSE("GPL"); | ||
852 | MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>"); | ||
853 | MODULE_DESCRIPTION("Maxim/Dallas DS2780 Stand-Alone Fuel Gauage IC driver"); | ||
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c index 25b88ac1d44c..718f2c537827 100644 --- a/drivers/power/gpio-charger.c +++ b/drivers/power/gpio-charger.c | |||
@@ -161,12 +161,27 @@ static int __devexit gpio_charger_remove(struct platform_device *pdev) | |||
161 | return 0; | 161 | return 0; |
162 | } | 162 | } |
163 | 163 | ||
164 | #ifdef CONFIG_PM_SLEEP | ||
165 | static int gpio_charger_resume(struct device *dev) | ||
166 | { | ||
167 | struct platform_device *pdev = to_platform_device(dev); | ||
168 | struct gpio_charger *gpio_charger = platform_get_drvdata(pdev); | ||
169 | |||
170 | power_supply_changed(&gpio_charger->charger); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | #endif | ||
175 | |||
176 | static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, NULL, gpio_charger_resume); | ||
177 | |||
164 | static struct platform_driver gpio_charger_driver = { | 178 | static struct platform_driver gpio_charger_driver = { |
165 | .probe = gpio_charger_probe, | 179 | .probe = gpio_charger_probe, |
166 | .remove = __devexit_p(gpio_charger_remove), | 180 | .remove = __devexit_p(gpio_charger_remove), |
167 | .driver = { | 181 | .driver = { |
168 | .name = "gpio-charger", | 182 | .name = "gpio-charger", |
169 | .owner = THIS_MODULE, | 183 | .owner = THIS_MODULE, |
184 | .pm = &gpio_charger_pm_ops, | ||
170 | }, | 185 | }, |
171 | }; | 186 | }; |
172 | 187 | ||
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c index 2ad9b14a5ce3..f6d72b402a8e 100644 --- a/drivers/power/isp1704_charger.c +++ b/drivers/power/isp1704_charger.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/usb/ulpi.h> | 33 | #include <linux/usb/ulpi.h> |
34 | #include <linux/usb/ch9.h> | 34 | #include <linux/usb/ch9.h> |
35 | #include <linux/usb/gadget.h> | 35 | #include <linux/usb/gadget.h> |
36 | #include <linux/power/isp1704_charger.h> | ||
36 | 37 | ||
37 | /* Vendor specific Power Control register */ | 38 | /* Vendor specific Power Control register */ |
38 | #define ISP1704_PWR_CTRL 0x3d | 39 | #define ISP1704_PWR_CTRL 0x3d |
@@ -71,6 +72,18 @@ struct isp1704_charger { | |||
71 | }; | 72 | }; |
72 | 73 | ||
73 | /* | 74 | /* |
75 | * Disable/enable the power from the isp1704 if a function for it | ||
76 | * has been provided with platform data. | ||
77 | */ | ||
78 | static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on) | ||
79 | { | ||
80 | struct isp1704_charger_data *board = isp->dev->platform_data; | ||
81 | |||
82 | if (board->set_power) | ||
83 | board->set_power(on); | ||
84 | } | ||
85 | |||
86 | /* | ||
74 | * Determine is the charging port DCP (dedicated charger) or CDP (Host/HUB | 87 | * Determine is the charging port DCP (dedicated charger) or CDP (Host/HUB |
75 | * chargers). | 88 | * chargers). |
76 | * | 89 | * |
@@ -222,6 +235,9 @@ static void isp1704_charger_work(struct work_struct *data) | |||
222 | 235 | ||
223 | mutex_lock(&lock); | 236 | mutex_lock(&lock); |
224 | 237 | ||
238 | if (event != USB_EVENT_NONE) | ||
239 | isp1704_charger_set_power(isp, 1); | ||
240 | |||
225 | switch (event) { | 241 | switch (event) { |
226 | case USB_EVENT_VBUS: | 242 | case USB_EVENT_VBUS: |
227 | isp->online = true; | 243 | isp->online = true; |
@@ -269,6 +285,8 @@ static void isp1704_charger_work(struct work_struct *data) | |||
269 | */ | 285 | */ |
270 | if (isp->otg->gadget) | 286 | if (isp->otg->gadget) |
271 | usb_gadget_disconnect(isp->otg->gadget); | 287 | usb_gadget_disconnect(isp->otg->gadget); |
288 | |||
289 | isp1704_charger_set_power(isp, 0); | ||
272 | break; | 290 | break; |
273 | case USB_EVENT_ENUMERATED: | 291 | case USB_EVENT_ENUMERATED: |
274 | if (isp->present) | 292 | if (isp->present) |
@@ -394,6 +412,8 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) | |||
394 | isp->dev = &pdev->dev; | 412 | isp->dev = &pdev->dev; |
395 | platform_set_drvdata(pdev, isp); | 413 | platform_set_drvdata(pdev, isp); |
396 | 414 | ||
415 | isp1704_charger_set_power(isp, 1); | ||
416 | |||
397 | ret = isp1704_test_ulpi(isp); | 417 | ret = isp1704_test_ulpi(isp); |
398 | if (ret < 0) | 418 | if (ret < 0) |
399 | goto fail1; | 419 | goto fail1; |
@@ -434,6 +454,7 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) | |||
434 | 454 | ||
435 | /* Detect charger if VBUS is valid (the cable was already plugged). */ | 455 | /* Detect charger if VBUS is valid (the cable was already plugged). */ |
436 | ret = otg_io_read(isp->otg, ULPI_USB_INT_STS); | 456 | ret = otg_io_read(isp->otg, ULPI_USB_INT_STS); |
457 | isp1704_charger_set_power(isp, 0); | ||
437 | if ((ret & ULPI_INT_VBUS_VALID) && !isp->otg->default_a) { | 458 | if ((ret & ULPI_INT_VBUS_VALID) && !isp->otg->default_a) { |
438 | isp->event = USB_EVENT_VBUS; | 459 | isp->event = USB_EVENT_VBUS; |
439 | schedule_work(&isp->work); | 460 | schedule_work(&isp->work); |
@@ -459,6 +480,7 @@ static int __devexit isp1704_charger_remove(struct platform_device *pdev) | |||
459 | otg_unregister_notifier(isp->otg, &isp->nb); | 480 | otg_unregister_notifier(isp->otg, &isp->nb); |
460 | power_supply_unregister(&isp->psy); | 481 | power_supply_unregister(&isp->psy); |
461 | otg_put_transceiver(isp->otg); | 482 | otg_put_transceiver(isp->otg); |
483 | isp1704_charger_set_power(isp, 0); | ||
462 | kfree(isp); | 484 | kfree(isp); |
463 | 485 | ||
464 | return 0; | 486 | return 0; |
diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c new file mode 100644 index 000000000000..33ff0e37809e --- /dev/null +++ b/drivers/power/max8903_charger.c | |||
@@ -0,0 +1,391 @@ | |||
1 | /* | ||
2 | * max8903_charger.c - Maxim 8903 USB/Adapter Charger Driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics | ||
5 | * MyungJoo Ham <myungjoo.ham@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/gpio.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/power_supply.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/power/max8903_charger.h> | ||
29 | |||
30 | struct max8903_data { | ||
31 | struct max8903_pdata *pdata; | ||
32 | struct device *dev; | ||
33 | struct power_supply psy; | ||
34 | bool fault; | ||
35 | bool usb_in; | ||
36 | bool ta_in; | ||
37 | }; | ||
38 | |||
39 | static enum power_supply_property max8903_charger_props[] = { | ||
40 | POWER_SUPPLY_PROP_STATUS, /* Charger status output */ | ||
41 | POWER_SUPPLY_PROP_ONLINE, /* External power source */ | ||
42 | POWER_SUPPLY_PROP_HEALTH, /* Fault or OK */ | ||
43 | }; | ||
44 | |||
45 | static int max8903_get_property(struct power_supply *psy, | ||
46 | enum power_supply_property psp, | ||
47 | union power_supply_propval *val) | ||
48 | { | ||
49 | struct max8903_data *data = container_of(psy, | ||
50 | struct max8903_data, psy); | ||
51 | |||
52 | switch (psp) { | ||
53 | case POWER_SUPPLY_PROP_STATUS: | ||
54 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; | ||
55 | if (data->pdata->chg) { | ||
56 | if (gpio_get_value(data->pdata->chg) == 0) | ||
57 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
58 | else if (data->usb_in || data->ta_in) | ||
59 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
60 | else | ||
61 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
62 | } | ||
63 | break; | ||
64 | case POWER_SUPPLY_PROP_ONLINE: | ||
65 | val->intval = 0; | ||
66 | if (data->usb_in || data->ta_in) | ||
67 | val->intval = 1; | ||
68 | break; | ||
69 | case POWER_SUPPLY_PROP_HEALTH: | ||
70 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
71 | if (data->fault) | ||
72 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
73 | break; | ||
74 | default: | ||
75 | return -EINVAL; | ||
76 | } | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static irqreturn_t max8903_dcin(int irq, void *_data) | ||
81 | { | ||
82 | struct max8903_data *data = _data; | ||
83 | struct max8903_pdata *pdata = data->pdata; | ||
84 | bool ta_in; | ||
85 | enum power_supply_type old_type; | ||
86 | |||
87 | ta_in = gpio_get_value(pdata->dok) ? false : true; | ||
88 | |||
89 | if (ta_in == data->ta_in) | ||
90 | return IRQ_HANDLED; | ||
91 | |||
92 | data->ta_in = ta_in; | ||
93 | |||
94 | /* Set Current-Limit-Mode 1:DC 0:USB */ | ||
95 | if (pdata->dcm) | ||
96 | gpio_set_value(pdata->dcm, ta_in ? 1 : 0); | ||
97 | |||
98 | /* Charger Enable / Disable (cen is negated) */ | ||
99 | if (pdata->cen) | ||
100 | gpio_set_value(pdata->cen, ta_in ? 0 : | ||
101 | (data->usb_in ? 0 : 1)); | ||
102 | |||
103 | dev_dbg(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ? | ||
104 | "Connected" : "Disconnected"); | ||
105 | |||
106 | old_type = data->psy.type; | ||
107 | |||
108 | if (data->ta_in) | ||
109 | data->psy.type = POWER_SUPPLY_TYPE_MAINS; | ||
110 | else if (data->usb_in) | ||
111 | data->psy.type = POWER_SUPPLY_TYPE_USB; | ||
112 | else | ||
113 | data->psy.type = POWER_SUPPLY_TYPE_BATTERY; | ||
114 | |||
115 | if (old_type != data->psy.type) | ||
116 | power_supply_changed(&data->psy); | ||
117 | |||
118 | return IRQ_HANDLED; | ||
119 | } | ||
120 | |||
121 | static irqreturn_t max8903_usbin(int irq, void *_data) | ||
122 | { | ||
123 | struct max8903_data *data = _data; | ||
124 | struct max8903_pdata *pdata = data->pdata; | ||
125 | bool usb_in; | ||
126 | enum power_supply_type old_type; | ||
127 | |||
128 | usb_in = gpio_get_value(pdata->uok) ? false : true; | ||
129 | |||
130 | if (usb_in == data->usb_in) | ||
131 | return IRQ_HANDLED; | ||
132 | |||
133 | data->usb_in = usb_in; | ||
134 | |||
135 | /* Do not touch Current-Limit-Mode */ | ||
136 | |||
137 | /* Charger Enable / Disable (cen is negated) */ | ||
138 | if (pdata->cen) | ||
139 | gpio_set_value(pdata->cen, usb_in ? 0 : | ||
140 | (data->ta_in ? 0 : 1)); | ||
141 | |||
142 | dev_dbg(data->dev, "USB Charger %s.\n", usb_in ? | ||
143 | "Connected" : "Disconnected"); | ||
144 | |||
145 | old_type = data->psy.type; | ||
146 | |||
147 | if (data->ta_in) | ||
148 | data->psy.type = POWER_SUPPLY_TYPE_MAINS; | ||
149 | else if (data->usb_in) | ||
150 | data->psy.type = POWER_SUPPLY_TYPE_USB; | ||
151 | else | ||
152 | data->psy.type = POWER_SUPPLY_TYPE_BATTERY; | ||
153 | |||
154 | if (old_type != data->psy.type) | ||
155 | power_supply_changed(&data->psy); | ||
156 | |||
157 | return IRQ_HANDLED; | ||
158 | } | ||
159 | |||
160 | static irqreturn_t max8903_fault(int irq, void *_data) | ||
161 | { | ||
162 | struct max8903_data *data = _data; | ||
163 | struct max8903_pdata *pdata = data->pdata; | ||
164 | bool fault; | ||
165 | |||
166 | fault = gpio_get_value(pdata->flt) ? false : true; | ||
167 | |||
168 | if (fault == data->fault) | ||
169 | return IRQ_HANDLED; | ||
170 | |||
171 | data->fault = fault; | ||
172 | |||
173 | if (fault) | ||
174 | dev_err(data->dev, "Charger suffers a fault and stops.\n"); | ||
175 | else | ||
176 | dev_err(data->dev, "Charger recovered from a fault.\n"); | ||
177 | |||
178 | return IRQ_HANDLED; | ||
179 | } | ||
180 | |||
181 | static __devinit int max8903_probe(struct platform_device *pdev) | ||
182 | { | ||
183 | struct max8903_data *data; | ||
184 | struct device *dev = &pdev->dev; | ||
185 | struct max8903_pdata *pdata = pdev->dev.platform_data; | ||
186 | int ret = 0; | ||
187 | int gpio; | ||
188 | int ta_in = 0; | ||
189 | int usb_in = 0; | ||
190 | |||
191 | data = kzalloc(sizeof(struct max8903_data), GFP_KERNEL); | ||
192 | if (data == NULL) { | ||
193 | dev_err(dev, "Cannot allocate memory.\n"); | ||
194 | return -ENOMEM; | ||
195 | } | ||
196 | data->pdata = pdata; | ||
197 | data->dev = dev; | ||
198 | platform_set_drvdata(pdev, data); | ||
199 | |||
200 | if (pdata->dc_valid == false && pdata->usb_valid == false) { | ||
201 | dev_err(dev, "No valid power sources.\n"); | ||
202 | ret = -EINVAL; | ||
203 | goto err; | ||
204 | } | ||
205 | |||
206 | if (pdata->dc_valid) { | ||
207 | if (pdata->dok && gpio_is_valid(pdata->dok) && | ||
208 | pdata->dcm && gpio_is_valid(pdata->dcm)) { | ||
209 | gpio = pdata->dok; /* PULL_UPed Interrupt */ | ||
210 | ta_in = gpio_get_value(gpio) ? 0 : 1; | ||
211 | |||
212 | gpio = pdata->dcm; /* Output */ | ||
213 | gpio_set_value(gpio, ta_in); | ||
214 | } else { | ||
215 | dev_err(dev, "When DC is wired, DOK and DCM should" | ||
216 | " be wired as well.\n"); | ||
217 | ret = -EINVAL; | ||
218 | goto err; | ||
219 | } | ||
220 | } else { | ||
221 | if (pdata->dcm) { | ||
222 | if (gpio_is_valid(pdata->dcm)) | ||
223 | gpio_set_value(pdata->dcm, 0); | ||
224 | else { | ||
225 | dev_err(dev, "Invalid pin: dcm.\n"); | ||
226 | ret = -EINVAL; | ||
227 | goto err; | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | |||
232 | if (pdata->usb_valid) { | ||
233 | if (pdata->uok && gpio_is_valid(pdata->uok)) { | ||
234 | gpio = pdata->uok; | ||
235 | usb_in = gpio_get_value(gpio) ? 0 : 1; | ||
236 | } else { | ||
237 | dev_err(dev, "When USB is wired, UOK should be wired." | ||
238 | "as well.\n"); | ||
239 | ret = -EINVAL; | ||
240 | goto err; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | if (pdata->cen) { | ||
245 | if (gpio_is_valid(pdata->cen)) { | ||
246 | gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1); | ||
247 | } else { | ||
248 | dev_err(dev, "Invalid pin: cen.\n"); | ||
249 | ret = -EINVAL; | ||
250 | goto err; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | if (pdata->chg) { | ||
255 | if (!gpio_is_valid(pdata->chg)) { | ||
256 | dev_err(dev, "Invalid pin: chg.\n"); | ||
257 | ret = -EINVAL; | ||
258 | goto err; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | if (pdata->flt) { | ||
263 | if (!gpio_is_valid(pdata->flt)) { | ||
264 | dev_err(dev, "Invalid pin: flt.\n"); | ||
265 | ret = -EINVAL; | ||
266 | goto err; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | if (pdata->usus) { | ||
271 | if (!gpio_is_valid(pdata->usus)) { | ||
272 | dev_err(dev, "Invalid pin: usus.\n"); | ||
273 | ret = -EINVAL; | ||
274 | goto err; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | data->fault = false; | ||
279 | data->ta_in = ta_in; | ||
280 | data->usb_in = usb_in; | ||
281 | |||
282 | data->psy.name = "max8903_charger"; | ||
283 | data->psy.type = (ta_in) ? POWER_SUPPLY_TYPE_MAINS : | ||
284 | ((usb_in) ? POWER_SUPPLY_TYPE_USB : | ||
285 | POWER_SUPPLY_TYPE_BATTERY); | ||
286 | data->psy.get_property = max8903_get_property; | ||
287 | data->psy.properties = max8903_charger_props; | ||
288 | data->psy.num_properties = ARRAY_SIZE(max8903_charger_props); | ||
289 | |||
290 | ret = power_supply_register(dev, &data->psy); | ||
291 | if (ret) { | ||
292 | dev_err(dev, "failed: power supply register.\n"); | ||
293 | goto err; | ||
294 | } | ||
295 | |||
296 | if (pdata->dc_valid) { | ||
297 | ret = request_threaded_irq(gpio_to_irq(pdata->dok), | ||
298 | NULL, max8903_dcin, | ||
299 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
300 | "MAX8903 DC IN", data); | ||
301 | if (ret) { | ||
302 | dev_err(dev, "Cannot request irq %d for DC (%d)\n", | ||
303 | gpio_to_irq(pdata->dok), ret); | ||
304 | goto err_psy; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | if (pdata->usb_valid) { | ||
309 | ret = request_threaded_irq(gpio_to_irq(pdata->uok), | ||
310 | NULL, max8903_usbin, | ||
311 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
312 | "MAX8903 USB IN", data); | ||
313 | if (ret) { | ||
314 | dev_err(dev, "Cannot request irq %d for USB (%d)\n", | ||
315 | gpio_to_irq(pdata->uok), ret); | ||
316 | goto err_dc_irq; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | if (pdata->flt) { | ||
321 | ret = request_threaded_irq(gpio_to_irq(pdata->flt), | ||
322 | NULL, max8903_fault, | ||
323 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
324 | "MAX8903 Fault", data); | ||
325 | if (ret) { | ||
326 | dev_err(dev, "Cannot request irq %d for Fault (%d)\n", | ||
327 | gpio_to_irq(pdata->flt), ret); | ||
328 | goto err_usb_irq; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | return 0; | ||
333 | |||
334 | err_usb_irq: | ||
335 | if (pdata->usb_valid) | ||
336 | free_irq(gpio_to_irq(pdata->uok), data); | ||
337 | err_dc_irq: | ||
338 | if (pdata->dc_valid) | ||
339 | free_irq(gpio_to_irq(pdata->dok), data); | ||
340 | err_psy: | ||
341 | power_supply_unregister(&data->psy); | ||
342 | err: | ||
343 | kfree(data); | ||
344 | return ret; | ||
345 | } | ||
346 | |||
347 | static __devexit int max8903_remove(struct platform_device *pdev) | ||
348 | { | ||
349 | struct max8903_data *data = platform_get_drvdata(pdev); | ||
350 | |||
351 | if (data) { | ||
352 | struct max8903_pdata *pdata = data->pdata; | ||
353 | |||
354 | if (pdata->flt) | ||
355 | free_irq(gpio_to_irq(pdata->flt), data); | ||
356 | if (pdata->usb_valid) | ||
357 | free_irq(gpio_to_irq(pdata->uok), data); | ||
358 | if (pdata->dc_valid) | ||
359 | free_irq(gpio_to_irq(pdata->dok), data); | ||
360 | power_supply_unregister(&data->psy); | ||
361 | kfree(data); | ||
362 | } | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static struct platform_driver max8903_driver = { | ||
368 | .probe = max8903_probe, | ||
369 | .remove = __devexit_p(max8903_remove), | ||
370 | .driver = { | ||
371 | .name = "max8903-charger", | ||
372 | .owner = THIS_MODULE, | ||
373 | }, | ||
374 | }; | ||
375 | |||
376 | static int __init max8903_init(void) | ||
377 | { | ||
378 | return platform_driver_register(&max8903_driver); | ||
379 | } | ||
380 | module_init(max8903_init); | ||
381 | |||
382 | static void __exit max8903_exit(void) | ||
383 | { | ||
384 | platform_driver_unregister(&max8903_driver); | ||
385 | } | ||
386 | module_exit(max8903_exit); | ||
387 | |||
388 | MODULE_LICENSE("GPL"); | ||
389 | MODULE_DESCRIPTION("MAX8903 Charger Driver"); | ||
390 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | ||
391 | MODULE_ALIAS("max8903-charger"); | ||
diff --git a/drivers/power/test_power.c b/drivers/power/test_power.c index 0cd9f67d33e5..b527c93bf2f3 100644 --- a/drivers/power/test_power.c +++ b/drivers/power/test_power.c | |||
@@ -3,6 +3,12 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2010 Anton Vorontsov <cbouatmailru@gmail.com> | 4 | * Copyright 2010 Anton Vorontsov <cbouatmailru@gmail.com> |
5 | * | 5 | * |
6 | * Dynamic module parameter code from the Virtual Battery Driver | ||
7 | * Copyright (C) 2008 Pylone, Inc. | ||
8 | * By: Masashi YOKOTA <yokota@pylone.jp> | ||
9 | * Originally found here: | ||
10 | * http://downloads.pylone.jp/src/virtual_battery/virtual_battery-0.0.1.tar.bz2 | ||
11 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 13 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 14 | * published by the Free Software Foundation. |
@@ -15,8 +21,12 @@ | |||
15 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
16 | #include <linux/vermagic.h> | 22 | #include <linux/vermagic.h> |
17 | 23 | ||
18 | static int test_power_ac_online = 1; | 24 | static int ac_online = 1; |
19 | static int test_power_battery_status = POWER_SUPPLY_STATUS_CHARGING; | 25 | static int battery_status = POWER_SUPPLY_STATUS_DISCHARGING; |
26 | static int battery_health = POWER_SUPPLY_HEALTH_GOOD; | ||
27 | static int battery_present = 1; /* true */ | ||
28 | static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION; | ||
29 | static int battery_capacity = 50; | ||
20 | 30 | ||
21 | static int test_power_get_ac_property(struct power_supply *psy, | 31 | static int test_power_get_ac_property(struct power_supply *psy, |
22 | enum power_supply_property psp, | 32 | enum power_supply_property psp, |
@@ -24,7 +34,7 @@ static int test_power_get_ac_property(struct power_supply *psy, | |||
24 | { | 34 | { |
25 | switch (psp) { | 35 | switch (psp) { |
26 | case POWER_SUPPLY_PROP_ONLINE: | 36 | case POWER_SUPPLY_PROP_ONLINE: |
27 | val->intval = test_power_ac_online; | 37 | val->intval = ac_online; |
28 | break; | 38 | break; |
29 | default: | 39 | default: |
30 | return -EINVAL; | 40 | return -EINVAL; |
@@ -47,22 +57,30 @@ static int test_power_get_battery_property(struct power_supply *psy, | |||
47 | val->strval = UTS_RELEASE; | 57 | val->strval = UTS_RELEASE; |
48 | break; | 58 | break; |
49 | case POWER_SUPPLY_PROP_STATUS: | 59 | case POWER_SUPPLY_PROP_STATUS: |
50 | val->intval = test_power_battery_status; | 60 | val->intval = battery_status; |
51 | break; | 61 | break; |
52 | case POWER_SUPPLY_PROP_CHARGE_TYPE: | 62 | case POWER_SUPPLY_PROP_CHARGE_TYPE: |
53 | val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; | 63 | val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; |
54 | break; | 64 | break; |
55 | case POWER_SUPPLY_PROP_HEALTH: | 65 | case POWER_SUPPLY_PROP_HEALTH: |
56 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | 66 | val->intval = battery_health; |
67 | break; | ||
68 | case POWER_SUPPLY_PROP_PRESENT: | ||
69 | val->intval = battery_present; | ||
57 | break; | 70 | break; |
58 | case POWER_SUPPLY_PROP_TECHNOLOGY: | 71 | case POWER_SUPPLY_PROP_TECHNOLOGY: |
59 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; | 72 | val->intval = battery_technology; |
60 | break; | 73 | break; |
61 | case POWER_SUPPLY_PROP_CAPACITY_LEVEL: | 74 | case POWER_SUPPLY_PROP_CAPACITY_LEVEL: |
62 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | 75 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; |
63 | break; | 76 | break; |
64 | case POWER_SUPPLY_PROP_CAPACITY: | 77 | case POWER_SUPPLY_PROP_CAPACITY: |
65 | val->intval = 50; | 78 | case POWER_SUPPLY_PROP_CHARGE_NOW: |
79 | val->intval = battery_capacity; | ||
80 | break; | ||
81 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
82 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
83 | val->intval = 100; | ||
66 | break; | 84 | break; |
67 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: | 85 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: |
68 | case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: | 86 | case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: |
@@ -84,9 +102,11 @@ static enum power_supply_property test_power_battery_props[] = { | |||
84 | POWER_SUPPLY_PROP_STATUS, | 102 | POWER_SUPPLY_PROP_STATUS, |
85 | POWER_SUPPLY_PROP_CHARGE_TYPE, | 103 | POWER_SUPPLY_PROP_CHARGE_TYPE, |
86 | POWER_SUPPLY_PROP_HEALTH, | 104 | POWER_SUPPLY_PROP_HEALTH, |
105 | POWER_SUPPLY_PROP_PRESENT, | ||
87 | POWER_SUPPLY_PROP_TECHNOLOGY, | 106 | POWER_SUPPLY_PROP_TECHNOLOGY, |
107 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
88 | POWER_SUPPLY_PROP_CHARGE_FULL, | 108 | POWER_SUPPLY_PROP_CHARGE_FULL, |
89 | POWER_SUPPLY_PROP_CHARGE_EMPTY, | 109 | POWER_SUPPLY_PROP_CHARGE_NOW, |
90 | POWER_SUPPLY_PROP_CAPACITY, | 110 | POWER_SUPPLY_PROP_CAPACITY, |
91 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | 111 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, |
92 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, | 112 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, |
@@ -118,6 +138,7 @@ static struct power_supply test_power_supplies[] = { | |||
118 | }, | 138 | }, |
119 | }; | 139 | }; |
120 | 140 | ||
141 | |||
121 | static int __init test_power_init(void) | 142 | static int __init test_power_init(void) |
122 | { | 143 | { |
123 | int i; | 144 | int i; |
@@ -145,8 +166,8 @@ static void __exit test_power_exit(void) | |||
145 | int i; | 166 | int i; |
146 | 167 | ||
147 | /* Let's see how we handle changes... */ | 168 | /* Let's see how we handle changes... */ |
148 | test_power_ac_online = 0; | 169 | ac_online = 0; |
149 | test_power_battery_status = POWER_SUPPLY_STATUS_DISCHARGING; | 170 | battery_status = POWER_SUPPLY_STATUS_DISCHARGING; |
150 | for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) | 171 | for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) |
151 | power_supply_changed(&test_power_supplies[i]); | 172 | power_supply_changed(&test_power_supplies[i]); |
152 | pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n", | 173 | pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n", |
@@ -158,6 +179,241 @@ static void __exit test_power_exit(void) | |||
158 | } | 179 | } |
159 | module_exit(test_power_exit); | 180 | module_exit(test_power_exit); |
160 | 181 | ||
182 | |||
183 | |||
184 | #define MAX_KEYLENGTH 256 | ||
185 | struct battery_property_map { | ||
186 | int value; | ||
187 | char const *key; | ||
188 | }; | ||
189 | |||
190 | static struct battery_property_map map_ac_online[] = { | ||
191 | { 0, "on" }, | ||
192 | { 1, "off" }, | ||
193 | { -1, NULL }, | ||
194 | }; | ||
195 | |||
196 | static struct battery_property_map map_status[] = { | ||
197 | { POWER_SUPPLY_STATUS_CHARGING, "charging" }, | ||
198 | { POWER_SUPPLY_STATUS_DISCHARGING, "discharging" }, | ||
199 | { POWER_SUPPLY_STATUS_NOT_CHARGING, "not-charging" }, | ||
200 | { POWER_SUPPLY_STATUS_FULL, "full" }, | ||
201 | { -1, NULL }, | ||
202 | }; | ||
203 | |||
204 | static struct battery_property_map map_health[] = { | ||
205 | { POWER_SUPPLY_HEALTH_GOOD, "good" }, | ||
206 | { POWER_SUPPLY_HEALTH_OVERHEAT, "overheat" }, | ||
207 | { POWER_SUPPLY_HEALTH_DEAD, "dead" }, | ||
208 | { POWER_SUPPLY_HEALTH_OVERVOLTAGE, "overvoltage" }, | ||
209 | { POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, "failure" }, | ||
210 | { -1, NULL }, | ||
211 | }; | ||
212 | |||
213 | static struct battery_property_map map_present[] = { | ||
214 | { 0, "false" }, | ||
215 | { 1, "true" }, | ||
216 | { -1, NULL }, | ||
217 | }; | ||
218 | |||
219 | static struct battery_property_map map_technology[] = { | ||
220 | { POWER_SUPPLY_TECHNOLOGY_NiMH, "NiMH" }, | ||
221 | { POWER_SUPPLY_TECHNOLOGY_LION, "LION" }, | ||
222 | { POWER_SUPPLY_TECHNOLOGY_LIPO, "LIPO" }, | ||
223 | { POWER_SUPPLY_TECHNOLOGY_LiFe, "LiFe" }, | ||
224 | { POWER_SUPPLY_TECHNOLOGY_NiCd, "NiCd" }, | ||
225 | { POWER_SUPPLY_TECHNOLOGY_LiMn, "LiMn" }, | ||
226 | { -1, NULL }, | ||
227 | }; | ||
228 | |||
229 | |||
230 | static int map_get_value(struct battery_property_map *map, const char *key, | ||
231 | int def_val) | ||
232 | { | ||
233 | char buf[MAX_KEYLENGTH]; | ||
234 | int cr; | ||
235 | |||
236 | strncpy(buf, key, MAX_KEYLENGTH); | ||
237 | buf[MAX_KEYLENGTH-1] = '\0'; | ||
238 | |||
239 | cr = strnlen(buf, MAX_KEYLENGTH) - 1; | ||
240 | if (buf[cr] == '\n') | ||
241 | buf[cr] = '\0'; | ||
242 | |||
243 | while (map->key) { | ||
244 | if (strncasecmp(map->key, buf, MAX_KEYLENGTH) == 0) | ||
245 | return map->value; | ||
246 | map++; | ||
247 | } | ||
248 | |||
249 | return def_val; | ||
250 | } | ||
251 | |||
252 | |||
253 | static const char *map_get_key(struct battery_property_map *map, int value, | ||
254 | const char *def_key) | ||
255 | { | ||
256 | while (map->key) { | ||
257 | if (map->value == value) | ||
258 | return map->key; | ||
259 | map++; | ||
260 | } | ||
261 | |||
262 | return def_key; | ||
263 | } | ||
264 | |||
265 | static int param_set_ac_online(const char *key, const struct kernel_param *kp) | ||
266 | { | ||
267 | ac_online = map_get_value(map_ac_online, key, ac_online); | ||
268 | power_supply_changed(&test_power_supplies[0]); | ||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int param_get_ac_online(char *buffer, const struct kernel_param *kp) | ||
273 | { | ||
274 | strcpy(buffer, map_get_key(map_ac_online, ac_online, "unknown")); | ||
275 | return strlen(buffer); | ||
276 | } | ||
277 | |||
278 | static int param_set_battery_status(const char *key, | ||
279 | const struct kernel_param *kp) | ||
280 | { | ||
281 | battery_status = map_get_value(map_status, key, battery_status); | ||
282 | power_supply_changed(&test_power_supplies[1]); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static int param_get_battery_status(char *buffer, const struct kernel_param *kp) | ||
287 | { | ||
288 | strcpy(buffer, map_get_key(map_status, battery_status, "unknown")); | ||
289 | return strlen(buffer); | ||
290 | } | ||
291 | |||
292 | static int param_set_battery_health(const char *key, | ||
293 | const struct kernel_param *kp) | ||
294 | { | ||
295 | battery_health = map_get_value(map_health, key, battery_health); | ||
296 | power_supply_changed(&test_power_supplies[1]); | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int param_get_battery_health(char *buffer, const struct kernel_param *kp) | ||
301 | { | ||
302 | strcpy(buffer, map_get_key(map_health, battery_health, "unknown")); | ||
303 | return strlen(buffer); | ||
304 | } | ||
305 | |||
306 | static int param_set_battery_present(const char *key, | ||
307 | const struct kernel_param *kp) | ||
308 | { | ||
309 | battery_present = map_get_value(map_present, key, battery_present); | ||
310 | power_supply_changed(&test_power_supplies[0]); | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static int param_get_battery_present(char *buffer, | ||
315 | const struct kernel_param *kp) | ||
316 | { | ||
317 | strcpy(buffer, map_get_key(map_present, battery_present, "unknown")); | ||
318 | return strlen(buffer); | ||
319 | } | ||
320 | |||
321 | static int param_set_battery_technology(const char *key, | ||
322 | const struct kernel_param *kp) | ||
323 | { | ||
324 | battery_technology = map_get_value(map_technology, key, | ||
325 | battery_technology); | ||
326 | power_supply_changed(&test_power_supplies[1]); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static int param_get_battery_technology(char *buffer, | ||
331 | const struct kernel_param *kp) | ||
332 | { | ||
333 | strcpy(buffer, | ||
334 | map_get_key(map_technology, battery_technology, "unknown")); | ||
335 | return strlen(buffer); | ||
336 | } | ||
337 | |||
338 | static int param_set_battery_capacity(const char *key, | ||
339 | const struct kernel_param *kp) | ||
340 | { | ||
341 | int tmp; | ||
342 | |||
343 | if (1 != sscanf(key, "%d", &tmp)) | ||
344 | return -EINVAL; | ||
345 | |||
346 | battery_capacity = tmp; | ||
347 | power_supply_changed(&test_power_supplies[1]); | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | #define param_get_battery_capacity param_get_int | ||
352 | |||
353 | |||
354 | |||
355 | static struct kernel_param_ops param_ops_ac_online = { | ||
356 | .set = param_set_ac_online, | ||
357 | .get = param_get_ac_online, | ||
358 | }; | ||
359 | |||
360 | static struct kernel_param_ops param_ops_battery_status = { | ||
361 | .set = param_set_battery_status, | ||
362 | .get = param_get_battery_status, | ||
363 | }; | ||
364 | |||
365 | static struct kernel_param_ops param_ops_battery_present = { | ||
366 | .set = param_set_battery_present, | ||
367 | .get = param_get_battery_present, | ||
368 | }; | ||
369 | |||
370 | static struct kernel_param_ops param_ops_battery_technology = { | ||
371 | .set = param_set_battery_technology, | ||
372 | .get = param_get_battery_technology, | ||
373 | }; | ||
374 | |||
375 | static struct kernel_param_ops param_ops_battery_health = { | ||
376 | .set = param_set_battery_health, | ||
377 | .get = param_get_battery_health, | ||
378 | }; | ||
379 | |||
380 | static struct kernel_param_ops param_ops_battery_capacity = { | ||
381 | .set = param_set_battery_capacity, | ||
382 | .get = param_get_battery_capacity, | ||
383 | }; | ||
384 | |||
385 | |||
386 | #define param_check_ac_online(name, p) __param_check(name, p, void); | ||
387 | #define param_check_battery_status(name, p) __param_check(name, p, void); | ||
388 | #define param_check_battery_present(name, p) __param_check(name, p, void); | ||
389 | #define param_check_battery_technology(name, p) __param_check(name, p, void); | ||
390 | #define param_check_battery_health(name, p) __param_check(name, p, void); | ||
391 | #define param_check_battery_capacity(name, p) __param_check(name, p, void); | ||
392 | |||
393 | |||
394 | module_param(ac_online, ac_online, 0644); | ||
395 | MODULE_PARM_DESC(ac_online, "AC charging state <on|off>"); | ||
396 | |||
397 | module_param(battery_status, battery_status, 0644); | ||
398 | MODULE_PARM_DESC(battery_status, | ||
399 | "battery status <charging|discharging|not-charging|full>"); | ||
400 | |||
401 | module_param(battery_present, battery_present, 0644); | ||
402 | MODULE_PARM_DESC(battery_present, | ||
403 | "battery presence state <good|overheat|dead|overvoltage|failure>"); | ||
404 | |||
405 | module_param(battery_technology, battery_technology, 0644); | ||
406 | MODULE_PARM_DESC(battery_technology, | ||
407 | "battery technology <NiMH|LION|LIPO|LiFe|NiCd|LiMn>"); | ||
408 | |||
409 | module_param(battery_health, battery_health, 0644); | ||
410 | MODULE_PARM_DESC(battery_health, | ||
411 | "battery health state <good|overheat|dead|overvoltage|failure>"); | ||
412 | |||
413 | module_param(battery_capacity, battery_capacity, 0644); | ||
414 | MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)"); | ||
415 | |||
416 | |||
161 | MODULE_DESCRIPTION("Power supply driver for testing"); | 417 | MODULE_DESCRIPTION("Power supply driver for testing"); |
162 | MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); | 418 | MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); |
163 | MODULE_LICENSE("GPL"); | 419 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c index e5ced3a4c1ed..d119c38b3ff6 100644 --- a/drivers/power/z2_battery.c +++ b/drivers/power/z2_battery.c | |||
@@ -271,24 +271,33 @@ static int __devexit z2_batt_remove(struct i2c_client *client) | |||
271 | } | 271 | } |
272 | 272 | ||
273 | #ifdef CONFIG_PM | 273 | #ifdef CONFIG_PM |
274 | static int z2_batt_suspend(struct i2c_client *client, pm_message_t state) | 274 | static int z2_batt_suspend(struct device *dev) |
275 | { | 275 | { |
276 | struct i2c_client *client = to_i2c_client(dev); | ||
276 | struct z2_charger *charger = i2c_get_clientdata(client); | 277 | struct z2_charger *charger = i2c_get_clientdata(client); |
277 | 278 | ||
278 | flush_work_sync(&charger->bat_work); | 279 | flush_work_sync(&charger->bat_work); |
279 | return 0; | 280 | return 0; |
280 | } | 281 | } |
281 | 282 | ||
282 | static int z2_batt_resume(struct i2c_client *client) | 283 | static int z2_batt_resume(struct device *dev) |
283 | { | 284 | { |
285 | struct i2c_client *client = to_i2c_client(dev); | ||
284 | struct z2_charger *charger = i2c_get_clientdata(client); | 286 | struct z2_charger *charger = i2c_get_clientdata(client); |
285 | 287 | ||
286 | schedule_work(&charger->bat_work); | 288 | schedule_work(&charger->bat_work); |
287 | return 0; | 289 | return 0; |
288 | } | 290 | } |
291 | |||
292 | static const struct dev_pm_ops z2_battery_pm_ops = { | ||
293 | .suspend = z2_batt_suspend, | ||
294 | .resume = z2_batt_resume, | ||
295 | }; | ||
296 | |||
297 | #define Z2_BATTERY_PM_OPS (&z2_battery_pm_ops) | ||
298 | |||
289 | #else | 299 | #else |
290 | #define z2_batt_suspend NULL | 300 | #define Z2_BATTERY_PM_OPS (NULL) |
291 | #define z2_batt_resume NULL | ||
292 | #endif | 301 | #endif |
293 | 302 | ||
294 | static const struct i2c_device_id z2_batt_id[] = { | 303 | static const struct i2c_device_id z2_batt_id[] = { |
@@ -301,11 +310,10 @@ static struct i2c_driver z2_batt_driver = { | |||
301 | .driver = { | 310 | .driver = { |
302 | .name = "z2-battery", | 311 | .name = "z2-battery", |
303 | .owner = THIS_MODULE, | 312 | .owner = THIS_MODULE, |
313 | .pm = Z2_BATTERY_PM_OPS | ||
304 | }, | 314 | }, |
305 | .probe = z2_batt_probe, | 315 | .probe = z2_batt_probe, |
306 | .remove = z2_batt_remove, | 316 | .remove = z2_batt_remove, |
307 | .suspend = z2_batt_suspend, | ||
308 | .resume = z2_batt_resume, | ||
309 | .id_table = z2_batt_id, | 317 | .id_table = z2_batt_id, |
310 | }; | 318 | }; |
311 | 319 | ||
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index f0b13a0d1851..d7ed20f293d7 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -297,5 +297,11 @@ config REGULATOR_TPS6524X | |||
297 | serial interface currently supported on the sequencer serial | 297 | serial interface currently supported on the sequencer serial |
298 | port controller. | 298 | port controller. |
299 | 299 | ||
300 | config REGULATOR_TPS65910 | ||
301 | tristate "TI TPS65910 Power Regulator" | ||
302 | depends on MFD_TPS65910 | ||
303 | help | ||
304 | This driver supports TPS65910 voltage regulator chips. | ||
305 | |||
300 | endif | 306 | endif |
301 | 307 | ||
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 165ff5371e9e..3932d2ec38f3 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -42,5 +42,6 @@ obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o | |||
42 | obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o | 42 | obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o |
43 | obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o | 43 | obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o |
44 | obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o | 44 | obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o |
45 | obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o | ||
45 | 46 | ||
46 | ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG | 47 | ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 0fae51c4845a..d3e38790906e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -158,6 +158,13 @@ static int regulator_check_consumers(struct regulator_dev *rdev, | |||
158 | struct regulator *regulator; | 158 | struct regulator *regulator; |
159 | 159 | ||
160 | list_for_each_entry(regulator, &rdev->consumer_list, list) { | 160 | list_for_each_entry(regulator, &rdev->consumer_list, list) { |
161 | /* | ||
162 | * Assume consumers that didn't say anything are OK | ||
163 | * with anything in the constraint range. | ||
164 | */ | ||
165 | if (!regulator->min_uV && !regulator->max_uV) | ||
166 | continue; | ||
167 | |||
161 | if (*max_uV > regulator->max_uV) | 168 | if (*max_uV > regulator->max_uV) |
162 | *max_uV = regulator->max_uV; | 169 | *max_uV = regulator->max_uV; |
163 | if (*min_uV < regulator->min_uV) | 170 | if (*min_uV < regulator->min_uV) |
@@ -197,9 +204,9 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, | |||
197 | } | 204 | } |
198 | 205 | ||
199 | /* operating mode constraint check */ | 206 | /* operating mode constraint check */ |
200 | static int regulator_check_mode(struct regulator_dev *rdev, int mode) | 207 | static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) |
201 | { | 208 | { |
202 | switch (mode) { | 209 | switch (*mode) { |
203 | case REGULATOR_MODE_FAST: | 210 | case REGULATOR_MODE_FAST: |
204 | case REGULATOR_MODE_NORMAL: | 211 | case REGULATOR_MODE_NORMAL: |
205 | case REGULATOR_MODE_IDLE: | 212 | case REGULATOR_MODE_IDLE: |
@@ -217,11 +224,17 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode) | |||
217 | rdev_err(rdev, "operation not allowed\n"); | 224 | rdev_err(rdev, "operation not allowed\n"); |
218 | return -EPERM; | 225 | return -EPERM; |
219 | } | 226 | } |
220 | if (!(rdev->constraints->valid_modes_mask & mode)) { | 227 | |
221 | rdev_err(rdev, "invalid mode %x\n", mode); | 228 | /* The modes are bitmasks, the most power hungry modes having |
222 | return -EINVAL; | 229 | * the lowest values. If the requested mode isn't supported |
230 | * try higher modes. */ | ||
231 | while (*mode) { | ||
232 | if (rdev->constraints->valid_modes_mask & *mode) | ||
233 | return 0; | ||
234 | *mode /= 2; | ||
223 | } | 235 | } |
224 | return 0; | 236 | |
237 | return -EINVAL; | ||
225 | } | 238 | } |
226 | 239 | ||
227 | /* dynamic regulator mode switching constraint check */ | 240 | /* dynamic regulator mode switching constraint check */ |
@@ -612,7 +625,7 @@ static void drms_uA_update(struct regulator_dev *rdev) | |||
612 | output_uV, current_uA); | 625 | output_uV, current_uA); |
613 | 626 | ||
614 | /* check the new mode is allowed */ | 627 | /* check the new mode is allowed */ |
615 | err = regulator_check_mode(rdev, mode); | 628 | err = regulator_mode_constrain(rdev, &mode); |
616 | if (err == 0) | 629 | if (err == 0) |
617 | rdev->desc->ops->set_mode(rdev, mode); | 630 | rdev->desc->ops->set_mode(rdev, mode); |
618 | } | 631 | } |
@@ -718,6 +731,10 @@ static void print_constraints(struct regulator_dev *rdev) | |||
718 | count += sprintf(buf + count, "at %d mV ", ret / 1000); | 731 | count += sprintf(buf + count, "at %d mV ", ret / 1000); |
719 | } | 732 | } |
720 | 733 | ||
734 | if (constraints->uV_offset) | ||
735 | count += sprintf(buf, "%dmV offset ", | ||
736 | constraints->uV_offset / 1000); | ||
737 | |||
721 | if (constraints->min_uA && constraints->max_uA) { | 738 | if (constraints->min_uA && constraints->max_uA) { |
722 | if (constraints->min_uA == constraints->max_uA) | 739 | if (constraints->min_uA == constraints->max_uA) |
723 | count += sprintf(buf + count, "%d mA ", | 740 | count += sprintf(buf + count, "%d mA ", |
@@ -1498,13 +1515,14 @@ static int _regulator_force_disable(struct regulator_dev *rdev, | |||
1498 | */ | 1515 | */ |
1499 | int regulator_force_disable(struct regulator *regulator) | 1516 | int regulator_force_disable(struct regulator *regulator) |
1500 | { | 1517 | { |
1518 | struct regulator_dev *rdev = regulator->rdev; | ||
1501 | struct regulator_dev *supply_rdev = NULL; | 1519 | struct regulator_dev *supply_rdev = NULL; |
1502 | int ret; | 1520 | int ret; |
1503 | 1521 | ||
1504 | mutex_lock(®ulator->rdev->mutex); | 1522 | mutex_lock(&rdev->mutex); |
1505 | regulator->uA_load = 0; | 1523 | regulator->uA_load = 0; |
1506 | ret = _regulator_force_disable(regulator->rdev, &supply_rdev); | 1524 | ret = _regulator_force_disable(rdev, &supply_rdev); |
1507 | mutex_unlock(®ulator->rdev->mutex); | 1525 | mutex_unlock(&rdev->mutex); |
1508 | 1526 | ||
1509 | if (supply_rdev) | 1527 | if (supply_rdev) |
1510 | regulator_disable(get_device_regulator(rdev_get_dev(supply_rdev))); | 1528 | regulator_disable(get_device_regulator(rdev_get_dev(supply_rdev))); |
@@ -1634,6 +1652,9 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, | |||
1634 | 1652 | ||
1635 | trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); | 1653 | trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); |
1636 | 1654 | ||
1655 | min_uV += rdev->constraints->uV_offset; | ||
1656 | max_uV += rdev->constraints->uV_offset; | ||
1657 | |||
1637 | if (rdev->desc->ops->set_voltage) { | 1658 | if (rdev->desc->ops->set_voltage) { |
1638 | ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, | 1659 | ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, |
1639 | &selector); | 1660 | &selector); |
@@ -1858,18 +1879,22 @@ EXPORT_SYMBOL_GPL(regulator_sync_voltage); | |||
1858 | 1879 | ||
1859 | static int _regulator_get_voltage(struct regulator_dev *rdev) | 1880 | static int _regulator_get_voltage(struct regulator_dev *rdev) |
1860 | { | 1881 | { |
1861 | int sel; | 1882 | int sel, ret; |
1862 | 1883 | ||
1863 | if (rdev->desc->ops->get_voltage_sel) { | 1884 | if (rdev->desc->ops->get_voltage_sel) { |
1864 | sel = rdev->desc->ops->get_voltage_sel(rdev); | 1885 | sel = rdev->desc->ops->get_voltage_sel(rdev); |
1865 | if (sel < 0) | 1886 | if (sel < 0) |
1866 | return sel; | 1887 | return sel; |
1867 | return rdev->desc->ops->list_voltage(rdev, sel); | 1888 | ret = rdev->desc->ops->list_voltage(rdev, sel); |
1868 | } | 1889 | } else if (rdev->desc->ops->get_voltage) { |
1869 | if (rdev->desc->ops->get_voltage) | 1890 | ret = rdev->desc->ops->get_voltage(rdev); |
1870 | return rdev->desc->ops->get_voltage(rdev); | 1891 | } else { |
1871 | else | ||
1872 | return -EINVAL; | 1892 | return -EINVAL; |
1893 | } | ||
1894 | |||
1895 | if (ret < 0) | ||
1896 | return ret; | ||
1897 | return ret - rdev->constraints->uV_offset; | ||
1873 | } | 1898 | } |
1874 | 1899 | ||
1875 | /** | 1900 | /** |
@@ -2005,7 +2030,7 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode) | |||
2005 | } | 2030 | } |
2006 | 2031 | ||
2007 | /* constraints check */ | 2032 | /* constraints check */ |
2008 | ret = regulator_check_mode(rdev, mode); | 2033 | ret = regulator_mode_constrain(rdev, &mode); |
2009 | if (ret < 0) | 2034 | if (ret < 0) |
2010 | goto out; | 2035 | goto out; |
2011 | 2036 | ||
@@ -2081,16 +2106,26 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) | |||
2081 | 2106 | ||
2082 | mutex_lock(&rdev->mutex); | 2107 | mutex_lock(&rdev->mutex); |
2083 | 2108 | ||
2109 | /* | ||
2110 | * first check to see if we can set modes at all, otherwise just | ||
2111 | * tell the consumer everything is OK. | ||
2112 | */ | ||
2084 | regulator->uA_load = uA_load; | 2113 | regulator->uA_load = uA_load; |
2085 | ret = regulator_check_drms(rdev); | 2114 | ret = regulator_check_drms(rdev); |
2086 | if (ret < 0) | 2115 | if (ret < 0) { |
2116 | ret = 0; | ||
2087 | goto out; | 2117 | goto out; |
2088 | ret = -EINVAL; | 2118 | } |
2089 | 2119 | ||
2090 | /* sanity check */ | ||
2091 | if (!rdev->desc->ops->get_optimum_mode) | 2120 | if (!rdev->desc->ops->get_optimum_mode) |
2092 | goto out; | 2121 | goto out; |
2093 | 2122 | ||
2123 | /* | ||
2124 | * we can actually do this so any errors are indicators of | ||
2125 | * potential real failure. | ||
2126 | */ | ||
2127 | ret = -EINVAL; | ||
2128 | |||
2094 | /* get output voltage */ | 2129 | /* get output voltage */ |
2095 | output_uV = _regulator_get_voltage(rdev); | 2130 | output_uV = _regulator_get_voltage(rdev); |
2096 | if (output_uV <= 0) { | 2131 | if (output_uV <= 0) { |
@@ -2116,7 +2151,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) | |||
2116 | mode = rdev->desc->ops->get_optimum_mode(rdev, | 2151 | mode = rdev->desc->ops->get_optimum_mode(rdev, |
2117 | input_uV, output_uV, | 2152 | input_uV, output_uV, |
2118 | total_uA_load); | 2153 | total_uA_load); |
2119 | ret = regulator_check_mode(rdev, mode); | 2154 | ret = regulator_mode_constrain(rdev, &mode); |
2120 | if (ret < 0) { | 2155 | if (ret < 0) { |
2121 | rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", | 2156 | rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", |
2122 | total_uA_load, input_uV, output_uV); | 2157 | total_uA_load, input_uV, output_uV); |
@@ -2589,14 +2624,6 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, | |||
2589 | if (ret < 0) | 2624 | if (ret < 0) |
2590 | goto scrub; | 2625 | goto scrub; |
2591 | 2626 | ||
2592 | /* set supply regulator if it exists */ | ||
2593 | if (init_data->supply_regulator && init_data->supply_regulator_dev) { | ||
2594 | dev_err(dev, | ||
2595 | "Supply regulator specified by both name and dev\n"); | ||
2596 | ret = -EINVAL; | ||
2597 | goto scrub; | ||
2598 | } | ||
2599 | |||
2600 | if (init_data->supply_regulator) { | 2627 | if (init_data->supply_regulator) { |
2601 | struct regulator_dev *r; | 2628 | struct regulator_dev *r; |
2602 | int found = 0; | 2629 | int found = 0; |
@@ -2621,14 +2648,6 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, | |||
2621 | goto scrub; | 2648 | goto scrub; |
2622 | } | 2649 | } |
2623 | 2650 | ||
2624 | if (init_data->supply_regulator_dev) { | ||
2625 | dev_warn(dev, "Uses supply_regulator_dev instead of regulator_supply\n"); | ||
2626 | ret = set_supply(rdev, | ||
2627 | dev_get_drvdata(init_data->supply_regulator_dev)); | ||
2628 | if (ret < 0) | ||
2629 | goto scrub; | ||
2630 | } | ||
2631 | |||
2632 | /* add consumers devices */ | 2651 | /* add consumers devices */ |
2633 | for (i = 0; i < init_data->num_consumer_supplies; i++) { | 2652 | for (i = 0; i < init_data->num_consumer_supplies; i++) { |
2634 | ret = set_consumer_device_supply(rdev, | 2653 | ret = set_consumer_device_supply(rdev, |
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 77e0cfb30b23..10d5a1d9768e 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c | |||
@@ -267,7 +267,6 @@ static int max8997_get_enable_register(struct regulator_dev *rdev, | |||
267 | default: | 267 | default: |
268 | /* Not controllable or not exists */ | 268 | /* Not controllable or not exists */ |
269 | return -EINVAL; | 269 | return -EINVAL; |
270 | break; | ||
271 | } | 270 | } |
272 | 271 | ||
273 | return 0; | 272 | return 0; |
@@ -1033,11 +1032,11 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) | |||
1033 | 1032 | ||
1034 | /* For the safety, set max voltage before setting up */ | 1033 | /* For the safety, set max voltage before setting up */ |
1035 | for (i = 0; i < 8; i++) { | 1034 | for (i = 0; i < 8; i++) { |
1036 | max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS(i + 1), | 1035 | max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i, |
1037 | max_buck1, 0x3f); | 1036 | max_buck1, 0x3f); |
1038 | max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS(i + 1), | 1037 | max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i, |
1039 | max_buck2, 0x3f); | 1038 | max_buck2, 0x3f); |
1040 | max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS(i + 1), | 1039 | max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i, |
1041 | max_buck5, 0x3f); | 1040 | max_buck5, 0x3f); |
1042 | } | 1041 | } |
1043 | 1042 | ||
@@ -1114,13 +1113,13 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) | |||
1114 | 1113 | ||
1115 | /* Initialize all the DVS related BUCK registers */ | 1114 | /* Initialize all the DVS related BUCK registers */ |
1116 | for (i = 0; i < 8; i++) { | 1115 | for (i = 0; i < 8; i++) { |
1117 | max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS(i + 1), | 1116 | max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i, |
1118 | max8997->buck1_vol[i], | 1117 | max8997->buck1_vol[i], |
1119 | 0x3f); | 1118 | 0x3f); |
1120 | max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS(i + 1), | 1119 | max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i, |
1121 | max8997->buck2_vol[i], | 1120 | max8997->buck2_vol[i], |
1122 | 0x3f); | 1121 | 0x3f); |
1123 | max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS(i + 1), | 1122 | max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i, |
1124 | max8997->buck5_vol[i], | 1123 | max8997->buck5_vol[i], |
1125 | 0x3f); | 1124 | 0x3f); |
1126 | } | 1125 | } |
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index f57e9c42fdb4..41a1495eec2b 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c | |||
@@ -732,13 +732,15 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
732 | if (!pdata->buck1_set1) { | 732 | if (!pdata->buck1_set1) { |
733 | printk(KERN_ERR "MAX8998 SET1 GPIO defined as 0 !\n"); | 733 | printk(KERN_ERR "MAX8998 SET1 GPIO defined as 0 !\n"); |
734 | WARN_ON(!pdata->buck1_set1); | 734 | WARN_ON(!pdata->buck1_set1); |
735 | return -EIO; | 735 | ret = -EIO; |
736 | goto err_free_mem; | ||
736 | } | 737 | } |
737 | /* Check if SET2 is not equal to 0 */ | 738 | /* Check if SET2 is not equal to 0 */ |
738 | if (!pdata->buck1_set2) { | 739 | if (!pdata->buck1_set2) { |
739 | printk(KERN_ERR "MAX8998 SET2 GPIO defined as 0 !\n"); | 740 | printk(KERN_ERR "MAX8998 SET2 GPIO defined as 0 !\n"); |
740 | WARN_ON(!pdata->buck1_set2); | 741 | WARN_ON(!pdata->buck1_set2); |
741 | return -EIO; | 742 | ret = -EIO; |
743 | goto err_free_mem; | ||
742 | } | 744 | } |
743 | 745 | ||
744 | gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1"); | 746 | gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1"); |
@@ -758,7 +760,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
758 | max8998->buck1_vol[0] = i; | 760 | max8998->buck1_vol[0] = i; |
759 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); | 761 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); |
760 | if (ret) | 762 | if (ret) |
761 | return ret; | 763 | goto err_free_mem; |
762 | 764 | ||
763 | /* Set predefined value for BUCK1 register 2 */ | 765 | /* Set predefined value for BUCK1 register 2 */ |
764 | i = 0; | 766 | i = 0; |
@@ -770,7 +772,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
770 | max8998->buck1_vol[1] = i; | 772 | max8998->buck1_vol[1] = i; |
771 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i); | 773 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i); |
772 | if (ret) | 774 | if (ret) |
773 | return ret; | 775 | goto err_free_mem; |
774 | 776 | ||
775 | /* Set predefined value for BUCK1 register 3 */ | 777 | /* Set predefined value for BUCK1 register 3 */ |
776 | i = 0; | 778 | i = 0; |
@@ -782,7 +784,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
782 | max8998->buck1_vol[2] = i; | 784 | max8998->buck1_vol[2] = i; |
783 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i); | 785 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i); |
784 | if (ret) | 786 | if (ret) |
785 | return ret; | 787 | goto err_free_mem; |
786 | 788 | ||
787 | /* Set predefined value for BUCK1 register 4 */ | 789 | /* Set predefined value for BUCK1 register 4 */ |
788 | i = 0; | 790 | i = 0; |
@@ -794,7 +796,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
794 | max8998->buck1_vol[3] = i; | 796 | max8998->buck1_vol[3] = i; |
795 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i); | 797 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i); |
796 | if (ret) | 798 | if (ret) |
797 | return ret; | 799 | goto err_free_mem; |
798 | 800 | ||
799 | } | 801 | } |
800 | 802 | ||
@@ -803,7 +805,8 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
803 | if (!pdata->buck2_set3) { | 805 | if (!pdata->buck2_set3) { |
804 | printk(KERN_ERR "MAX8998 SET3 GPIO defined as 0 !\n"); | 806 | printk(KERN_ERR "MAX8998 SET3 GPIO defined as 0 !\n"); |
805 | WARN_ON(!pdata->buck2_set3); | 807 | WARN_ON(!pdata->buck2_set3); |
806 | return -EIO; | 808 | ret = -EIO; |
809 | goto err_free_mem; | ||
807 | } | 810 | } |
808 | gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3"); | 811 | gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3"); |
809 | gpio_direction_output(pdata->buck2_set3, | 812 | gpio_direction_output(pdata->buck2_set3, |
@@ -818,7 +821,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
818 | max8998->buck2_vol[0] = i; | 821 | max8998->buck2_vol[0] = i; |
819 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); | 822 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); |
820 | if (ret) | 823 | if (ret) |
821 | return ret; | 824 | goto err_free_mem; |
822 | 825 | ||
823 | /* BUCK2 register 2 */ | 826 | /* BUCK2 register 2 */ |
824 | i = 0; | 827 | i = 0; |
@@ -830,7 +833,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
830 | max8998->buck2_vol[1] = i; | 833 | max8998->buck2_vol[1] = i; |
831 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); | 834 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); |
832 | if (ret) | 835 | if (ret) |
833 | return ret; | 836 | goto err_free_mem; |
834 | } | 837 | } |
835 | 838 | ||
836 | for (i = 0; i < pdata->num_regulators; i++) { | 839 | for (i = 0; i < pdata->num_regulators; i++) { |
@@ -860,6 +863,7 @@ err: | |||
860 | if (rdev[i]) | 863 | if (rdev[i]) |
861 | regulator_unregister(rdev[i]); | 864 | regulator_unregister(rdev[i]); |
862 | 865 | ||
866 | err_free_mem: | ||
863 | kfree(max8998->rdev); | 867 | kfree(max8998->rdev); |
864 | kfree(max8998); | 868 | kfree(max8998); |
865 | 869 | ||
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 1b8f7398a4a8..3285d41842f2 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c | |||
@@ -431,7 +431,8 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev, | |||
431 | int min_uV, int max_uV, unsigned *selector) | 431 | int min_uV, int max_uV, unsigned *selector) |
432 | { | 432 | { |
433 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | 433 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); |
434 | int hi, value, val, mask, id = rdev_get_id(rdev); | 434 | int hi, value, mask, id = rdev_get_id(rdev); |
435 | u32 valread; | ||
435 | int ret; | 436 | int ret; |
436 | 437 | ||
437 | dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", | 438 | dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", |
@@ -447,15 +448,16 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev, | |||
447 | 448 | ||
448 | mc13xxx_lock(priv->mc13xxx); | 449 | mc13xxx_lock(priv->mc13xxx); |
449 | ret = mc13xxx_reg_read(priv->mc13xxx, | 450 | ret = mc13xxx_reg_read(priv->mc13xxx, |
450 | mc13892_regulators[id].vsel_reg, &val); | 451 | mc13892_regulators[id].vsel_reg, &valread); |
451 | if (ret) | 452 | if (ret) |
452 | goto err; | 453 | goto err; |
453 | 454 | ||
454 | hi = val & MC13892_SWITCHERS0_SWxHI; | 455 | if (value > 1375000) |
455 | if (value > 1375) | ||
456 | hi = 1; | 456 | hi = 1; |
457 | if (value < 1100) | 457 | else if (value < 1100000) |
458 | hi = 0; | 458 | hi = 0; |
459 | else | ||
460 | hi = valread & MC13892_SWITCHERS0_SWxHI; | ||
459 | 461 | ||
460 | if (hi) { | 462 | if (hi) { |
461 | value = (value - 1100000) / 25000; | 463 | value = (value - 1100000) / 25000; |
@@ -464,8 +466,10 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev, | |||
464 | value = (value - 600000) / 25000; | 466 | value = (value - 600000) / 25000; |
465 | 467 | ||
466 | mask = mc13892_regulators[id].vsel_mask | MC13892_SWITCHERS0_SWxHI; | 468 | mask = mc13892_regulators[id].vsel_mask | MC13892_SWITCHERS0_SWxHI; |
467 | ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg, | 469 | valread = (valread & ~mask) | |
468 | mask, value << mc13892_regulators[id].vsel_shift); | 470 | (value << mc13892_regulators[id].vsel_shift); |
471 | ret = mc13xxx_reg_write(priv->mc13xxx, mc13892_regulators[id].vsel_reg, | ||
472 | valread); | ||
469 | err: | 473 | err: |
470 | mc13xxx_unlock(priv->mc13xxx); | 474 | mc13xxx_unlock(priv->mc13xxx); |
471 | 475 | ||
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 2bb5de1f2421..bc27ab136378 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c | |||
@@ -174,7 +174,7 @@ static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev) | |||
174 | 174 | ||
175 | dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); | 175 | dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); |
176 | 176 | ||
177 | BUG_ON(val > mc13xxx_regulators[id].desc.n_voltages); | 177 | BUG_ON(val >= mc13xxx_regulators[id].desc.n_voltages); |
178 | 178 | ||
179 | return mc13xxx_regulators[id].voltages[val]; | 179 | return mc13xxx_regulators[id].voltages[val]; |
180 | } | 180 | } |
diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index a4d7f4540c18..1011873896dc 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c | |||
@@ -158,6 +158,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) | |||
158 | "failed to register regulator\n"); | 158 | "failed to register regulator\n"); |
159 | return ret; | 159 | return ret; |
160 | } | 160 | } |
161 | platform_set_drvdata(pdev, tps6105x); | ||
161 | 162 | ||
162 | return 0; | 163 | return 0; |
163 | } | 164 | } |
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 60a7ca5409e9..fbddc15e1811 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c | |||
@@ -466,7 +466,6 @@ static struct regulator_ops tps65023_ldo_ops = { | |||
466 | static int __devinit tps_65023_probe(struct i2c_client *client, | 466 | static int __devinit tps_65023_probe(struct i2c_client *client, |
467 | const struct i2c_device_id *id) | 467 | const struct i2c_device_id *id) |
468 | { | 468 | { |
469 | static int desc_id; | ||
470 | const struct tps_info *info = (void *)id->driver_data; | 469 | const struct tps_info *info = (void *)id->driver_data; |
471 | struct regulator_init_data *init_data; | 470 | struct regulator_init_data *init_data; |
472 | struct regulator_dev *rdev; | 471 | struct regulator_dev *rdev; |
@@ -499,7 +498,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client, | |||
499 | tps->info[i] = info; | 498 | tps->info[i] = info; |
500 | 499 | ||
501 | tps->desc[i].name = info->name; | 500 | tps->desc[i].name = info->name; |
502 | tps->desc[i].id = desc_id++; | 501 | tps->desc[i].id = i; |
503 | tps->desc[i].n_voltages = num_voltages[i]; | 502 | tps->desc[i].n_voltages = num_voltages[i]; |
504 | tps->desc[i].ops = (i > TPS65023_DCDC_3 ? | 503 | tps->desc[i].ops = (i > TPS65023_DCDC_3 ? |
505 | &tps65023_ldo_ops : &tps65023_dcdc_ops); | 504 | &tps65023_ldo_ops : &tps65023_dcdc_ops); |
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 064755290599..bfffabc21eda 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c | |||
@@ -553,7 +553,6 @@ static __devinit | |||
553 | int tps6507x_pmic_probe(struct platform_device *pdev) | 553 | int tps6507x_pmic_probe(struct platform_device *pdev) |
554 | { | 554 | { |
555 | struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); | 555 | struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); |
556 | static int desc_id; | ||
557 | struct tps_info *info = &tps6507x_pmic_regs[0]; | 556 | struct tps_info *info = &tps6507x_pmic_regs[0]; |
558 | struct regulator_init_data *init_data; | 557 | struct regulator_init_data *init_data; |
559 | struct regulator_dev *rdev; | 558 | struct regulator_dev *rdev; |
@@ -598,7 +597,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev) | |||
598 | } | 597 | } |
599 | 598 | ||
600 | tps->desc[i].name = info->name; | 599 | tps->desc[i].name = info->name; |
601 | tps->desc[i].id = desc_id++; | 600 | tps->desc[i].id = i; |
602 | tps->desc[i].n_voltages = num_voltages[i]; | 601 | tps->desc[i].n_voltages = num_voltages[i]; |
603 | tps->desc[i].ops = (i > TPS6507X_DCDC_3 ? | 602 | tps->desc[i].ops = (i > TPS6507X_DCDC_3 ? |
604 | &tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops); | 603 | &tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops); |
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c new file mode 100644 index 000000000000..55dd4e6650db --- /dev/null +++ b/drivers/regulator/tps65910-regulator.c | |||
@@ -0,0 +1,993 @@ | |||
1 | /* | ||
2 | * tps65910.c -- TI tps65910 | ||
3 | * | ||
4 | * Copyright 2010 Texas Instruments Inc. | ||
5 | * | ||
6 | * Author: Graeme Gregory <gg@slimlogic.co.uk> | ||
7 | * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/regulator/driver.h> | ||
22 | #include <linux/regulator/machine.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/gpio.h> | ||
26 | #include <linux/mfd/tps65910.h> | ||
27 | |||
28 | #define TPS65910_REG_VRTC 0 | ||
29 | #define TPS65910_REG_VIO 1 | ||
30 | #define TPS65910_REG_VDD1 2 | ||
31 | #define TPS65910_REG_VDD2 3 | ||
32 | #define TPS65910_REG_VDD3 4 | ||
33 | #define TPS65910_REG_VDIG1 5 | ||
34 | #define TPS65910_REG_VDIG2 6 | ||
35 | #define TPS65910_REG_VPLL 7 | ||
36 | #define TPS65910_REG_VDAC 8 | ||
37 | #define TPS65910_REG_VAUX1 9 | ||
38 | #define TPS65910_REG_VAUX2 10 | ||
39 | #define TPS65910_REG_VAUX33 11 | ||
40 | #define TPS65910_REG_VMMC 12 | ||
41 | |||
42 | #define TPS65911_REG_VDDCTRL 4 | ||
43 | #define TPS65911_REG_LDO1 5 | ||
44 | #define TPS65911_REG_LDO2 6 | ||
45 | #define TPS65911_REG_LDO3 7 | ||
46 | #define TPS65911_REG_LDO4 8 | ||
47 | #define TPS65911_REG_LDO5 9 | ||
48 | #define TPS65911_REG_LDO6 10 | ||
49 | #define TPS65911_REG_LDO7 11 | ||
50 | #define TPS65911_REG_LDO8 12 | ||
51 | |||
52 | #define TPS65910_NUM_REGULATOR 13 | ||
53 | #define TPS65910_SUPPLY_STATE_ENABLED 0x1 | ||
54 | |||
55 | /* supported VIO voltages in milivolts */ | ||
56 | static const u16 VIO_VSEL_table[] = { | ||
57 | 1500, 1800, 2500, 3300, | ||
58 | }; | ||
59 | |||
60 | /* VSEL tables for TPS65910 specific LDOs and dcdc's */ | ||
61 | |||
62 | /* supported VDD3 voltages in milivolts */ | ||
63 | static const u16 VDD3_VSEL_table[] = { | ||
64 | 5000, | ||
65 | }; | ||
66 | |||
67 | /* supported VDIG1 voltages in milivolts */ | ||
68 | static const u16 VDIG1_VSEL_table[] = { | ||
69 | 1200, 1500, 1800, 2700, | ||
70 | }; | ||
71 | |||
72 | /* supported VDIG2 voltages in milivolts */ | ||
73 | static const u16 VDIG2_VSEL_table[] = { | ||
74 | 1000, 1100, 1200, 1800, | ||
75 | }; | ||
76 | |||
77 | /* supported VPLL voltages in milivolts */ | ||
78 | static const u16 VPLL_VSEL_table[] = { | ||
79 | 1000, 1100, 1800, 2500, | ||
80 | }; | ||
81 | |||
82 | /* supported VDAC voltages in milivolts */ | ||
83 | static const u16 VDAC_VSEL_table[] = { | ||
84 | 1800, 2600, 2800, 2850, | ||
85 | }; | ||
86 | |||
87 | /* supported VAUX1 voltages in milivolts */ | ||
88 | static const u16 VAUX1_VSEL_table[] = { | ||
89 | 1800, 2500, 2800, 2850, | ||
90 | }; | ||
91 | |||
92 | /* supported VAUX2 voltages in milivolts */ | ||
93 | static const u16 VAUX2_VSEL_table[] = { | ||
94 | 1800, 2800, 2900, 3300, | ||
95 | }; | ||
96 | |||
97 | /* supported VAUX33 voltages in milivolts */ | ||
98 | static const u16 VAUX33_VSEL_table[] = { | ||
99 | 1800, 2000, 2800, 3300, | ||
100 | }; | ||
101 | |||
102 | /* supported VMMC voltages in milivolts */ | ||
103 | static const u16 VMMC_VSEL_table[] = { | ||
104 | 1800, 2800, 3000, 3300, | ||
105 | }; | ||
106 | |||
107 | struct tps_info { | ||
108 | const char *name; | ||
109 | unsigned min_uV; | ||
110 | unsigned max_uV; | ||
111 | u8 table_len; | ||
112 | const u16 *table; | ||
113 | }; | ||
114 | |||
115 | static struct tps_info tps65910_regs[] = { | ||
116 | { | ||
117 | .name = "VRTC", | ||
118 | }, | ||
119 | { | ||
120 | .name = "VIO", | ||
121 | .min_uV = 1500000, | ||
122 | .max_uV = 3300000, | ||
123 | .table_len = ARRAY_SIZE(VIO_VSEL_table), | ||
124 | .table = VIO_VSEL_table, | ||
125 | }, | ||
126 | { | ||
127 | .name = "VDD1", | ||
128 | .min_uV = 600000, | ||
129 | .max_uV = 4500000, | ||
130 | }, | ||
131 | { | ||
132 | .name = "VDD2", | ||
133 | .min_uV = 600000, | ||
134 | .max_uV = 4500000, | ||
135 | }, | ||
136 | { | ||
137 | .name = "VDD3", | ||
138 | .min_uV = 5000000, | ||
139 | .max_uV = 5000000, | ||
140 | .table_len = ARRAY_SIZE(VDD3_VSEL_table), | ||
141 | .table = VDD3_VSEL_table, | ||
142 | }, | ||
143 | { | ||
144 | .name = "VDIG1", | ||
145 | .min_uV = 1200000, | ||
146 | .max_uV = 2700000, | ||
147 | .table_len = ARRAY_SIZE(VDIG1_VSEL_table), | ||
148 | .table = VDIG1_VSEL_table, | ||
149 | }, | ||
150 | { | ||
151 | .name = "VDIG2", | ||
152 | .min_uV = 1000000, | ||
153 | .max_uV = 1800000, | ||
154 | .table_len = ARRAY_SIZE(VDIG2_VSEL_table), | ||
155 | .table = VDIG2_VSEL_table, | ||
156 | }, | ||
157 | { | ||
158 | .name = "VPLL", | ||
159 | .min_uV = 1000000, | ||
160 | .max_uV = 2500000, | ||
161 | .table_len = ARRAY_SIZE(VPLL_VSEL_table), | ||
162 | .table = VPLL_VSEL_table, | ||
163 | }, | ||
164 | { | ||
165 | .name = "VDAC", | ||
166 | .min_uV = 1800000, | ||
167 | .max_uV = 2850000, | ||
168 | .table_len = ARRAY_SIZE(VDAC_VSEL_table), | ||
169 | .table = VDAC_VSEL_table, | ||
170 | }, | ||
171 | { | ||
172 | .name = "VAUX1", | ||
173 | .min_uV = 1800000, | ||
174 | .max_uV = 2850000, | ||
175 | .table_len = ARRAY_SIZE(VAUX1_VSEL_table), | ||
176 | .table = VAUX1_VSEL_table, | ||
177 | }, | ||
178 | { | ||
179 | .name = "VAUX2", | ||
180 | .min_uV = 1800000, | ||
181 | .max_uV = 3300000, | ||
182 | .table_len = ARRAY_SIZE(VAUX2_VSEL_table), | ||
183 | .table = VAUX2_VSEL_table, | ||
184 | }, | ||
185 | { | ||
186 | .name = "VAUX33", | ||
187 | .min_uV = 1800000, | ||
188 | .max_uV = 3300000, | ||
189 | .table_len = ARRAY_SIZE(VAUX33_VSEL_table), | ||
190 | .table = VAUX33_VSEL_table, | ||
191 | }, | ||
192 | { | ||
193 | .name = "VMMC", | ||
194 | .min_uV = 1800000, | ||
195 | .max_uV = 3300000, | ||
196 | .table_len = ARRAY_SIZE(VMMC_VSEL_table), | ||
197 | .table = VMMC_VSEL_table, | ||
198 | }, | ||
199 | }; | ||
200 | |||
201 | static struct tps_info tps65911_regs[] = { | ||
202 | { | ||
203 | .name = "VIO", | ||
204 | .min_uV = 1500000, | ||
205 | .max_uV = 3300000, | ||
206 | .table_len = ARRAY_SIZE(VIO_VSEL_table), | ||
207 | .table = VIO_VSEL_table, | ||
208 | }, | ||
209 | { | ||
210 | .name = "VDD1", | ||
211 | .min_uV = 600000, | ||
212 | .max_uV = 4500000, | ||
213 | }, | ||
214 | { | ||
215 | .name = "VDD2", | ||
216 | .min_uV = 600000, | ||
217 | .max_uV = 4500000, | ||
218 | }, | ||
219 | { | ||
220 | .name = "VDDCTRL", | ||
221 | .min_uV = 600000, | ||
222 | .max_uV = 1400000, | ||
223 | }, | ||
224 | { | ||
225 | .name = "LDO1", | ||
226 | .min_uV = 1000000, | ||
227 | .max_uV = 3300000, | ||
228 | }, | ||
229 | { | ||
230 | .name = "LDO2", | ||
231 | .min_uV = 1000000, | ||
232 | .max_uV = 3300000, | ||
233 | }, | ||
234 | { | ||
235 | .name = "LDO3", | ||
236 | .min_uV = 1000000, | ||
237 | .max_uV = 3300000, | ||
238 | }, | ||
239 | { | ||
240 | .name = "LDO4", | ||
241 | .min_uV = 1000000, | ||
242 | .max_uV = 3300000, | ||
243 | }, | ||
244 | { | ||
245 | .name = "LDO5", | ||
246 | .min_uV = 1000000, | ||
247 | .max_uV = 3300000, | ||
248 | }, | ||
249 | { | ||
250 | .name = "LDO6", | ||
251 | .min_uV = 1000000, | ||
252 | .max_uV = 3300000, | ||
253 | }, | ||
254 | { | ||
255 | .name = "LDO7", | ||
256 | .min_uV = 1000000, | ||
257 | .max_uV = 3300000, | ||
258 | }, | ||
259 | { | ||
260 | .name = "LDO8", | ||
261 | .min_uV = 1000000, | ||
262 | .max_uV = 3300000, | ||
263 | }, | ||
264 | }; | ||
265 | |||
266 | struct tps65910_reg { | ||
267 | struct regulator_desc desc[TPS65910_NUM_REGULATOR]; | ||
268 | struct tps65910 *mfd; | ||
269 | struct regulator_dev *rdev[TPS65910_NUM_REGULATOR]; | ||
270 | struct tps_info *info[TPS65910_NUM_REGULATOR]; | ||
271 | struct mutex mutex; | ||
272 | int mode; | ||
273 | int (*get_ctrl_reg)(int); | ||
274 | }; | ||
275 | |||
276 | static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg) | ||
277 | { | ||
278 | u8 val; | ||
279 | int err; | ||
280 | |||
281 | err = pmic->mfd->read(pmic->mfd, reg, 1, &val); | ||
282 | if (err) | ||
283 | return err; | ||
284 | |||
285 | return val; | ||
286 | } | ||
287 | |||
288 | static inline int tps65910_write(struct tps65910_reg *pmic, u8 reg, u8 val) | ||
289 | { | ||
290 | return pmic->mfd->write(pmic->mfd, reg, 1, &val); | ||
291 | } | ||
292 | |||
293 | static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg, | ||
294 | u8 set_mask, u8 clear_mask) | ||
295 | { | ||
296 | int err, data; | ||
297 | |||
298 | mutex_lock(&pmic->mutex); | ||
299 | |||
300 | data = tps65910_read(pmic, reg); | ||
301 | if (data < 0) { | ||
302 | dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg); | ||
303 | err = data; | ||
304 | goto out; | ||
305 | } | ||
306 | |||
307 | data &= ~clear_mask; | ||
308 | data |= set_mask; | ||
309 | err = tps65910_write(pmic, reg, data); | ||
310 | if (err) | ||
311 | dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg); | ||
312 | |||
313 | out: | ||
314 | mutex_unlock(&pmic->mutex); | ||
315 | return err; | ||
316 | } | ||
317 | |||
318 | static int tps65910_reg_read(struct tps65910_reg *pmic, u8 reg) | ||
319 | { | ||
320 | int data; | ||
321 | |||
322 | mutex_lock(&pmic->mutex); | ||
323 | |||
324 | data = tps65910_read(pmic, reg); | ||
325 | if (data < 0) | ||
326 | dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg); | ||
327 | |||
328 | mutex_unlock(&pmic->mutex); | ||
329 | return data; | ||
330 | } | ||
331 | |||
332 | static int tps65910_reg_write(struct tps65910_reg *pmic, u8 reg, u8 val) | ||
333 | { | ||
334 | int err; | ||
335 | |||
336 | mutex_lock(&pmic->mutex); | ||
337 | |||
338 | err = tps65910_write(pmic, reg, val); | ||
339 | if (err < 0) | ||
340 | dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg); | ||
341 | |||
342 | mutex_unlock(&pmic->mutex); | ||
343 | return err; | ||
344 | } | ||
345 | |||
346 | static int tps65910_get_ctrl_register(int id) | ||
347 | { | ||
348 | switch (id) { | ||
349 | case TPS65910_REG_VRTC: | ||
350 | return TPS65910_VRTC; | ||
351 | case TPS65910_REG_VIO: | ||
352 | return TPS65910_VIO; | ||
353 | case TPS65910_REG_VDD1: | ||
354 | return TPS65910_VDD1; | ||
355 | case TPS65910_REG_VDD2: | ||
356 | return TPS65910_VDD2; | ||
357 | case TPS65910_REG_VDD3: | ||
358 | return TPS65910_VDD3; | ||
359 | case TPS65910_REG_VDIG1: | ||
360 | return TPS65910_VDIG1; | ||
361 | case TPS65910_REG_VDIG2: | ||
362 | return TPS65910_VDIG2; | ||
363 | case TPS65910_REG_VPLL: | ||
364 | return TPS65910_VPLL; | ||
365 | case TPS65910_REG_VDAC: | ||
366 | return TPS65910_VDAC; | ||
367 | case TPS65910_REG_VAUX1: | ||
368 | return TPS65910_VAUX1; | ||
369 | case TPS65910_REG_VAUX2: | ||
370 | return TPS65910_VAUX2; | ||
371 | case TPS65910_REG_VAUX33: | ||
372 | return TPS65910_VAUX33; | ||
373 | case TPS65910_REG_VMMC: | ||
374 | return TPS65910_VMMC; | ||
375 | default: | ||
376 | return -EINVAL; | ||
377 | } | ||
378 | } | ||
379 | |||
380 | static int tps65911_get_ctrl_register(int id) | ||
381 | { | ||
382 | switch (id) { | ||
383 | case TPS65910_REG_VRTC: | ||
384 | return TPS65910_VRTC; | ||
385 | case TPS65910_REG_VIO: | ||
386 | return TPS65910_VIO; | ||
387 | case TPS65910_REG_VDD1: | ||
388 | return TPS65910_VDD1; | ||
389 | case TPS65910_REG_VDD2: | ||
390 | return TPS65910_VDD2; | ||
391 | case TPS65911_REG_VDDCTRL: | ||
392 | return TPS65911_VDDCTRL; | ||
393 | case TPS65911_REG_LDO1: | ||
394 | return TPS65911_LDO1; | ||
395 | case TPS65911_REG_LDO2: | ||
396 | return TPS65911_LDO2; | ||
397 | case TPS65911_REG_LDO3: | ||
398 | return TPS65911_LDO3; | ||
399 | case TPS65911_REG_LDO4: | ||
400 | return TPS65911_LDO4; | ||
401 | case TPS65911_REG_LDO5: | ||
402 | return TPS65911_LDO5; | ||
403 | case TPS65911_REG_LDO6: | ||
404 | return TPS65911_LDO6; | ||
405 | case TPS65911_REG_LDO7: | ||
406 | return TPS65911_LDO7; | ||
407 | case TPS65911_REG_LDO8: | ||
408 | return TPS65911_LDO8; | ||
409 | default: | ||
410 | return -EINVAL; | ||
411 | } | ||
412 | } | ||
413 | |||
414 | static int tps65910_is_enabled(struct regulator_dev *dev) | ||
415 | { | ||
416 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
417 | int reg, value, id = rdev_get_id(dev); | ||
418 | |||
419 | reg = pmic->get_ctrl_reg(id); | ||
420 | if (reg < 0) | ||
421 | return reg; | ||
422 | |||
423 | value = tps65910_reg_read(pmic, reg); | ||
424 | if (value < 0) | ||
425 | return value; | ||
426 | |||
427 | return value & TPS65910_SUPPLY_STATE_ENABLED; | ||
428 | } | ||
429 | |||
430 | static int tps65910_enable(struct regulator_dev *dev) | ||
431 | { | ||
432 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
433 | struct tps65910 *mfd = pmic->mfd; | ||
434 | int reg, id = rdev_get_id(dev); | ||
435 | |||
436 | reg = pmic->get_ctrl_reg(id); | ||
437 | if (reg < 0) | ||
438 | return reg; | ||
439 | |||
440 | return tps65910_set_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); | ||
441 | } | ||
442 | |||
443 | static int tps65910_disable(struct regulator_dev *dev) | ||
444 | { | ||
445 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
446 | struct tps65910 *mfd = pmic->mfd; | ||
447 | int reg, id = rdev_get_id(dev); | ||
448 | |||
449 | reg = pmic->get_ctrl_reg(id); | ||
450 | if (reg < 0) | ||
451 | return reg; | ||
452 | |||
453 | return tps65910_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED); | ||
454 | } | ||
455 | |||
456 | |||
457 | static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) | ||
458 | { | ||
459 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
460 | struct tps65910 *mfd = pmic->mfd; | ||
461 | int reg, value, id = rdev_get_id(dev); | ||
462 | |||
463 | reg = pmic->get_ctrl_reg(id); | ||
464 | if (reg < 0) | ||
465 | return reg; | ||
466 | |||
467 | switch (mode) { | ||
468 | case REGULATOR_MODE_NORMAL: | ||
469 | return tps65910_modify_bits(pmic, reg, LDO_ST_ON_BIT, | ||
470 | LDO_ST_MODE_BIT); | ||
471 | case REGULATOR_MODE_IDLE: | ||
472 | value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT; | ||
473 | return tps65910_set_bits(mfd, reg, value); | ||
474 | case REGULATOR_MODE_STANDBY: | ||
475 | return tps65910_clear_bits(mfd, reg, LDO_ST_ON_BIT); | ||
476 | } | ||
477 | |||
478 | return -EINVAL; | ||
479 | } | ||
480 | |||
481 | static unsigned int tps65910_get_mode(struct regulator_dev *dev) | ||
482 | { | ||
483 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
484 | int reg, value, id = rdev_get_id(dev); | ||
485 | |||
486 | reg = pmic->get_ctrl_reg(id); | ||
487 | if (reg < 0) | ||
488 | return reg; | ||
489 | |||
490 | value = tps65910_reg_read(pmic, reg); | ||
491 | if (value < 0) | ||
492 | return value; | ||
493 | |||
494 | if (value & LDO_ST_ON_BIT) | ||
495 | return REGULATOR_MODE_STANDBY; | ||
496 | else if (value & LDO_ST_MODE_BIT) | ||
497 | return REGULATOR_MODE_IDLE; | ||
498 | else | ||
499 | return REGULATOR_MODE_NORMAL; | ||
500 | } | ||
501 | |||
502 | static int tps65910_get_voltage_dcdc(struct regulator_dev *dev) | ||
503 | { | ||
504 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
505 | int id = rdev_get_id(dev), voltage = 0; | ||
506 | int opvsel = 0, srvsel = 0, vselmax = 0, mult = 0, sr = 0; | ||
507 | |||
508 | switch (id) { | ||
509 | case TPS65910_REG_VDD1: | ||
510 | opvsel = tps65910_reg_read(pmic, TPS65910_VDD1_OP); | ||
511 | mult = tps65910_reg_read(pmic, TPS65910_VDD1); | ||
512 | mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT; | ||
513 | srvsel = tps65910_reg_read(pmic, TPS65910_VDD1_SR); | ||
514 | sr = opvsel & VDD1_OP_CMD_MASK; | ||
515 | opvsel &= VDD1_OP_SEL_MASK; | ||
516 | srvsel &= VDD1_SR_SEL_MASK; | ||
517 | vselmax = 75; | ||
518 | break; | ||
519 | case TPS65910_REG_VDD2: | ||
520 | opvsel = tps65910_reg_read(pmic, TPS65910_VDD2_OP); | ||
521 | mult = tps65910_reg_read(pmic, TPS65910_VDD2); | ||
522 | mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT; | ||
523 | srvsel = tps65910_reg_read(pmic, TPS65910_VDD2_SR); | ||
524 | sr = opvsel & VDD2_OP_CMD_MASK; | ||
525 | opvsel &= VDD2_OP_SEL_MASK; | ||
526 | srvsel &= VDD2_SR_SEL_MASK; | ||
527 | vselmax = 75; | ||
528 | break; | ||
529 | case TPS65911_REG_VDDCTRL: | ||
530 | opvsel = tps65910_reg_read(pmic, TPS65911_VDDCTRL_OP); | ||
531 | srvsel = tps65910_reg_read(pmic, TPS65911_VDDCTRL_SR); | ||
532 | sr = opvsel & VDDCTRL_OP_CMD_MASK; | ||
533 | opvsel &= VDDCTRL_OP_SEL_MASK; | ||
534 | srvsel &= VDDCTRL_SR_SEL_MASK; | ||
535 | vselmax = 64; | ||
536 | break; | ||
537 | } | ||
538 | |||
539 | /* multiplier 0 == 1 but 2,3 normal */ | ||
540 | if (!mult) | ||
541 | mult=1; | ||
542 | |||
543 | if (sr) { | ||
544 | /* normalise to valid range */ | ||
545 | if (srvsel < 3) | ||
546 | srvsel = 3; | ||
547 | if (srvsel > vselmax) | ||
548 | srvsel = vselmax; | ||
549 | srvsel -= 3; | ||
550 | |||
551 | voltage = (srvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100; | ||
552 | } else { | ||
553 | |||
554 | /* normalise to valid range*/ | ||
555 | if (opvsel < 3) | ||
556 | opvsel = 3; | ||
557 | if (opvsel > vselmax) | ||
558 | opvsel = vselmax; | ||
559 | opvsel -= 3; | ||
560 | |||
561 | voltage = (opvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100; | ||
562 | } | ||
563 | |||
564 | voltage *= mult; | ||
565 | |||
566 | return voltage; | ||
567 | } | ||
568 | |||
569 | static int tps65910_get_voltage(struct regulator_dev *dev) | ||
570 | { | ||
571 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
572 | int reg, value, id = rdev_get_id(dev), voltage = 0; | ||
573 | |||
574 | reg = pmic->get_ctrl_reg(id); | ||
575 | if (reg < 0) | ||
576 | return reg; | ||
577 | |||
578 | value = tps65910_reg_read(pmic, reg); | ||
579 | if (value < 0) | ||
580 | return value; | ||
581 | |||
582 | switch (id) { | ||
583 | case TPS65910_REG_VIO: | ||
584 | case TPS65910_REG_VDIG1: | ||
585 | case TPS65910_REG_VDIG2: | ||
586 | case TPS65910_REG_VPLL: | ||
587 | case TPS65910_REG_VDAC: | ||
588 | case TPS65910_REG_VAUX1: | ||
589 | case TPS65910_REG_VAUX2: | ||
590 | case TPS65910_REG_VAUX33: | ||
591 | case TPS65910_REG_VMMC: | ||
592 | value &= LDO_SEL_MASK; | ||
593 | value >>= LDO_SEL_SHIFT; | ||
594 | break; | ||
595 | default: | ||
596 | return -EINVAL; | ||
597 | } | ||
598 | |||
599 | voltage = pmic->info[id]->table[value] * 1000; | ||
600 | |||
601 | return voltage; | ||
602 | } | ||
603 | |||
604 | static int tps65910_get_voltage_vdd3(struct regulator_dev *dev) | ||
605 | { | ||
606 | return 5 * 1000 * 1000; | ||
607 | } | ||
608 | |||
609 | static int tps65911_get_voltage(struct regulator_dev *dev) | ||
610 | { | ||
611 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
612 | int step_mv, id = rdev_get_id(dev); | ||
613 | u8 value, reg; | ||
614 | |||
615 | reg = pmic->get_ctrl_reg(id); | ||
616 | |||
617 | value = tps65910_reg_read(pmic, reg); | ||
618 | |||
619 | switch (id) { | ||
620 | case TPS65911_REG_LDO1: | ||
621 | case TPS65911_REG_LDO2: | ||
622 | case TPS65911_REG_LDO4: | ||
623 | value &= LDO1_SEL_MASK; | ||
624 | value >>= LDO_SEL_SHIFT; | ||
625 | /* The first 5 values of the selector correspond to 1V */ | ||
626 | if (value < 5) | ||
627 | value = 0; | ||
628 | else | ||
629 | value -= 4; | ||
630 | |||
631 | step_mv = 50; | ||
632 | break; | ||
633 | case TPS65911_REG_LDO3: | ||
634 | case TPS65911_REG_LDO5: | ||
635 | case TPS65911_REG_LDO6: | ||
636 | case TPS65911_REG_LDO7: | ||
637 | case TPS65911_REG_LDO8: | ||
638 | value &= LDO3_SEL_MASK; | ||
639 | value >>= LDO_SEL_SHIFT; | ||
640 | /* The first 3 values of the selector correspond to 1V */ | ||
641 | if (value < 3) | ||
642 | value = 0; | ||
643 | else | ||
644 | value -= 2; | ||
645 | |||
646 | step_mv = 100; | ||
647 | break; | ||
648 | case TPS65910_REG_VIO: | ||
649 | return pmic->info[id]->table[value] * 1000; | ||
650 | break; | ||
651 | default: | ||
652 | return -EINVAL; | ||
653 | } | ||
654 | |||
655 | return (LDO_MIN_VOLT + value * step_mv) * 1000; | ||
656 | } | ||
657 | |||
658 | static int tps65910_set_voltage_dcdc(struct regulator_dev *dev, | ||
659 | unsigned selector) | ||
660 | { | ||
661 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
662 | int id = rdev_get_id(dev), vsel; | ||
663 | int dcdc_mult = 0; | ||
664 | |||
665 | switch (id) { | ||
666 | case TPS65910_REG_VDD1: | ||
667 | dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1; | ||
668 | if (dcdc_mult == 1) | ||
669 | dcdc_mult--; | ||
670 | vsel = (selector % VDD1_2_NUM_VOLTS) + 3; | ||
671 | |||
672 | tps65910_modify_bits(pmic, TPS65910_VDD1, | ||
673 | (dcdc_mult << VDD1_VGAIN_SEL_SHIFT), | ||
674 | VDD1_VGAIN_SEL_MASK); | ||
675 | tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel); | ||
676 | break; | ||
677 | case TPS65910_REG_VDD2: | ||
678 | dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1; | ||
679 | if (dcdc_mult == 1) | ||
680 | dcdc_mult--; | ||
681 | vsel = (selector % VDD1_2_NUM_VOLTS) + 3; | ||
682 | |||
683 | tps65910_modify_bits(pmic, TPS65910_VDD2, | ||
684 | (dcdc_mult << VDD2_VGAIN_SEL_SHIFT), | ||
685 | VDD1_VGAIN_SEL_MASK); | ||
686 | tps65910_reg_write(pmic, TPS65910_VDD2_OP, vsel); | ||
687 | break; | ||
688 | case TPS65911_REG_VDDCTRL: | ||
689 | vsel = selector; | ||
690 | tps65910_reg_write(pmic, TPS65911_VDDCTRL_OP, vsel); | ||
691 | } | ||
692 | |||
693 | return 0; | ||
694 | } | ||
695 | |||
696 | static int tps65910_set_voltage(struct regulator_dev *dev, unsigned selector) | ||
697 | { | ||
698 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
699 | int reg, id = rdev_get_id(dev); | ||
700 | |||
701 | reg = pmic->get_ctrl_reg(id); | ||
702 | if (reg < 0) | ||
703 | return reg; | ||
704 | |||
705 | switch (id) { | ||
706 | case TPS65910_REG_VIO: | ||
707 | case TPS65910_REG_VDIG1: | ||
708 | case TPS65910_REG_VDIG2: | ||
709 | case TPS65910_REG_VPLL: | ||
710 | case TPS65910_REG_VDAC: | ||
711 | case TPS65910_REG_VAUX1: | ||
712 | case TPS65910_REG_VAUX2: | ||
713 | case TPS65910_REG_VAUX33: | ||
714 | case TPS65910_REG_VMMC: | ||
715 | return tps65910_modify_bits(pmic, reg, | ||
716 | (selector << LDO_SEL_SHIFT), LDO_SEL_MASK); | ||
717 | } | ||
718 | |||
719 | return -EINVAL; | ||
720 | } | ||
721 | |||
722 | static int tps65911_set_voltage(struct regulator_dev *dev, unsigned selector) | ||
723 | { | ||
724 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
725 | int reg, id = rdev_get_id(dev); | ||
726 | |||
727 | reg = pmic->get_ctrl_reg(id); | ||
728 | if (reg < 0) | ||
729 | return reg; | ||
730 | |||
731 | switch (id) { | ||
732 | case TPS65911_REG_LDO1: | ||
733 | case TPS65911_REG_LDO2: | ||
734 | case TPS65911_REG_LDO4: | ||
735 | return tps65910_modify_bits(pmic, reg, | ||
736 | (selector << LDO_SEL_SHIFT), LDO1_SEL_MASK); | ||
737 | case TPS65911_REG_LDO3: | ||
738 | case TPS65911_REG_LDO5: | ||
739 | case TPS65911_REG_LDO6: | ||
740 | case TPS65911_REG_LDO7: | ||
741 | case TPS65911_REG_LDO8: | ||
742 | case TPS65910_REG_VIO: | ||
743 | return tps65910_modify_bits(pmic, reg, | ||
744 | (selector << LDO_SEL_SHIFT), LDO3_SEL_MASK); | ||
745 | } | ||
746 | |||
747 | return -EINVAL; | ||
748 | } | ||
749 | |||
750 | |||
751 | static int tps65910_list_voltage_dcdc(struct regulator_dev *dev, | ||
752 | unsigned selector) | ||
753 | { | ||
754 | int volt, mult = 1, id = rdev_get_id(dev); | ||
755 | |||
756 | switch (id) { | ||
757 | case TPS65910_REG_VDD1: | ||
758 | case TPS65910_REG_VDD2: | ||
759 | mult = (selector / VDD1_2_NUM_VOLTS) + 1; | ||
760 | volt = VDD1_2_MIN_VOLT + | ||
761 | (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET; | ||
762 | case TPS65911_REG_VDDCTRL: | ||
763 | volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET); | ||
764 | } | ||
765 | |||
766 | return volt * 100 * mult; | ||
767 | } | ||
768 | |||
769 | static int tps65910_list_voltage(struct regulator_dev *dev, | ||
770 | unsigned selector) | ||
771 | { | ||
772 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
773 | int id = rdev_get_id(dev), voltage; | ||
774 | |||
775 | if (id < TPS65910_REG_VIO || id > TPS65910_REG_VMMC) | ||
776 | return -EINVAL; | ||
777 | |||
778 | if (selector >= pmic->info[id]->table_len) | ||
779 | return -EINVAL; | ||
780 | else | ||
781 | voltage = pmic->info[id]->table[selector] * 1000; | ||
782 | |||
783 | return voltage; | ||
784 | } | ||
785 | |||
786 | static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector) | ||
787 | { | ||
788 | struct tps65910_reg *pmic = rdev_get_drvdata(dev); | ||
789 | int step_mv = 0, id = rdev_get_id(dev); | ||
790 | |||
791 | switch(id) { | ||
792 | case TPS65911_REG_LDO1: | ||
793 | case TPS65911_REG_LDO2: | ||
794 | case TPS65911_REG_LDO4: | ||
795 | /* The first 5 values of the selector correspond to 1V */ | ||
796 | if (selector < 5) | ||
797 | selector = 0; | ||
798 | else | ||
799 | selector -= 4; | ||
800 | |||
801 | step_mv = 50; | ||
802 | break; | ||
803 | case TPS65911_REG_LDO3: | ||
804 | case TPS65911_REG_LDO5: | ||
805 | case TPS65911_REG_LDO6: | ||
806 | case TPS65911_REG_LDO7: | ||
807 | case TPS65911_REG_LDO8: | ||
808 | /* The first 3 values of the selector correspond to 1V */ | ||
809 | if (selector < 3) | ||
810 | selector = 0; | ||
811 | else | ||
812 | selector -= 2; | ||
813 | |||
814 | step_mv = 100; | ||
815 | break; | ||
816 | case TPS65910_REG_VIO: | ||
817 | return pmic->info[id]->table[selector] * 1000; | ||
818 | default: | ||
819 | return -EINVAL; | ||
820 | } | ||
821 | |||
822 | return (LDO_MIN_VOLT + selector * step_mv) * 1000; | ||
823 | } | ||
824 | |||
825 | /* Regulator ops (except VRTC) */ | ||
826 | static struct regulator_ops tps65910_ops_dcdc = { | ||
827 | .is_enabled = tps65910_is_enabled, | ||
828 | .enable = tps65910_enable, | ||
829 | .disable = tps65910_disable, | ||
830 | .set_mode = tps65910_set_mode, | ||
831 | .get_mode = tps65910_get_mode, | ||
832 | .get_voltage = tps65910_get_voltage_dcdc, | ||
833 | .set_voltage_sel = tps65910_set_voltage_dcdc, | ||
834 | .list_voltage = tps65910_list_voltage_dcdc, | ||
835 | }; | ||
836 | |||
837 | static struct regulator_ops tps65910_ops_vdd3 = { | ||
838 | .is_enabled = tps65910_is_enabled, | ||
839 | .enable = tps65910_enable, | ||
840 | .disable = tps65910_disable, | ||
841 | .set_mode = tps65910_set_mode, | ||
842 | .get_mode = tps65910_get_mode, | ||
843 | .get_voltage = tps65910_get_voltage_vdd3, | ||
844 | .list_voltage = tps65910_list_voltage, | ||
845 | }; | ||
846 | |||
847 | static struct regulator_ops tps65910_ops = { | ||
848 | .is_enabled = tps65910_is_enabled, | ||
849 | .enable = tps65910_enable, | ||
850 | .disable = tps65910_disable, | ||
851 | .set_mode = tps65910_set_mode, | ||
852 | .get_mode = tps65910_get_mode, | ||
853 | .get_voltage = tps65910_get_voltage, | ||
854 | .set_voltage_sel = tps65910_set_voltage, | ||
855 | .list_voltage = tps65910_list_voltage, | ||
856 | }; | ||
857 | |||
858 | static struct regulator_ops tps65911_ops = { | ||
859 | .is_enabled = tps65910_is_enabled, | ||
860 | .enable = tps65910_enable, | ||
861 | .disable = tps65910_disable, | ||
862 | .set_mode = tps65910_set_mode, | ||
863 | .get_mode = tps65910_get_mode, | ||
864 | .get_voltage = tps65911_get_voltage, | ||
865 | .set_voltage_sel = tps65911_set_voltage, | ||
866 | .list_voltage = tps65911_list_voltage, | ||
867 | }; | ||
868 | |||
869 | static __devinit int tps65910_probe(struct platform_device *pdev) | ||
870 | { | ||
871 | struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); | ||
872 | struct tps_info *info; | ||
873 | struct regulator_init_data *reg_data; | ||
874 | struct regulator_dev *rdev; | ||
875 | struct tps65910_reg *pmic; | ||
876 | struct tps65910_board *pmic_plat_data; | ||
877 | int i, err; | ||
878 | |||
879 | pmic_plat_data = dev_get_platdata(tps65910->dev); | ||
880 | if (!pmic_plat_data) | ||
881 | return -EINVAL; | ||
882 | |||
883 | reg_data = pmic_plat_data->tps65910_pmic_init_data; | ||
884 | |||
885 | pmic = kzalloc(sizeof(*pmic), GFP_KERNEL); | ||
886 | if (!pmic) | ||
887 | return -ENOMEM; | ||
888 | |||
889 | mutex_init(&pmic->mutex); | ||
890 | pmic->mfd = tps65910; | ||
891 | platform_set_drvdata(pdev, pmic); | ||
892 | |||
893 | /* Give control of all register to control port */ | ||
894 | tps65910_set_bits(pmic->mfd, TPS65910_DEVCTRL, | ||
895 | DEVCTRL_SR_CTL_I2C_SEL_MASK); | ||
896 | |||
897 | switch(tps65910_chip_id(tps65910)) { | ||
898 | case TPS65910: | ||
899 | pmic->get_ctrl_reg = &tps65910_get_ctrl_register; | ||
900 | info = tps65910_regs; | ||
901 | case TPS65911: | ||
902 | pmic->get_ctrl_reg = &tps65911_get_ctrl_register; | ||
903 | info = tps65911_regs; | ||
904 | default: | ||
905 | pr_err("Invalid tps chip version\n"); | ||
906 | return -ENODEV; | ||
907 | } | ||
908 | |||
909 | for (i = 0; i < TPS65910_NUM_REGULATOR; i++, info++, reg_data++) { | ||
910 | /* Register the regulators */ | ||
911 | pmic->info[i] = info; | ||
912 | |||
913 | pmic->desc[i].name = info->name; | ||
914 | pmic->desc[i].id = i; | ||
915 | pmic->desc[i].n_voltages = info->table_len; | ||
916 | |||
917 | if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) { | ||
918 | pmic->desc[i].ops = &tps65910_ops_dcdc; | ||
919 | } else if (i == TPS65910_REG_VDD3) { | ||
920 | if (tps65910_chip_id(tps65910) == TPS65910) | ||
921 | pmic->desc[i].ops = &tps65910_ops_vdd3; | ||
922 | else | ||
923 | pmic->desc[i].ops = &tps65910_ops_dcdc; | ||
924 | } else { | ||
925 | if (tps65910_chip_id(tps65910) == TPS65910) | ||
926 | pmic->desc[i].ops = &tps65910_ops; | ||
927 | else | ||
928 | pmic->desc[i].ops = &tps65911_ops; | ||
929 | } | ||
930 | |||
931 | pmic->desc[i].type = REGULATOR_VOLTAGE; | ||
932 | pmic->desc[i].owner = THIS_MODULE; | ||
933 | |||
934 | rdev = regulator_register(&pmic->desc[i], | ||
935 | tps65910->dev, reg_data, pmic); | ||
936 | if (IS_ERR(rdev)) { | ||
937 | dev_err(tps65910->dev, | ||
938 | "failed to register %s regulator\n", | ||
939 | pdev->name); | ||
940 | err = PTR_ERR(rdev); | ||
941 | goto err; | ||
942 | } | ||
943 | |||
944 | /* Save regulator for cleanup */ | ||
945 | pmic->rdev[i] = rdev; | ||
946 | } | ||
947 | return 0; | ||
948 | |||
949 | err: | ||
950 | while (--i >= 0) | ||
951 | regulator_unregister(pmic->rdev[i]); | ||
952 | |||
953 | kfree(pmic); | ||
954 | return err; | ||
955 | } | ||
956 | |||
957 | static int __devexit tps65910_remove(struct platform_device *pdev) | ||
958 | { | ||
959 | struct tps65910_reg *tps65910_reg = platform_get_drvdata(pdev); | ||
960 | int i; | ||
961 | |||
962 | for (i = 0; i < TPS65910_NUM_REGULATOR; i++) | ||
963 | regulator_unregister(tps65910_reg->rdev[i]); | ||
964 | |||
965 | kfree(tps65910_reg); | ||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | static struct platform_driver tps65910_driver = { | ||
970 | .driver = { | ||
971 | .name = "tps65910-pmic", | ||
972 | .owner = THIS_MODULE, | ||
973 | }, | ||
974 | .probe = tps65910_probe, | ||
975 | .remove = __devexit_p(tps65910_remove), | ||
976 | }; | ||
977 | |||
978 | static int __init tps65910_init(void) | ||
979 | { | ||
980 | return platform_driver_register(&tps65910_driver); | ||
981 | } | ||
982 | subsys_initcall(tps65910_init); | ||
983 | |||
984 | static void __exit tps65910_cleanup(void) | ||
985 | { | ||
986 | platform_driver_unregister(&tps65910_driver); | ||
987 | } | ||
988 | module_exit(tps65910_cleanup); | ||
989 | |||
990 | MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); | ||
991 | MODULE_DESCRIPTION("TPS6507x voltage regulator driver"); | ||
992 | MODULE_LICENSE("GPL v2"); | ||
993 | MODULE_ALIAS("platform:tps65910-pmic"); | ||
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 6a292852a358..87fe0f75a56e 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c | |||
@@ -51,8 +51,13 @@ struct twlreg_info { | |||
51 | u16 min_mV; | 51 | u16 min_mV; |
52 | u16 max_mV; | 52 | u16 max_mV; |
53 | 53 | ||
54 | u8 flags; | ||
55 | |||
54 | /* used by regulator core */ | 56 | /* used by regulator core */ |
55 | struct regulator_desc desc; | 57 | struct regulator_desc desc; |
58 | |||
59 | /* chip specific features */ | ||
60 | unsigned long features; | ||
56 | }; | 61 | }; |
57 | 62 | ||
58 | 63 | ||
@@ -70,12 +75,35 @@ struct twlreg_info { | |||
70 | #define VREG_TRANS 1 | 75 | #define VREG_TRANS 1 |
71 | #define VREG_STATE 2 | 76 | #define VREG_STATE 2 |
72 | #define VREG_VOLTAGE 3 | 77 | #define VREG_VOLTAGE 3 |
78 | #define VREG_VOLTAGE_SMPS 4 | ||
73 | /* TWL6030 Misc register offsets */ | 79 | /* TWL6030 Misc register offsets */ |
74 | #define VREG_BC_ALL 1 | 80 | #define VREG_BC_ALL 1 |
75 | #define VREG_BC_REF 2 | 81 | #define VREG_BC_REF 2 |
76 | #define VREG_BC_PROC 3 | 82 | #define VREG_BC_PROC 3 |
77 | #define VREG_BC_CLK_RST 4 | 83 | #define VREG_BC_CLK_RST 4 |
78 | 84 | ||
85 | /* TWL6030 LDO register values for CFG_STATE */ | ||
86 | #define TWL6030_CFG_STATE_OFF 0x00 | ||
87 | #define TWL6030_CFG_STATE_ON 0x01 | ||
88 | #define TWL6030_CFG_STATE_OFF2 0x02 | ||
89 | #define TWL6030_CFG_STATE_SLEEP 0x03 | ||
90 | #define TWL6030_CFG_STATE_GRP_SHIFT 5 | ||
91 | #define TWL6030_CFG_STATE_APP_SHIFT 2 | ||
92 | #define TWL6030_CFG_STATE_APP_MASK (0x03 << TWL6030_CFG_STATE_APP_SHIFT) | ||
93 | #define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\ | ||
94 | TWL6030_CFG_STATE_APP_SHIFT) | ||
95 | |||
96 | /* Flags for SMPS Voltage reading */ | ||
97 | #define SMPS_OFFSET_EN BIT(0) | ||
98 | #define SMPS_EXTENDED_EN BIT(1) | ||
99 | |||
100 | /* twl6025 SMPS EPROM values */ | ||
101 | #define TWL6030_SMPS_OFFSET 0xB0 | ||
102 | #define TWL6030_SMPS_MULT 0xB3 | ||
103 | #define SMPS_MULTOFFSET_SMPS4 BIT(0) | ||
104 | #define SMPS_MULTOFFSET_VIO BIT(1) | ||
105 | #define SMPS_MULTOFFSET_SMPS3 BIT(6) | ||
106 | |||
79 | static inline int | 107 | static inline int |
80 | twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset) | 108 | twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset) |
81 | { | 109 | { |
@@ -118,21 +146,38 @@ static int twlreg_grp(struct regulator_dev *rdev) | |||
118 | #define P2_GRP_6030 BIT(1) /* "peripherals" */ | 146 | #define P2_GRP_6030 BIT(1) /* "peripherals" */ |
119 | #define P1_GRP_6030 BIT(0) /* CPU/Linux */ | 147 | #define P1_GRP_6030 BIT(0) /* CPU/Linux */ |
120 | 148 | ||
121 | static int twlreg_is_enabled(struct regulator_dev *rdev) | 149 | static int twl4030reg_is_enabled(struct regulator_dev *rdev) |
122 | { | 150 | { |
123 | int state = twlreg_grp(rdev); | 151 | int state = twlreg_grp(rdev); |
124 | 152 | ||
125 | if (state < 0) | 153 | if (state < 0) |
126 | return state; | 154 | return state; |
127 | 155 | ||
128 | if (twl_class_is_4030()) | 156 | return state & P1_GRP_4030; |
129 | state &= P1_GRP_4030; | 157 | } |
158 | |||
159 | static int twl6030reg_is_enabled(struct regulator_dev *rdev) | ||
160 | { | ||
161 | struct twlreg_info *info = rdev_get_drvdata(rdev); | ||
162 | int grp = 0, val; | ||
163 | |||
164 | if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) | ||
165 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); | ||
166 | if (grp < 0) | ||
167 | return grp; | ||
168 | |||
169 | if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) | ||
170 | grp &= P1_GRP_6030; | ||
130 | else | 171 | else |
131 | state &= P1_GRP_6030; | 172 | grp = 1; |
132 | return state; | 173 | |
174 | val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE); | ||
175 | val = TWL6030_CFG_STATE_APP(val); | ||
176 | |||
177 | return grp && (val == TWL6030_CFG_STATE_ON); | ||
133 | } | 178 | } |
134 | 179 | ||
135 | static int twlreg_enable(struct regulator_dev *rdev) | 180 | static int twl4030reg_enable(struct regulator_dev *rdev) |
136 | { | 181 | { |
137 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 182 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
138 | int grp; | 183 | int grp; |
@@ -142,10 +187,7 @@ static int twlreg_enable(struct regulator_dev *rdev) | |||
142 | if (grp < 0) | 187 | if (grp < 0) |
143 | return grp; | 188 | return grp; |
144 | 189 | ||
145 | if (twl_class_is_4030()) | 190 | grp |= P1_GRP_4030; |
146 | grp |= P1_GRP_4030; | ||
147 | else | ||
148 | grp |= P1_GRP_6030; | ||
149 | 191 | ||
150 | ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); | 192 | ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); |
151 | 193 | ||
@@ -154,29 +196,63 @@ static int twlreg_enable(struct regulator_dev *rdev) | |||
154 | return ret; | 196 | return ret; |
155 | } | 197 | } |
156 | 198 | ||
157 | static int twlreg_disable(struct regulator_dev *rdev) | 199 | static int twl6030reg_enable(struct regulator_dev *rdev) |
200 | { | ||
201 | struct twlreg_info *info = rdev_get_drvdata(rdev); | ||
202 | int grp = 0; | ||
203 | int ret; | ||
204 | |||
205 | if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) | ||
206 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); | ||
207 | if (grp < 0) | ||
208 | return grp; | ||
209 | |||
210 | ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, | ||
211 | grp << TWL6030_CFG_STATE_GRP_SHIFT | | ||
212 | TWL6030_CFG_STATE_ON); | ||
213 | |||
214 | udelay(info->delay); | ||
215 | |||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | static int twl4030reg_disable(struct regulator_dev *rdev) | ||
158 | { | 220 | { |
159 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 221 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
160 | int grp; | 222 | int grp; |
223 | int ret; | ||
161 | 224 | ||
162 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); | 225 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); |
163 | if (grp < 0) | 226 | if (grp < 0) |
164 | return grp; | 227 | return grp; |
165 | 228 | ||
166 | if (twl_class_is_4030()) | 229 | grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030); |
167 | grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030); | ||
168 | else | ||
169 | grp &= ~(P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030); | ||
170 | 230 | ||
171 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); | 231 | ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); |
232 | |||
233 | return ret; | ||
172 | } | 234 | } |
173 | 235 | ||
174 | static int twlreg_get_status(struct regulator_dev *rdev) | 236 | static int twl6030reg_disable(struct regulator_dev *rdev) |
175 | { | 237 | { |
176 | int state = twlreg_grp(rdev); | 238 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
239 | int grp = 0; | ||
240 | int ret; | ||
241 | |||
242 | if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) | ||
243 | grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030; | ||
244 | |||
245 | /* For 6030, set the off state for all grps enabled */ | ||
246 | ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, | ||
247 | (grp) << TWL6030_CFG_STATE_GRP_SHIFT | | ||
248 | TWL6030_CFG_STATE_OFF); | ||
249 | |||
250 | return ret; | ||
251 | } | ||
177 | 252 | ||
178 | if (twl_class_is_6030()) | 253 | static int twl4030reg_get_status(struct regulator_dev *rdev) |
179 | return 0; /* FIXME return for 6030 regulator */ | 254 | { |
255 | int state = twlreg_grp(rdev); | ||
180 | 256 | ||
181 | if (state < 0) | 257 | if (state < 0) |
182 | return state; | 258 | return state; |
@@ -190,15 +266,39 @@ static int twlreg_get_status(struct regulator_dev *rdev) | |||
190 | : REGULATOR_STATUS_STANDBY; | 266 | : REGULATOR_STATUS_STANDBY; |
191 | } | 267 | } |
192 | 268 | ||
193 | static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode) | 269 | static int twl6030reg_get_status(struct regulator_dev *rdev) |
270 | { | ||
271 | struct twlreg_info *info = rdev_get_drvdata(rdev); | ||
272 | int val; | ||
273 | |||
274 | val = twlreg_grp(rdev); | ||
275 | if (val < 0) | ||
276 | return val; | ||
277 | |||
278 | val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE); | ||
279 | |||
280 | switch (TWL6030_CFG_STATE_APP(val)) { | ||
281 | case TWL6030_CFG_STATE_ON: | ||
282 | return REGULATOR_STATUS_NORMAL; | ||
283 | |||
284 | case TWL6030_CFG_STATE_SLEEP: | ||
285 | return REGULATOR_STATUS_STANDBY; | ||
286 | |||
287 | case TWL6030_CFG_STATE_OFF: | ||
288 | case TWL6030_CFG_STATE_OFF2: | ||
289 | default: | ||
290 | break; | ||
291 | } | ||
292 | |||
293 | return REGULATOR_STATUS_OFF; | ||
294 | } | ||
295 | |||
296 | static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode) | ||
194 | { | 297 | { |
195 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 298 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
196 | unsigned message; | 299 | unsigned message; |
197 | int status; | 300 | int status; |
198 | 301 | ||
199 | if (twl_class_is_6030()) | ||
200 | return 0; /* FIXME return for 6030 regulator */ | ||
201 | |||
202 | /* We can only set the mode through state machine commands... */ | 302 | /* We can only set the mode through state machine commands... */ |
203 | switch (mode) { | 303 | switch (mode) { |
204 | case REGULATOR_MODE_NORMAL: | 304 | case REGULATOR_MODE_NORMAL: |
@@ -227,6 +327,36 @@ static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode) | |||
227 | message & 0xff, TWL4030_PM_MASTER_PB_WORD_LSB); | 327 | message & 0xff, TWL4030_PM_MASTER_PB_WORD_LSB); |
228 | } | 328 | } |
229 | 329 | ||
330 | static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode) | ||
331 | { | ||
332 | struct twlreg_info *info = rdev_get_drvdata(rdev); | ||
333 | int grp = 0; | ||
334 | int val; | ||
335 | |||
336 | if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) | ||
337 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); | ||
338 | |||
339 | if (grp < 0) | ||
340 | return grp; | ||
341 | |||
342 | /* Compose the state register settings */ | ||
343 | val = grp << TWL6030_CFG_STATE_GRP_SHIFT; | ||
344 | /* We can only set the mode through state machine commands... */ | ||
345 | switch (mode) { | ||
346 | case REGULATOR_MODE_NORMAL: | ||
347 | val |= TWL6030_CFG_STATE_ON; | ||
348 | break; | ||
349 | case REGULATOR_MODE_STANDBY: | ||
350 | val |= TWL6030_CFG_STATE_SLEEP; | ||
351 | break; | ||
352 | |||
353 | default: | ||
354 | return -EINVAL; | ||
355 | } | ||
356 | |||
357 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, val); | ||
358 | } | ||
359 | |||
230 | /*----------------------------------------------------------------------*/ | 360 | /*----------------------------------------------------------------------*/ |
231 | 361 | ||
232 | /* | 362 | /* |
@@ -375,13 +505,13 @@ static struct regulator_ops twl4030ldo_ops = { | |||
375 | .set_voltage = twl4030ldo_set_voltage, | 505 | .set_voltage = twl4030ldo_set_voltage, |
376 | .get_voltage = twl4030ldo_get_voltage, | 506 | .get_voltage = twl4030ldo_get_voltage, |
377 | 507 | ||
378 | .enable = twlreg_enable, | 508 | .enable = twl4030reg_enable, |
379 | .disable = twlreg_disable, | 509 | .disable = twl4030reg_disable, |
380 | .is_enabled = twlreg_is_enabled, | 510 | .is_enabled = twl4030reg_is_enabled, |
381 | 511 | ||
382 | .set_mode = twlreg_set_mode, | 512 | .set_mode = twl4030reg_set_mode, |
383 | 513 | ||
384 | .get_status = twlreg_get_status, | 514 | .get_status = twl4030reg_get_status, |
385 | }; | 515 | }; |
386 | 516 | ||
387 | static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) | 517 | static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) |
@@ -433,13 +563,13 @@ static struct regulator_ops twl6030ldo_ops = { | |||
433 | .set_voltage = twl6030ldo_set_voltage, | 563 | .set_voltage = twl6030ldo_set_voltage, |
434 | .get_voltage = twl6030ldo_get_voltage, | 564 | .get_voltage = twl6030ldo_get_voltage, |
435 | 565 | ||
436 | .enable = twlreg_enable, | 566 | .enable = twl6030reg_enable, |
437 | .disable = twlreg_disable, | 567 | .disable = twl6030reg_disable, |
438 | .is_enabled = twlreg_is_enabled, | 568 | .is_enabled = twl6030reg_is_enabled, |
439 | 569 | ||
440 | .set_mode = twlreg_set_mode, | 570 | .set_mode = twl6030reg_set_mode, |
441 | 571 | ||
442 | .get_status = twlreg_get_status, | 572 | .get_status = twl6030reg_get_status, |
443 | }; | 573 | }; |
444 | 574 | ||
445 | /*----------------------------------------------------------------------*/ | 575 | /*----------------------------------------------------------------------*/ |
@@ -461,25 +591,242 @@ static int twlfixed_get_voltage(struct regulator_dev *rdev) | |||
461 | return info->min_mV * 1000; | 591 | return info->min_mV * 1000; |
462 | } | 592 | } |
463 | 593 | ||
464 | static struct regulator_ops twlfixed_ops = { | 594 | static struct regulator_ops twl4030fixed_ops = { |
595 | .list_voltage = twlfixed_list_voltage, | ||
596 | |||
597 | .get_voltage = twlfixed_get_voltage, | ||
598 | |||
599 | .enable = twl4030reg_enable, | ||
600 | .disable = twl4030reg_disable, | ||
601 | .is_enabled = twl4030reg_is_enabled, | ||
602 | |||
603 | .set_mode = twl4030reg_set_mode, | ||
604 | |||
605 | .get_status = twl4030reg_get_status, | ||
606 | }; | ||
607 | |||
608 | static struct regulator_ops twl6030fixed_ops = { | ||
465 | .list_voltage = twlfixed_list_voltage, | 609 | .list_voltage = twlfixed_list_voltage, |
466 | 610 | ||
467 | .get_voltage = twlfixed_get_voltage, | 611 | .get_voltage = twlfixed_get_voltage, |
468 | 612 | ||
469 | .enable = twlreg_enable, | 613 | .enable = twl6030reg_enable, |
470 | .disable = twlreg_disable, | 614 | .disable = twl6030reg_disable, |
471 | .is_enabled = twlreg_is_enabled, | 615 | .is_enabled = twl6030reg_is_enabled, |
472 | 616 | ||
473 | .set_mode = twlreg_set_mode, | 617 | .set_mode = twl6030reg_set_mode, |
474 | 618 | ||
475 | .get_status = twlreg_get_status, | 619 | .get_status = twl6030reg_get_status, |
476 | }; | 620 | }; |
477 | 621 | ||
478 | static struct regulator_ops twl6030_fixed_resource = { | 622 | static struct regulator_ops twl6030_fixed_resource = { |
479 | .enable = twlreg_enable, | 623 | .enable = twl6030reg_enable, |
480 | .disable = twlreg_disable, | 624 | .disable = twl6030reg_disable, |
481 | .is_enabled = twlreg_is_enabled, | 625 | .is_enabled = twl6030reg_is_enabled, |
482 | .get_status = twlreg_get_status, | 626 | .get_status = twl6030reg_get_status, |
627 | }; | ||
628 | |||
629 | /* | ||
630 | * SMPS status and control | ||
631 | */ | ||
632 | |||
633 | static int twl6030smps_list_voltage(struct regulator_dev *rdev, unsigned index) | ||
634 | { | ||
635 | struct twlreg_info *info = rdev_get_drvdata(rdev); | ||
636 | |||
637 | int voltage = 0; | ||
638 | |||
639 | switch (info->flags) { | ||
640 | case SMPS_OFFSET_EN: | ||
641 | voltage = 100000; | ||
642 | /* fall through */ | ||
643 | case 0: | ||
644 | switch (index) { | ||
645 | case 0: | ||
646 | voltage = 0; | ||
647 | break; | ||
648 | case 58: | ||
649 | voltage = 1350 * 1000; | ||
650 | break; | ||
651 | case 59: | ||
652 | voltage = 1500 * 1000; | ||
653 | break; | ||
654 | case 60: | ||
655 | voltage = 1800 * 1000; | ||
656 | break; | ||
657 | case 61: | ||
658 | voltage = 1900 * 1000; | ||
659 | break; | ||
660 | case 62: | ||
661 | voltage = 2100 * 1000; | ||
662 | break; | ||
663 | default: | ||
664 | voltage += (600000 + (12500 * (index - 1))); | ||
665 | } | ||
666 | break; | ||
667 | case SMPS_EXTENDED_EN: | ||
668 | switch (index) { | ||
669 | case 0: | ||
670 | voltage = 0; | ||
671 | break; | ||
672 | case 58: | ||
673 | voltage = 2084 * 1000; | ||
674 | break; | ||
675 | case 59: | ||
676 | voltage = 2315 * 1000; | ||
677 | break; | ||
678 | case 60: | ||
679 | voltage = 2778 * 1000; | ||
680 | break; | ||
681 | case 61: | ||
682 | voltage = 2932 * 1000; | ||
683 | break; | ||
684 | case 62: | ||
685 | voltage = 3241 * 1000; | ||
686 | break; | ||
687 | default: | ||
688 | voltage = (1852000 + (38600 * (index - 1))); | ||
689 | } | ||
690 | break; | ||
691 | case SMPS_OFFSET_EN | SMPS_EXTENDED_EN: | ||
692 | switch (index) { | ||
693 | case 0: | ||
694 | voltage = 0; | ||
695 | break; | ||
696 | case 58: | ||
697 | voltage = 4167 * 1000; | ||
698 | break; | ||
699 | case 59: | ||
700 | voltage = 2315 * 1000; | ||
701 | break; | ||
702 | case 60: | ||
703 | voltage = 2778 * 1000; | ||
704 | break; | ||
705 | case 61: | ||
706 | voltage = 2932 * 1000; | ||
707 | break; | ||
708 | case 62: | ||
709 | voltage = 3241 * 1000; | ||
710 | break; | ||
711 | default: | ||
712 | voltage = (2161000 + (38600 * (index - 1))); | ||
713 | } | ||
714 | break; | ||
715 | } | ||
716 | |||
717 | return voltage; | ||
718 | } | ||
719 | |||
720 | static int | ||
721 | twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, | ||
722 | unsigned int *selector) | ||
723 | { | ||
724 | struct twlreg_info *info = rdev_get_drvdata(rdev); | ||
725 | int vsel = 0; | ||
726 | |||
727 | switch (info->flags) { | ||
728 | case 0: | ||
729 | if (min_uV == 0) | ||
730 | vsel = 0; | ||
731 | else if ((min_uV >= 600000) && (max_uV <= 1300000)) { | ||
732 | vsel = (min_uV - 600000) / 125; | ||
733 | if (vsel % 100) | ||
734 | vsel += 100; | ||
735 | vsel /= 100; | ||
736 | vsel++; | ||
737 | } | ||
738 | /* Values 1..57 for vsel are linear and can be calculated | ||
739 | * values 58..62 are non linear. | ||
740 | */ | ||
741 | else if ((min_uV > 1900000) && (max_uV >= 2100000)) | ||
742 | vsel = 62; | ||
743 | else if ((min_uV > 1800000) && (max_uV >= 1900000)) | ||
744 | vsel = 61; | ||
745 | else if ((min_uV > 1500000) && (max_uV >= 1800000)) | ||
746 | vsel = 60; | ||
747 | else if ((min_uV > 1350000) && (max_uV >= 1500000)) | ||
748 | vsel = 59; | ||
749 | else if ((min_uV > 1300000) && (max_uV >= 1350000)) | ||
750 | vsel = 58; | ||
751 | else | ||
752 | return -EINVAL; | ||
753 | break; | ||
754 | case SMPS_OFFSET_EN: | ||
755 | if (min_uV == 0) | ||
756 | vsel = 0; | ||
757 | else if ((min_uV >= 700000) && (max_uV <= 1420000)) { | ||
758 | vsel = (min_uV - 700000) / 125; | ||
759 | if (vsel % 100) | ||
760 | vsel += 100; | ||
761 | vsel /= 100; | ||
762 | vsel++; | ||
763 | } | ||
764 | /* Values 1..57 for vsel are linear and can be calculated | ||
765 | * values 58..62 are non linear. | ||
766 | */ | ||
767 | else if ((min_uV > 1900000) && (max_uV >= 2100000)) | ||
768 | vsel = 62; | ||
769 | else if ((min_uV > 1800000) && (max_uV >= 1900000)) | ||
770 | vsel = 61; | ||
771 | else if ((min_uV > 1350000) && (max_uV >= 1800000)) | ||
772 | vsel = 60; | ||
773 | else if ((min_uV > 1350000) && (max_uV >= 1500000)) | ||
774 | vsel = 59; | ||
775 | else if ((min_uV > 1300000) && (max_uV >= 1350000)) | ||
776 | vsel = 58; | ||
777 | else | ||
778 | return -EINVAL; | ||
779 | break; | ||
780 | case SMPS_EXTENDED_EN: | ||
781 | if (min_uV == 0) | ||
782 | vsel = 0; | ||
783 | else if ((min_uV >= 1852000) && (max_uV <= 4013600)) { | ||
784 | vsel = (min_uV - 1852000) / 386; | ||
785 | if (vsel % 100) | ||
786 | vsel += 100; | ||
787 | vsel /= 100; | ||
788 | vsel++; | ||
789 | } | ||
790 | break; | ||
791 | case SMPS_OFFSET_EN|SMPS_EXTENDED_EN: | ||
792 | if (min_uV == 0) | ||
793 | vsel = 0; | ||
794 | else if ((min_uV >= 2161000) && (max_uV <= 4321000)) { | ||
795 | vsel = (min_uV - 1852000) / 386; | ||
796 | if (vsel % 100) | ||
797 | vsel += 100; | ||
798 | vsel /= 100; | ||
799 | vsel++; | ||
800 | } | ||
801 | break; | ||
802 | } | ||
803 | |||
804 | *selector = vsel; | ||
805 | |||
806 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS, | ||
807 | vsel); | ||
808 | } | ||
809 | |||
810 | static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev) | ||
811 | { | ||
812 | struct twlreg_info *info = rdev_get_drvdata(rdev); | ||
813 | |||
814 | return twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS); | ||
815 | } | ||
816 | |||
817 | static struct regulator_ops twlsmps_ops = { | ||
818 | .list_voltage = twl6030smps_list_voltage, | ||
819 | |||
820 | .set_voltage = twl6030smps_set_voltage, | ||
821 | .get_voltage_sel = twl6030smps_get_voltage_sel, | ||
822 | |||
823 | .enable = twl6030reg_enable, | ||
824 | .disable = twl6030reg_disable, | ||
825 | .is_enabled = twl6030reg_is_enabled, | ||
826 | |||
827 | .set_mode = twl6030reg_set_mode, | ||
828 | |||
829 | .get_status = twl6030reg_get_status, | ||
483 | }; | 830 | }; |
484 | 831 | ||
485 | /*----------------------------------------------------------------------*/ | 832 | /*----------------------------------------------------------------------*/ |
@@ -487,11 +834,10 @@ static struct regulator_ops twl6030_fixed_resource = { | |||
487 | #define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ | 834 | #define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ |
488 | remap_conf) \ | 835 | remap_conf) \ |
489 | TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ | 836 | TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ |
490 | remap_conf, TWL4030) | 837 | remap_conf, TWL4030, twl4030fixed_ops) |
491 | #define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ | 838 | #define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay) \ |
492 | remap_conf) \ | ||
493 | TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ | 839 | TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ |
494 | remap_conf, TWL6030) | 840 | 0x0, TWL6030, twl6030fixed_ops) |
495 | 841 | ||
496 | #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) { \ | 842 | #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) { \ |
497 | .base = offset, \ | 843 | .base = offset, \ |
@@ -510,13 +856,11 @@ static struct regulator_ops twl6030_fixed_resource = { | |||
510 | }, \ | 856 | }, \ |
511 | } | 857 | } |
512 | 858 | ||
513 | #define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num, \ | 859 | #define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \ |
514 | remap_conf) { \ | ||
515 | .base = offset, \ | 860 | .base = offset, \ |
516 | .id = num, \ | 861 | .id = num, \ |
517 | .min_mV = min_mVolts, \ | 862 | .min_mV = min_mVolts, \ |
518 | .max_mV = max_mVolts, \ | 863 | .max_mV = max_mVolts, \ |
519 | .remap = remap_conf, \ | ||
520 | .desc = { \ | 864 | .desc = { \ |
521 | .name = #label, \ | 865 | .name = #label, \ |
522 | .id = TWL6030_REG_##label, \ | 866 | .id = TWL6030_REG_##label, \ |
@@ -527,9 +871,23 @@ static struct regulator_ops twl6030_fixed_resource = { | |||
527 | }, \ | 871 | }, \ |
528 | } | 872 | } |
529 | 873 | ||
874 | #define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \ | ||
875 | .base = offset, \ | ||
876 | .id = num, \ | ||
877 | .min_mV = min_mVolts, \ | ||
878 | .max_mV = max_mVolts, \ | ||
879 | .desc = { \ | ||
880 | .name = #label, \ | ||
881 | .id = TWL6025_REG_##label, \ | ||
882 | .n_voltages = ((max_mVolts - min_mVolts)/100) + 1, \ | ||
883 | .ops = &twl6030ldo_ops, \ | ||
884 | .type = REGULATOR_VOLTAGE, \ | ||
885 | .owner = THIS_MODULE, \ | ||
886 | }, \ | ||
887 | } | ||
530 | 888 | ||
531 | #define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \ | 889 | #define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \ |
532 | family) { \ | 890 | family, operations) { \ |
533 | .base = offset, \ | 891 | .base = offset, \ |
534 | .id = num, \ | 892 | .id = num, \ |
535 | .min_mV = mVolts, \ | 893 | .min_mV = mVolts, \ |
@@ -539,17 +897,16 @@ static struct regulator_ops twl6030_fixed_resource = { | |||
539 | .name = #label, \ | 897 | .name = #label, \ |
540 | .id = family##_REG_##label, \ | 898 | .id = family##_REG_##label, \ |
541 | .n_voltages = 1, \ | 899 | .n_voltages = 1, \ |
542 | .ops = &twlfixed_ops, \ | 900 | .ops = &operations, \ |
543 | .type = REGULATOR_VOLTAGE, \ | 901 | .type = REGULATOR_VOLTAGE, \ |
544 | .owner = THIS_MODULE, \ | 902 | .owner = THIS_MODULE, \ |
545 | }, \ | 903 | }, \ |
546 | } | 904 | } |
547 | 905 | ||
548 | #define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay, remap_conf) { \ | 906 | #define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay) { \ |
549 | .base = offset, \ | 907 | .base = offset, \ |
550 | .id = num, \ | 908 | .id = num, \ |
551 | .delay = turnon_delay, \ | 909 | .delay = turnon_delay, \ |
552 | .remap = remap_conf, \ | ||
553 | .desc = { \ | 910 | .desc = { \ |
554 | .name = #label, \ | 911 | .name = #label, \ |
555 | .id = TWL6030_REG_##label, \ | 912 | .id = TWL6030_REG_##label, \ |
@@ -559,6 +916,21 @@ static struct regulator_ops twl6030_fixed_resource = { | |||
559 | }, \ | 916 | }, \ |
560 | } | 917 | } |
561 | 918 | ||
919 | #define TWL6025_ADJUSTABLE_SMPS(label, offset, num) { \ | ||
920 | .base = offset, \ | ||
921 | .id = num, \ | ||
922 | .min_mV = 600, \ | ||
923 | .max_mV = 2100, \ | ||
924 | .desc = { \ | ||
925 | .name = #label, \ | ||
926 | .id = TWL6025_REG_##label, \ | ||
927 | .n_voltages = 63, \ | ||
928 | .ops = &twlsmps_ops, \ | ||
929 | .type = REGULATOR_VOLTAGE, \ | ||
930 | .owner = THIS_MODULE, \ | ||
931 | }, \ | ||
932 | } | ||
933 | |||
562 | /* | 934 | /* |
563 | * We list regulators here if systems need some level of | 935 | * We list regulators here if systems need some level of |
564 | * software control over them after boot. | 936 | * software control over them after boot. |
@@ -589,19 +961,52 @@ static struct twlreg_info twl_regs[] = { | |||
589 | /* 6030 REG with base as PMC Slave Misc : 0x0030 */ | 961 | /* 6030 REG with base as PMC Slave Misc : 0x0030 */ |
590 | /* Turnon-delay and remap configuration values for 6030 are not | 962 | /* Turnon-delay and remap configuration values for 6030 are not |
591 | verified since the specification is not public */ | 963 | verified since the specification is not public */ |
592 | TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1, 0x21), | 964 | TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1), |
593 | TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2, 0x21), | 965 | TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2), |
594 | TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3, 0x21), | 966 | TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3), |
595 | TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4, 0x21), | 967 | TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4), |
596 | TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5, 0x21), | 968 | TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5), |
597 | TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7, 0x21), | 969 | TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7), |
598 | TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x21), | 970 | TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0), |
599 | TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x21), | 971 | TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0), |
600 | TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x21), | 972 | TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0), |
601 | TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x21), | 973 | TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0), |
602 | TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0, 0x21), | 974 | TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0), |
975 | |||
976 | /* 6025 are renamed compared to 6030 versions */ | ||
977 | TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300, 1), | ||
978 | TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300, 2), | ||
979 | TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300, 3), | ||
980 | TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300, 4), | ||
981 | TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300, 5), | ||
982 | TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300, 7), | ||
983 | TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300, 16), | ||
984 | TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300, 17), | ||
985 | TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300, 18), | ||
986 | |||
987 | TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34, 1), | ||
988 | TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10, 2), | ||
989 | TWL6025_ADJUSTABLE_SMPS(VIO, 0x16, 3), | ||
603 | }; | 990 | }; |
604 | 991 | ||
992 | static u8 twl_get_smps_offset(void) | ||
993 | { | ||
994 | u8 value; | ||
995 | |||
996 | twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value, | ||
997 | TWL6030_SMPS_OFFSET); | ||
998 | return value; | ||
999 | } | ||
1000 | |||
1001 | static u8 twl_get_smps_mult(void) | ||
1002 | { | ||
1003 | u8 value; | ||
1004 | |||
1005 | twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value, | ||
1006 | TWL6030_SMPS_MULT); | ||
1007 | return value; | ||
1008 | } | ||
1009 | |||
605 | static int __devinit twlreg_probe(struct platform_device *pdev) | 1010 | static int __devinit twlreg_probe(struct platform_device *pdev) |
606 | { | 1011 | { |
607 | int i; | 1012 | int i; |
@@ -623,6 +1028,9 @@ static int __devinit twlreg_probe(struct platform_device *pdev) | |||
623 | if (!initdata) | 1028 | if (!initdata) |
624 | return -EINVAL; | 1029 | return -EINVAL; |
625 | 1030 | ||
1031 | /* copy the features into regulator data */ | ||
1032 | info->features = (unsigned long)initdata->driver_data; | ||
1033 | |||
626 | /* Constrain board-specific capabilities according to what | 1034 | /* Constrain board-specific capabilities according to what |
627 | * this driver and the chip itself can actually do. | 1035 | * this driver and the chip itself can actually do. |
628 | */ | 1036 | */ |
@@ -645,6 +1053,27 @@ static int __devinit twlreg_probe(struct platform_device *pdev) | |||
645 | break; | 1053 | break; |
646 | } | 1054 | } |
647 | 1055 | ||
1056 | switch (pdev->id) { | ||
1057 | case TWL6025_REG_SMPS3: | ||
1058 | if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3) | ||
1059 | info->flags |= SMPS_EXTENDED_EN; | ||
1060 | if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3) | ||
1061 | info->flags |= SMPS_OFFSET_EN; | ||
1062 | break; | ||
1063 | case TWL6025_REG_SMPS4: | ||
1064 | if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4) | ||
1065 | info->flags |= SMPS_EXTENDED_EN; | ||
1066 | if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4) | ||
1067 | info->flags |= SMPS_OFFSET_EN; | ||
1068 | break; | ||
1069 | case TWL6025_REG_VIO: | ||
1070 | if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO) | ||
1071 | info->flags |= SMPS_EXTENDED_EN; | ||
1072 | if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO) | ||
1073 | info->flags |= SMPS_OFFSET_EN; | ||
1074 | break; | ||
1075 | } | ||
1076 | |||
648 | rdev = regulator_register(&info->desc, &pdev->dev, initdata, info); | 1077 | rdev = regulator_register(&info->desc, &pdev->dev, initdata, info); |
649 | if (IS_ERR(rdev)) { | 1078 | if (IS_ERR(rdev)) { |
650 | dev_err(&pdev->dev, "can't register %s, %ld\n", | 1079 | dev_err(&pdev->dev, "can't register %s, %ld\n", |
@@ -653,7 +1082,8 @@ static int __devinit twlreg_probe(struct platform_device *pdev) | |||
653 | } | 1082 | } |
654 | platform_set_drvdata(pdev, rdev); | 1083 | platform_set_drvdata(pdev, rdev); |
655 | 1084 | ||
656 | twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP, | 1085 | if (twl_class_is_4030()) |
1086 | twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP, | ||
657 | info->remap); | 1087 | info->remap); |
658 | 1088 | ||
659 | /* NOTE: many regulators support short-circuit IRQs (presentable | 1089 | /* NOTE: many regulators support short-circuit IRQs (presentable |
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index e93453b1b978..a0982e809851 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c | |||
@@ -600,7 +600,6 @@ err: | |||
600 | static __devexit int wm831x_buckv_remove(struct platform_device *pdev) | 600 | static __devexit int wm831x_buckv_remove(struct platform_device *pdev) |
601 | { | 601 | { |
602 | struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); | 602 | struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); |
603 | struct wm831x *wm831x = dcdc->wm831x; | ||
604 | 603 | ||
605 | platform_set_drvdata(pdev, NULL); | 604 | platform_set_drvdata(pdev, NULL); |
606 | 605 | ||
@@ -776,7 +775,6 @@ err: | |||
776 | static __devexit int wm831x_buckp_remove(struct platform_device *pdev) | 775 | static __devexit int wm831x_buckp_remove(struct platform_device *pdev) |
777 | { | 776 | { |
778 | struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); | 777 | struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); |
779 | struct wm831x *wm831x = dcdc->wm831x; | ||
780 | 778 | ||
781 | platform_set_drvdata(pdev, NULL); | 779 | platform_set_drvdata(pdev, NULL); |
782 | 780 | ||
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index b42d01cef35a..0f12c70bebc9 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c | |||
@@ -55,7 +55,7 @@ static int wm8400_ldo_list_voltage(struct regulator_dev *dev, | |||
55 | return 1600000 + ((selector - 14) * 100000); | 55 | return 1600000 + ((selector - 14) * 100000); |
56 | } | 56 | } |
57 | 57 | ||
58 | static int wm8400_ldo_get_voltage(struct regulator_dev *dev) | 58 | static int wm8400_ldo_get_voltage_sel(struct regulator_dev *dev) |
59 | { | 59 | { |
60 | struct wm8400 *wm8400 = rdev_get_drvdata(dev); | 60 | struct wm8400 *wm8400 = rdev_get_drvdata(dev); |
61 | u16 val; | 61 | u16 val; |
@@ -63,7 +63,7 @@ static int wm8400_ldo_get_voltage(struct regulator_dev *dev) | |||
63 | val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev)); | 63 | val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev)); |
64 | val &= WM8400_LDO1_VSEL_MASK; | 64 | val &= WM8400_LDO1_VSEL_MASK; |
65 | 65 | ||
66 | return wm8400_ldo_list_voltage(dev, val); | 66 | return val; |
67 | } | 67 | } |
68 | 68 | ||
69 | static int wm8400_ldo_set_voltage(struct regulator_dev *dev, | 69 | static int wm8400_ldo_set_voltage(struct regulator_dev *dev, |
@@ -104,7 +104,7 @@ static struct regulator_ops wm8400_ldo_ops = { | |||
104 | .enable = wm8400_ldo_enable, | 104 | .enable = wm8400_ldo_enable, |
105 | .disable = wm8400_ldo_disable, | 105 | .disable = wm8400_ldo_disable, |
106 | .list_voltage = wm8400_ldo_list_voltage, | 106 | .list_voltage = wm8400_ldo_list_voltage, |
107 | .get_voltage = wm8400_ldo_get_voltage, | 107 | .get_voltage_sel = wm8400_ldo_get_voltage_sel, |
108 | .set_voltage = wm8400_ldo_set_voltage, | 108 | .set_voltage = wm8400_ldo_set_voltage, |
109 | }; | 109 | }; |
110 | 110 | ||
@@ -145,7 +145,7 @@ static int wm8400_dcdc_list_voltage(struct regulator_dev *dev, | |||
145 | return 850000 + (selector * 25000); | 145 | return 850000 + (selector * 25000); |
146 | } | 146 | } |
147 | 147 | ||
148 | static int wm8400_dcdc_get_voltage(struct regulator_dev *dev) | 148 | static int wm8400_dcdc_get_voltage_sel(struct regulator_dev *dev) |
149 | { | 149 | { |
150 | struct wm8400 *wm8400 = rdev_get_drvdata(dev); | 150 | struct wm8400 *wm8400 = rdev_get_drvdata(dev); |
151 | u16 val; | 151 | u16 val; |
@@ -154,7 +154,7 @@ static int wm8400_dcdc_get_voltage(struct regulator_dev *dev) | |||
154 | val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset); | 154 | val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset); |
155 | val &= WM8400_DC1_VSEL_MASK; | 155 | val &= WM8400_DC1_VSEL_MASK; |
156 | 156 | ||
157 | return 850000 + (25000 * val); | 157 | return val; |
158 | } | 158 | } |
159 | 159 | ||
160 | static int wm8400_dcdc_set_voltage(struct regulator_dev *dev, | 160 | static int wm8400_dcdc_set_voltage(struct regulator_dev *dev, |
@@ -261,7 +261,7 @@ static struct regulator_ops wm8400_dcdc_ops = { | |||
261 | .enable = wm8400_dcdc_enable, | 261 | .enable = wm8400_dcdc_enable, |
262 | .disable = wm8400_dcdc_disable, | 262 | .disable = wm8400_dcdc_disable, |
263 | .list_voltage = wm8400_dcdc_list_voltage, | 263 | .list_voltage = wm8400_dcdc_list_voltage, |
264 | .get_voltage = wm8400_dcdc_get_voltage, | 264 | .get_voltage_sel = wm8400_dcdc_get_voltage_sel, |
265 | .set_voltage = wm8400_dcdc_set_voltage, | 265 | .set_voltage = wm8400_dcdc_set_voltage, |
266 | .get_mode = wm8400_dcdc_get_mode, | 266 | .get_mode = wm8400_dcdc_get_mode, |
267 | .set_mode = wm8400_dcdc_set_mode, | 267 | .set_mode = wm8400_dcdc_set_mode, |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8e437e2f6281..f822e13dc04b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -361,12 +361,39 @@ config RTC_DRV_RX8025 | |||
361 | This driver can also be built as a module. If so, the module | 361 | This driver can also be built as a module. If so, the module |
362 | will be called rtc-rx8025. | 362 | will be called rtc-rx8025. |
363 | 363 | ||
364 | config RTC_DRV_EM3027 | ||
365 | tristate "EM Microelectronic EM3027" | ||
366 | help | ||
367 | If you say yes here you get support for the EM | ||
368 | Microelectronic EM3027 RTC chips. | ||
369 | |||
370 | This driver can also be built as a module. If so, the module | ||
371 | will be called rtc-em3027. | ||
372 | |||
373 | config RTC_DRV_RV3029C2 | ||
374 | tristate "Micro Crystal RTC" | ||
375 | help | ||
376 | If you say yes here you get support for the Micro Crystal | ||
377 | RV3029-C2 RTC chips. | ||
378 | |||
379 | This driver can also be built as a module. If so, the module | ||
380 | will be called rtc-rv3029c2. | ||
381 | |||
364 | endif # I2C | 382 | endif # I2C |
365 | 383 | ||
366 | comment "SPI RTC drivers" | 384 | comment "SPI RTC drivers" |
367 | 385 | ||
368 | if SPI_MASTER | 386 | if SPI_MASTER |
369 | 387 | ||
388 | config RTC_DRV_M41T93 | ||
389 | tristate "ST M41T93" | ||
390 | help | ||
391 | If you say yes here you will get support for the | ||
392 | ST M41T93 SPI RTC chip. | ||
393 | |||
394 | This driver can also be built as a module. If so, the module | ||
395 | will be called rtc-m41t93. | ||
396 | |||
370 | config RTC_DRV_M41T94 | 397 | config RTC_DRV_M41T94 |
371 | tristate "ST M41T94" | 398 | tristate "ST M41T94" |
372 | help | 399 | help |
@@ -655,6 +682,14 @@ config RTC_DRV_WM8350 | |||
655 | This driver can also be built as a module. If so, the module | 682 | This driver can also be built as a module. If so, the module |
656 | will be called "rtc-wm8350". | 683 | will be called "rtc-wm8350". |
657 | 684 | ||
685 | config RTC_DRV_SPEAR | ||
686 | tristate "SPEAR ST RTC" | ||
687 | depends on PLAT_SPEAR | ||
688 | default y | ||
689 | help | ||
690 | If you say Y here you will get support for the RTC found on | ||
691 | spear | ||
692 | |||
658 | config RTC_DRV_PCF50633 | 693 | config RTC_DRV_PCF50633 |
659 | depends on MFD_PCF50633 | 694 | depends on MFD_PCF50633 |
660 | tristate "NXP PCF50633 RTC" | 695 | tristate "NXP PCF50633 RTC" |
@@ -884,6 +919,13 @@ config RTC_DRV_PXA | |||
884 | This RTC driver uses PXA RTC registers available since pxa27x | 919 | This RTC driver uses PXA RTC registers available since pxa27x |
885 | series (RDxR, RYxR) instead of legacy RCNR, RTAR. | 920 | series (RDxR, RYxR) instead of legacy RCNR, RTAR. |
886 | 921 | ||
922 | config RTC_DRV_VT8500 | ||
923 | tristate "VIA/WonderMedia 85xx SoC RTC" | ||
924 | depends on ARCH_VT8500 | ||
925 | help | ||
926 | If you say Y here you will get access to the real time clock | ||
927 | built into your VIA VT8500 SoC or its relatives. | ||
928 | |||
887 | 929 | ||
888 | config RTC_DRV_SUN4V | 930 | config RTC_DRV_SUN4V |
889 | bool "SUN4V Hypervisor RTC" | 931 | bool "SUN4V Hypervisor RTC" |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 612f5a88a8ee..213d725f16d4 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -44,6 +44,7 @@ obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | |||
44 | obj-$(CONFIG_RTC_DRV_DS3232) += rtc-ds3232.o | 44 | obj-$(CONFIG_RTC_DRV_DS3232) += rtc-ds3232.o |
45 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o | 45 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o |
46 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o | 46 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o |
47 | obj-$(CONFIG_RTC_DRV_EM3027) += rtc-em3027.o | ||
47 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | 48 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o |
48 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o | 49 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o |
49 | obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o | 50 | obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o |
@@ -53,6 +54,7 @@ obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o | |||
53 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o | 54 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o |
54 | obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o | 55 | obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o |
55 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | 56 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o |
57 | obj-$(CONFIG_RTC_DRV_M41T93) += rtc-m41t93.o | ||
56 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o | 58 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o |
57 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o | 59 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o |
58 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o | 60 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o |
@@ -82,12 +84,14 @@ obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o | |||
82 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | 84 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
83 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 85 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
84 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o | 86 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o |
87 | obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o | ||
85 | obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o | 88 | obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o |
86 | obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o | 89 | obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o |
87 | obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o | 90 | obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o |
88 | obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o | 91 | obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o |
89 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o | 92 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o |
90 | obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o | 93 | obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o |
94 | obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o | ||
91 | obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o | 95 | obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o |
92 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o | 96 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o |
93 | obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o | 97 | obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o |
@@ -99,6 +103,7 @@ obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o | |||
99 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o | 103 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o |
100 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 104 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
101 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 105 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o |
106 | obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o | ||
102 | obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o | 107 | obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o |
103 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o | 108 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o |
104 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 109 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c new file mode 100644 index 000000000000..d8e1c2578553 --- /dev/null +++ b/drivers/rtc/rtc-em3027.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * An rtc/i2c driver for the EM Microelectronic EM3027 | ||
3 | * Copyright 2011 CompuLab, Ltd. | ||
4 | * | ||
5 | * Author: Mike Rapoport <mike@compulab.co.il> | ||
6 | * | ||
7 | * Based on rtc-ds1672.c by Alessandro Zummo <a.zummo@towertech.it> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/rtc.h> | ||
16 | #include <linux/bcd.h> | ||
17 | |||
18 | /* Registers */ | ||
19 | #define EM3027_REG_ON_OFF_CTRL 0x00 | ||
20 | #define EM3027_REG_IRQ_CTRL 0x01 | ||
21 | #define EM3027_REG_IRQ_FLAGS 0x02 | ||
22 | #define EM3027_REG_STATUS 0x03 | ||
23 | #define EM3027_REG_RST_CTRL 0x04 | ||
24 | |||
25 | #define EM3027_REG_WATCH_SEC 0x08 | ||
26 | #define EM3027_REG_WATCH_MIN 0x09 | ||
27 | #define EM3027_REG_WATCH_HOUR 0x0a | ||
28 | #define EM3027_REG_WATCH_DATE 0x0b | ||
29 | #define EM3027_REG_WATCH_DAY 0x0c | ||
30 | #define EM3027_REG_WATCH_MON 0x0d | ||
31 | #define EM3027_REG_WATCH_YEAR 0x0e | ||
32 | |||
33 | #define EM3027_REG_ALARM_SEC 0x10 | ||
34 | #define EM3027_REG_ALARM_MIN 0x11 | ||
35 | #define EM3027_REG_ALARM_HOUR 0x12 | ||
36 | #define EM3027_REG_ALARM_DATE 0x13 | ||
37 | #define EM3027_REG_ALARM_DAY 0x14 | ||
38 | #define EM3027_REG_ALARM_MON 0x15 | ||
39 | #define EM3027_REG_ALARM_YEAR 0x16 | ||
40 | |||
41 | static struct i2c_driver em3027_driver; | ||
42 | |||
43 | static int em3027_get_time(struct device *dev, struct rtc_time *tm) | ||
44 | { | ||
45 | struct i2c_client *client = to_i2c_client(dev); | ||
46 | |||
47 | unsigned char addr = EM3027_REG_WATCH_SEC; | ||
48 | unsigned char buf[7]; | ||
49 | |||
50 | struct i2c_msg msgs[] = { | ||
51 | {client->addr, 0, 1, &addr}, /* setup read addr */ | ||
52 | {client->addr, I2C_M_RD, 7, buf}, /* read time/date */ | ||
53 | }; | ||
54 | |||
55 | /* read time/date registers */ | ||
56 | if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { | ||
57 | dev_err(&client->dev, "%s: read error\n", __func__); | ||
58 | return -EIO; | ||
59 | } | ||
60 | |||
61 | tm->tm_sec = bcd2bin(buf[0]); | ||
62 | tm->tm_min = bcd2bin(buf[1]); | ||
63 | tm->tm_hour = bcd2bin(buf[2]); | ||
64 | tm->tm_mday = bcd2bin(buf[3]); | ||
65 | tm->tm_wday = bcd2bin(buf[4]); | ||
66 | tm->tm_mon = bcd2bin(buf[5]); | ||
67 | tm->tm_year = bcd2bin(buf[6]) + 100; | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int em3027_set_time(struct device *dev, struct rtc_time *tm) | ||
73 | { | ||
74 | struct i2c_client *client = to_i2c_client(dev); | ||
75 | unsigned char buf[8]; | ||
76 | |||
77 | struct i2c_msg msg = { | ||
78 | client->addr, 0, 8, buf, /* write time/date */ | ||
79 | }; | ||
80 | |||
81 | buf[0] = EM3027_REG_WATCH_SEC; | ||
82 | buf[1] = bin2bcd(tm->tm_sec); | ||
83 | buf[2] = bin2bcd(tm->tm_min); | ||
84 | buf[3] = bin2bcd(tm->tm_hour); | ||
85 | buf[4] = bin2bcd(tm->tm_mday); | ||
86 | buf[5] = bin2bcd(tm->tm_wday); | ||
87 | buf[6] = bin2bcd(tm->tm_mon); | ||
88 | buf[7] = bin2bcd(tm->tm_year % 100); | ||
89 | |||
90 | /* write time/date registers */ | ||
91 | if ((i2c_transfer(client->adapter, &msg, 1)) != 1) { | ||
92 | dev_err(&client->dev, "%s: write error\n", __func__); | ||
93 | return -EIO; | ||
94 | } | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static const struct rtc_class_ops em3027_rtc_ops = { | ||
100 | .read_time = em3027_get_time, | ||
101 | .set_time = em3027_set_time, | ||
102 | }; | ||
103 | |||
104 | static int em3027_probe(struct i2c_client *client, | ||
105 | const struct i2c_device_id *id) | ||
106 | { | ||
107 | struct rtc_device *rtc; | ||
108 | |||
109 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
110 | return -ENODEV; | ||
111 | |||
112 | rtc = rtc_device_register(em3027_driver.driver.name, &client->dev, | ||
113 | &em3027_rtc_ops, THIS_MODULE); | ||
114 | if (IS_ERR(rtc)) | ||
115 | return PTR_ERR(rtc); | ||
116 | |||
117 | i2c_set_clientdata(client, rtc); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int em3027_remove(struct i2c_client *client) | ||
123 | { | ||
124 | struct rtc_device *rtc = i2c_get_clientdata(client); | ||
125 | |||
126 | if (rtc) | ||
127 | rtc_device_unregister(rtc); | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static struct i2c_device_id em3027_id[] = { | ||
133 | { "em3027", 0 }, | ||
134 | { } | ||
135 | }; | ||
136 | |||
137 | static struct i2c_driver em3027_driver = { | ||
138 | .driver = { | ||
139 | .name = "rtc-em3027", | ||
140 | }, | ||
141 | .probe = &em3027_probe, | ||
142 | .remove = &em3027_remove, | ||
143 | .id_table = em3027_id, | ||
144 | }; | ||
145 | |||
146 | static int __init em3027_init(void) | ||
147 | { | ||
148 | return i2c_add_driver(&em3027_driver); | ||
149 | } | ||
150 | |||
151 | static void __exit em3027_exit(void) | ||
152 | { | ||
153 | i2c_del_driver(&em3027_driver); | ||
154 | } | ||
155 | |||
156 | MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); | ||
157 | MODULE_DESCRIPTION("EM Microelectronic EM3027 RTC driver"); | ||
158 | MODULE_LICENSE("GPL"); | ||
159 | |||
160 | module_init(em3027_init); | ||
161 | module_exit(em3027_exit); | ||
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c new file mode 100644 index 000000000000..1a84b3e227d1 --- /dev/null +++ b/drivers/rtc/rtc-m41t93.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Driver for ST M41T93 SPI RTC | ||
4 | * | ||
5 | * (c) 2010 Nikolaus Voss, Weinmann Medical GmbH | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/bcd.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/spi/spi.h> | ||
18 | |||
19 | #define M41T93_REG_SSEC 0 | ||
20 | #define M41T93_REG_ST_SEC 1 | ||
21 | #define M41T93_REG_MIN 2 | ||
22 | #define M41T93_REG_CENT_HOUR 3 | ||
23 | #define M41T93_REG_WDAY 4 | ||
24 | #define M41T93_REG_DAY 5 | ||
25 | #define M41T93_REG_MON 6 | ||
26 | #define M41T93_REG_YEAR 7 | ||
27 | |||
28 | |||
29 | #define M41T93_REG_ALM_HOUR_HT 0xc | ||
30 | #define M41T93_REG_FLAGS 0xf | ||
31 | |||
32 | #define M41T93_FLAG_ST (1 << 7) | ||
33 | #define M41T93_FLAG_OF (1 << 2) | ||
34 | #define M41T93_FLAG_BL (1 << 4) | ||
35 | #define M41T93_FLAG_HT (1 << 6) | ||
36 | |||
37 | static inline int m41t93_set_reg(struct spi_device *spi, u8 addr, u8 data) | ||
38 | { | ||
39 | u8 buf[2]; | ||
40 | |||
41 | /* MSB must be '1' to write */ | ||
42 | buf[0] = addr | 0x80; | ||
43 | buf[1] = data; | ||
44 | |||
45 | return spi_write(spi, buf, sizeof(buf)); | ||
46 | } | ||
47 | |||
48 | static int m41t93_set_time(struct device *dev, struct rtc_time *tm) | ||
49 | { | ||
50 | struct spi_device *spi = to_spi_device(dev); | ||
51 | u8 buf[9] = {0x80}; /* write cmd + 8 data bytes */ | ||
52 | u8 * const data = &buf[1]; /* ptr to first data byte */ | ||
53 | |||
54 | dev_dbg(dev, "%s secs=%d, mins=%d, " | ||
55 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | ||
56 | "write", tm->tm_sec, tm->tm_min, | ||
57 | tm->tm_hour, tm->tm_mday, | ||
58 | tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
59 | |||
60 | if (tm->tm_year < 100) { | ||
61 | dev_warn(&spi->dev, "unsupported date (before 2000-01-01).\n"); | ||
62 | return -EINVAL; | ||
63 | } | ||
64 | |||
65 | data[M41T93_REG_SSEC] = 0; | ||
66 | data[M41T93_REG_ST_SEC] = bin2bcd(tm->tm_sec); | ||
67 | data[M41T93_REG_MIN] = bin2bcd(tm->tm_min); | ||
68 | data[M41T93_REG_CENT_HOUR] = bin2bcd(tm->tm_hour) | | ||
69 | ((tm->tm_year/100-1) << 6); | ||
70 | data[M41T93_REG_DAY] = bin2bcd(tm->tm_mday); | ||
71 | data[M41T93_REG_WDAY] = bin2bcd(tm->tm_wday + 1); | ||
72 | data[M41T93_REG_MON] = bin2bcd(tm->tm_mon + 1); | ||
73 | data[M41T93_REG_YEAR] = bin2bcd(tm->tm_year % 100); | ||
74 | |||
75 | return spi_write(spi, buf, sizeof(buf)); | ||
76 | } | ||
77 | |||
78 | |||
79 | static int m41t93_get_time(struct device *dev, struct rtc_time *tm) | ||
80 | { | ||
81 | struct spi_device *spi = to_spi_device(dev); | ||
82 | const u8 start_addr = 0; | ||
83 | u8 buf[8]; | ||
84 | int century_after_1900; | ||
85 | int tmp; | ||
86 | int ret = 0; | ||
87 | |||
88 | /* Check status of clock. Two states must be considered: | ||
89 | 1. halt bit (HT) is set: the clock is running but update of readout | ||
90 | registers has been disabled due to power failure. This is normal | ||
91 | case after poweron. Time is valid after resetting HT bit. | ||
92 | 2. oscillator fail bit (OF) is set. Oscillator has be stopped and | ||
93 | time is invalid: | ||
94 | a) OF can be immeditely reset. | ||
95 | b) OF cannot be immediately reset: oscillator has to be restarted. | ||
96 | */ | ||
97 | tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT); | ||
98 | if (tmp < 0) | ||
99 | return tmp; | ||
100 | |||
101 | if (tmp & M41T93_FLAG_HT) { | ||
102 | dev_dbg(&spi->dev, "HT bit is set, reenable clock update.\n"); | ||
103 | m41t93_set_reg(spi, M41T93_REG_ALM_HOUR_HT, | ||
104 | tmp & ~M41T93_FLAG_HT); | ||
105 | } | ||
106 | |||
107 | tmp = spi_w8r8(spi, M41T93_REG_FLAGS); | ||
108 | if (tmp < 0) | ||
109 | return tmp; | ||
110 | |||
111 | if (tmp & M41T93_FLAG_OF) { | ||
112 | ret = -EINVAL; | ||
113 | dev_warn(&spi->dev, "OF bit is set, resetting.\n"); | ||
114 | m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF); | ||
115 | |||
116 | tmp = spi_w8r8(spi, M41T93_REG_FLAGS); | ||
117 | if (tmp < 0) | ||
118 | return tmp; | ||
119 | else if (tmp & M41T93_FLAG_OF) { | ||
120 | u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST; | ||
121 | |||
122 | dev_warn(&spi->dev, | ||
123 | "OF bit is still set, kickstarting clock.\n"); | ||
124 | m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc); | ||
125 | reset_osc &= ~M41T93_FLAG_ST; | ||
126 | m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | if (tmp & M41T93_FLAG_BL) | ||
131 | dev_warn(&spi->dev, "BL bit is set, replace battery.\n"); | ||
132 | |||
133 | /* read actual time/date */ | ||
134 | tmp = spi_write_then_read(spi, &start_addr, 1, buf, sizeof(buf)); | ||
135 | if (tmp < 0) | ||
136 | return tmp; | ||
137 | |||
138 | tm->tm_sec = bcd2bin(buf[M41T93_REG_ST_SEC]); | ||
139 | tm->tm_min = bcd2bin(buf[M41T93_REG_MIN]); | ||
140 | tm->tm_hour = bcd2bin(buf[M41T93_REG_CENT_HOUR] & 0x3f); | ||
141 | tm->tm_mday = bcd2bin(buf[M41T93_REG_DAY]); | ||
142 | tm->tm_mon = bcd2bin(buf[M41T93_REG_MON]) - 1; | ||
143 | tm->tm_wday = bcd2bin(buf[M41T93_REG_WDAY] & 0x0f) - 1; | ||
144 | |||
145 | century_after_1900 = (buf[M41T93_REG_CENT_HOUR] >> 6) + 1; | ||
146 | tm->tm_year = bcd2bin(buf[M41T93_REG_YEAR]) + century_after_1900 * 100; | ||
147 | |||
148 | dev_dbg(dev, "%s secs=%d, mins=%d, " | ||
149 | "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", | ||
150 | "read", tm->tm_sec, tm->tm_min, | ||
151 | tm->tm_hour, tm->tm_mday, | ||
152 | tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
153 | |||
154 | return ret < 0 ? ret : rtc_valid_tm(tm); | ||
155 | } | ||
156 | |||
157 | |||
158 | static const struct rtc_class_ops m41t93_rtc_ops = { | ||
159 | .read_time = m41t93_get_time, | ||
160 | .set_time = m41t93_set_time, | ||
161 | }; | ||
162 | |||
163 | static struct spi_driver m41t93_driver; | ||
164 | |||
165 | static int __devinit m41t93_probe(struct spi_device *spi) | ||
166 | { | ||
167 | struct rtc_device *rtc; | ||
168 | int res; | ||
169 | |||
170 | spi->bits_per_word = 8; | ||
171 | spi_setup(spi); | ||
172 | |||
173 | res = spi_w8r8(spi, M41T93_REG_WDAY); | ||
174 | if (res < 0 || (res & 0xf8) != 0) { | ||
175 | dev_err(&spi->dev, "not found 0x%x.\n", res); | ||
176 | return -ENODEV; | ||
177 | } | ||
178 | |||
179 | rtc = rtc_device_register(m41t93_driver.driver.name, | ||
180 | &spi->dev, &m41t93_rtc_ops, THIS_MODULE); | ||
181 | if (IS_ERR(rtc)) | ||
182 | return PTR_ERR(rtc); | ||
183 | |||
184 | dev_set_drvdata(&spi->dev, rtc); | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | |||
190 | static int __devexit m41t93_remove(struct spi_device *spi) | ||
191 | { | ||
192 | struct rtc_device *rtc = platform_get_drvdata(spi); | ||
193 | |||
194 | if (rtc) | ||
195 | rtc_device_unregister(rtc); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static struct spi_driver m41t93_driver = { | ||
201 | .driver = { | ||
202 | .name = "rtc-m41t93", | ||
203 | .bus = &spi_bus_type, | ||
204 | .owner = THIS_MODULE, | ||
205 | }, | ||
206 | .probe = m41t93_probe, | ||
207 | .remove = __devexit_p(m41t93_remove), | ||
208 | }; | ||
209 | |||
210 | static __init int m41t93_init(void) | ||
211 | { | ||
212 | return spi_register_driver(&m41t93_driver); | ||
213 | } | ||
214 | module_init(m41t93_init); | ||
215 | |||
216 | static __exit void m41t93_exit(void) | ||
217 | { | ||
218 | spi_unregister_driver(&m41t93_driver); | ||
219 | } | ||
220 | module_exit(m41t93_exit); | ||
221 | |||
222 | MODULE_AUTHOR("Nikolaus Voss <n.voss@weinmann.de>"); | ||
223 | MODULE_DESCRIPTION("Driver for ST M41T93 SPI RTC"); | ||
224 | MODULE_LICENSE("GPL"); | ||
225 | MODULE_ALIAS("spi:rtc-m41t93"); | ||
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index b2f096871a97..0cec5650d56a 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c | |||
@@ -380,7 +380,7 @@ cleanup1: | |||
380 | cleanup0: | 380 | cleanup0: |
381 | dev_set_drvdata(dev, NULL); | 381 | dev_set_drvdata(dev, NULL); |
382 | mrst_rtc.dev = NULL; | 382 | mrst_rtc.dev = NULL; |
383 | release_region(iomem->start, iomem->end + 1 - iomem->start); | 383 | release_mem_region(iomem->start, resource_size(iomem)); |
384 | dev_err(dev, "rtc-mrst: unable to initialise\n"); | 384 | dev_err(dev, "rtc-mrst: unable to initialise\n"); |
385 | return retval; | 385 | return retval; |
386 | } | 386 | } |
@@ -406,7 +406,7 @@ static void __devexit rtc_mrst_do_remove(struct device *dev) | |||
406 | mrst->rtc = NULL; | 406 | mrst->rtc = NULL; |
407 | 407 | ||
408 | iomem = mrst->iomem; | 408 | iomem = mrst->iomem; |
409 | release_region(iomem->start, iomem->end + 1 - iomem->start); | 409 | release_mem_region(iomem->start, resource_size(iomem)); |
410 | mrst->iomem = NULL; | 410 | mrst->iomem = NULL; |
411 | 411 | ||
412 | mrst->dev = NULL; | 412 | mrst->dev = NULL; |
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index d814417bee8c..39e41fbdf08b 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
@@ -55,12 +55,6 @@ static const u32 PIE_BIT_DEF[MAX_PIE_NUM][2] = { | |||
55 | { MAX_PIE_FREQ, RTC_SAM7_BIT }, | 55 | { MAX_PIE_FREQ, RTC_SAM7_BIT }, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | /* Those are the bits from a classic RTC we want to mimic */ | ||
59 | #define RTC_IRQF 0x80 /* any of the following 3 is active */ | ||
60 | #define RTC_PF 0x40 /* Periodic interrupt */ | ||
61 | #define RTC_AF 0x20 /* Alarm interrupt */ | ||
62 | #define RTC_UF 0x10 /* Update interrupt for 1Hz RTC */ | ||
63 | |||
64 | #define MXC_RTC_TIME 0 | 58 | #define MXC_RTC_TIME 0 |
65 | #define MXC_RTC_ALARM 1 | 59 | #define MXC_RTC_ALARM 1 |
66 | 60 | ||
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index f90c574f9d05..0c423892923c 100644 --- a/drivers/rtc/rtc-pcf50633.c +++ b/drivers/rtc/rtc-pcf50633.c | |||
@@ -58,7 +58,6 @@ struct pcf50633_time { | |||
58 | 58 | ||
59 | struct pcf50633_rtc { | 59 | struct pcf50633_rtc { |
60 | int alarm_enabled; | 60 | int alarm_enabled; |
61 | int second_enabled; | ||
62 | int alarm_pending; | 61 | int alarm_pending; |
63 | 62 | ||
64 | struct pcf50633 *pcf; | 63 | struct pcf50633 *pcf; |
@@ -143,7 +142,7 @@ static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
143 | { | 142 | { |
144 | struct pcf50633_rtc *rtc; | 143 | struct pcf50633_rtc *rtc; |
145 | struct pcf50633_time pcf_tm; | 144 | struct pcf50633_time pcf_tm; |
146 | int second_masked, alarm_masked, ret = 0; | 145 | int alarm_masked, ret = 0; |
147 | 146 | ||
148 | rtc = dev_get_drvdata(dev); | 147 | rtc = dev_get_drvdata(dev); |
149 | 148 | ||
@@ -162,11 +161,8 @@ static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
162 | pcf_tm.time[PCF50633_TI_SEC]); | 161 | pcf_tm.time[PCF50633_TI_SEC]); |
163 | 162 | ||
164 | 163 | ||
165 | second_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_SECOND); | ||
166 | alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM); | 164 | alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM); |
167 | 165 | ||
168 | if (!second_masked) | ||
169 | pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_SECOND); | ||
170 | if (!alarm_masked) | 166 | if (!alarm_masked) |
171 | pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM); | 167 | pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM); |
172 | 168 | ||
@@ -175,8 +171,6 @@ static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
175 | PCF50633_TI_EXTENT, | 171 | PCF50633_TI_EXTENT, |
176 | &pcf_tm.time[0]); | 172 | &pcf_tm.time[0]); |
177 | 173 | ||
178 | if (!second_masked) | ||
179 | pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_SECOND); | ||
180 | if (!alarm_masked) | 174 | if (!alarm_masked) |
181 | pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); | 175 | pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); |
182 | 176 | ||
@@ -250,15 +244,8 @@ static void pcf50633_rtc_irq(int irq, void *data) | |||
250 | { | 244 | { |
251 | struct pcf50633_rtc *rtc = data; | 245 | struct pcf50633_rtc *rtc = data; |
252 | 246 | ||
253 | switch (irq) { | 247 | rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); |
254 | case PCF50633_IRQ_ALARM: | 248 | rtc->alarm_pending = 1; |
255 | rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); | ||
256 | rtc->alarm_pending = 1; | ||
257 | break; | ||
258 | case PCF50633_IRQ_SECOND: | ||
259 | rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF); | ||
260 | break; | ||
261 | } | ||
262 | } | 249 | } |
263 | 250 | ||
264 | static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) | 251 | static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) |
@@ -282,9 +269,6 @@ static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) | |||
282 | 269 | ||
283 | pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM, | 270 | pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM, |
284 | pcf50633_rtc_irq, rtc); | 271 | pcf50633_rtc_irq, rtc); |
285 | pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_SECOND, | ||
286 | pcf50633_rtc_irq, rtc); | ||
287 | |||
288 | return 0; | 272 | return 0; |
289 | } | 273 | } |
290 | 274 | ||
@@ -295,7 +279,6 @@ static int __devexit pcf50633_rtc_remove(struct platform_device *pdev) | |||
295 | rtc = platform_get_drvdata(pdev); | 279 | rtc = platform_get_drvdata(pdev); |
296 | 280 | ||
297 | pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_ALARM); | 281 | pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_ALARM); |
298 | pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_SECOND); | ||
299 | 282 | ||
300 | rtc_device_unregister(rtc->rtc_dev); | 283 | rtc_device_unregister(rtc->rtc_dev); |
301 | kfree(rtc); | 284 | kfree(rtc); |
diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c new file mode 100644 index 000000000000..ea09ff211dc6 --- /dev/null +++ b/drivers/rtc/rtc-rv3029c2.c | |||
@@ -0,0 +1,454 @@ | |||
1 | /* | ||
2 | * Micro Crystal RV-3029C2 rtc class driver | ||
3 | * | ||
4 | * Author: Gregory Hermant <gregory.hermant@calao-systems.com> | ||
5 | * | ||
6 | * based on previously existing rtc class drivers | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * NOTE: Currently this driver only supports the bare minimum for read | ||
13 | * and write the RTC and alarms. The extra features provided by this chip | ||
14 | * (trickle charger, eeprom, T° compensation) are unavailable. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/bcd.h> | ||
20 | #include <linux/rtc.h> | ||
21 | |||
22 | /* Register map */ | ||
23 | /* control section */ | ||
24 | #define RV3029C2_ONOFF_CTRL 0x00 | ||
25 | #define RV3029C2_IRQ_CTRL 0x01 | ||
26 | #define RV3029C2_IRQ_CTRL_AIE (1 << 0) | ||
27 | #define RV3029C2_IRQ_FLAGS 0x02 | ||
28 | #define RV3029C2_IRQ_FLAGS_AF (1 << 0) | ||
29 | #define RV3029C2_STATUS 0x03 | ||
30 | #define RV3029C2_STATUS_VLOW1 (1 << 2) | ||
31 | #define RV3029C2_STATUS_VLOW2 (1 << 3) | ||
32 | #define RV3029C2_STATUS_SR (1 << 4) | ||
33 | #define RV3029C2_STATUS_PON (1 << 5) | ||
34 | #define RV3029C2_STATUS_EEBUSY (1 << 7) | ||
35 | #define RV3029C2_RST_CTRL 0x04 | ||
36 | #define RV3029C2_CONTROL_SECTION_LEN 0x05 | ||
37 | |||
38 | /* watch section */ | ||
39 | #define RV3029C2_W_SEC 0x08 | ||
40 | #define RV3029C2_W_MINUTES 0x09 | ||
41 | #define RV3029C2_W_HOURS 0x0A | ||
42 | #define RV3029C2_REG_HR_12_24 (1<<6) /* 24h/12h mode */ | ||
43 | #define RV3029C2_REG_HR_PM (1<<5) /* PM/AM bit in 12h mode */ | ||
44 | #define RV3029C2_W_DATE 0x0B | ||
45 | #define RV3029C2_W_DAYS 0x0C | ||
46 | #define RV3029C2_W_MONTHS 0x0D | ||
47 | #define RV3029C2_W_YEARS 0x0E | ||
48 | #define RV3029C2_WATCH_SECTION_LEN 0x07 | ||
49 | |||
50 | /* alarm section */ | ||
51 | #define RV3029C2_A_SC 0x10 | ||
52 | #define RV3029C2_A_MN 0x11 | ||
53 | #define RV3029C2_A_HR 0x12 | ||
54 | #define RV3029C2_A_DT 0x13 | ||
55 | #define RV3029C2_A_DW 0x14 | ||
56 | #define RV3029C2_A_MO 0x15 | ||
57 | #define RV3029C2_A_YR 0x16 | ||
58 | #define RV3029C2_ALARM_SECTION_LEN 0x07 | ||
59 | |||
60 | /* timer section */ | ||
61 | #define RV3029C2_TIMER_LOW 0x18 | ||
62 | #define RV3029C2_TIMER_HIGH 0x19 | ||
63 | |||
64 | /* temperature section */ | ||
65 | #define RV3029C2_TEMP_PAGE 0x20 | ||
66 | |||
67 | /* eeprom data section */ | ||
68 | #define RV3029C2_E2P_EEDATA1 0x28 | ||
69 | #define RV3029C2_E2P_EEDATA2 0x29 | ||
70 | |||
71 | /* eeprom control section */ | ||
72 | #define RV3029C2_CONTROL_E2P_EECTRL 0x30 | ||
73 | #define RV3029C2_TRICKLE_1K (1<<0) /* 1K resistance */ | ||
74 | #define RV3029C2_TRICKLE_5K (1<<1) /* 5K resistance */ | ||
75 | #define RV3029C2_TRICKLE_20K (1<<2) /* 20K resistance */ | ||
76 | #define RV3029C2_TRICKLE_80K (1<<3) /* 80K resistance */ | ||
77 | #define RV3029C2_CONTROL_E2P_XTALOFFSET 0x31 | ||
78 | #define RV3029C2_CONTROL_E2P_QCOEF 0x32 | ||
79 | #define RV3029C2_CONTROL_E2P_TURNOVER 0x33 | ||
80 | |||
81 | /* user ram section */ | ||
82 | #define RV3029C2_USR1_RAM_PAGE 0x38 | ||
83 | #define RV3029C2_USR1_SECTION_LEN 0x04 | ||
84 | #define RV3029C2_USR2_RAM_PAGE 0x3C | ||
85 | #define RV3029C2_USR2_SECTION_LEN 0x04 | ||
86 | |||
87 | static int | ||
88 | rv3029c2_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf, | ||
89 | unsigned len) | ||
90 | { | ||
91 | int ret; | ||
92 | |||
93 | if ((reg > RV3029C2_USR1_RAM_PAGE + 7) || | ||
94 | (reg + len > RV3029C2_USR1_RAM_PAGE + 8)) | ||
95 | return -EINVAL; | ||
96 | |||
97 | ret = i2c_smbus_read_i2c_block_data(client, reg, len, buf); | ||
98 | if (ret < 0) | ||
99 | return ret; | ||
100 | if (ret < len) | ||
101 | return -EIO; | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static int | ||
106 | rv3029c2_i2c_write_regs(struct i2c_client *client, u8 reg, u8 const buf[], | ||
107 | unsigned len) | ||
108 | { | ||
109 | if ((reg > RV3029C2_USR1_RAM_PAGE + 7) || | ||
110 | (reg + len > RV3029C2_USR1_RAM_PAGE + 8)) | ||
111 | return -EINVAL; | ||
112 | |||
113 | return i2c_smbus_write_i2c_block_data(client, reg, len, buf); | ||
114 | } | ||
115 | |||
116 | static int | ||
117 | rv3029c2_i2c_get_sr(struct i2c_client *client, u8 *buf) | ||
118 | { | ||
119 | int ret = rv3029c2_i2c_read_regs(client, RV3029C2_STATUS, buf, 1); | ||
120 | |||
121 | if (ret < 0) | ||
122 | return -EIO; | ||
123 | dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]); | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static int | ||
128 | rv3029c2_i2c_set_sr(struct i2c_client *client, u8 val) | ||
129 | { | ||
130 | u8 buf[1]; | ||
131 | int sr; | ||
132 | |||
133 | buf[0] = val; | ||
134 | sr = rv3029c2_i2c_write_regs(client, RV3029C2_STATUS, buf, 1); | ||
135 | dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]); | ||
136 | if (sr < 0) | ||
137 | return -EIO; | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int | ||
142 | rv3029c2_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | ||
143 | { | ||
144 | u8 buf[1]; | ||
145 | int ret; | ||
146 | u8 regs[RV3029C2_WATCH_SECTION_LEN] = { 0, }; | ||
147 | |||
148 | ret = rv3029c2_i2c_get_sr(client, buf); | ||
149 | if (ret < 0) { | ||
150 | dev_err(&client->dev, "%s: reading SR failed\n", __func__); | ||
151 | return -EIO; | ||
152 | } | ||
153 | |||
154 | ret = rv3029c2_i2c_read_regs(client, RV3029C2_W_SEC , regs, | ||
155 | RV3029C2_WATCH_SECTION_LEN); | ||
156 | if (ret < 0) { | ||
157 | dev_err(&client->dev, "%s: reading RTC section failed\n", | ||
158 | __func__); | ||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | tm->tm_sec = bcd2bin(regs[RV3029C2_W_SEC-RV3029C2_W_SEC]); | ||
163 | tm->tm_min = bcd2bin(regs[RV3029C2_W_MINUTES-RV3029C2_W_SEC]); | ||
164 | |||
165 | /* HR field has a more complex interpretation */ | ||
166 | { | ||
167 | const u8 _hr = regs[RV3029C2_W_HOURS-RV3029C2_W_SEC]; | ||
168 | if (_hr & RV3029C2_REG_HR_12_24) { | ||
169 | /* 12h format */ | ||
170 | tm->tm_hour = bcd2bin(_hr & 0x1f); | ||
171 | if (_hr & RV3029C2_REG_HR_PM) /* PM flag set */ | ||
172 | tm->tm_hour += 12; | ||
173 | } else /* 24h format */ | ||
174 | tm->tm_hour = bcd2bin(_hr & 0x3f); | ||
175 | } | ||
176 | |||
177 | tm->tm_mday = bcd2bin(regs[RV3029C2_W_DATE-RV3029C2_W_SEC]); | ||
178 | tm->tm_mon = bcd2bin(regs[RV3029C2_W_MONTHS-RV3029C2_W_SEC]) - 1; | ||
179 | tm->tm_year = bcd2bin(regs[RV3029C2_W_YEARS-RV3029C2_W_SEC]) + 100; | ||
180 | tm->tm_wday = bcd2bin(regs[RV3029C2_W_DAYS-RV3029C2_W_SEC]) - 1; | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int rv3029c2_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
186 | { | ||
187 | return rv3029c2_i2c_read_time(to_i2c_client(dev), tm); | ||
188 | } | ||
189 | |||
190 | static int | ||
191 | rv3029c2_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm) | ||
192 | { | ||
193 | struct rtc_time *const tm = &alarm->time; | ||
194 | int ret; | ||
195 | u8 regs[8]; | ||
196 | |||
197 | ret = rv3029c2_i2c_get_sr(client, regs); | ||
198 | if (ret < 0) { | ||
199 | dev_err(&client->dev, "%s: reading SR failed\n", __func__); | ||
200 | return -EIO; | ||
201 | } | ||
202 | |||
203 | ret = rv3029c2_i2c_read_regs(client, RV3029C2_A_SC, regs, | ||
204 | RV3029C2_ALARM_SECTION_LEN); | ||
205 | |||
206 | if (ret < 0) { | ||
207 | dev_err(&client->dev, "%s: reading alarm section failed\n", | ||
208 | __func__); | ||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | tm->tm_sec = bcd2bin(regs[RV3029C2_A_SC-RV3029C2_A_SC] & 0x7f); | ||
213 | tm->tm_min = bcd2bin(regs[RV3029C2_A_MN-RV3029C2_A_SC] & 0x7f); | ||
214 | tm->tm_hour = bcd2bin(regs[RV3029C2_A_HR-RV3029C2_A_SC] & 0x3f); | ||
215 | tm->tm_mday = bcd2bin(regs[RV3029C2_A_DT-RV3029C2_A_SC] & 0x3f); | ||
216 | tm->tm_mon = bcd2bin(regs[RV3029C2_A_MO-RV3029C2_A_SC] & 0x1f) - 1; | ||
217 | tm->tm_year = bcd2bin(regs[RV3029C2_A_YR-RV3029C2_A_SC] & 0x7f) + 100; | ||
218 | tm->tm_wday = bcd2bin(regs[RV3029C2_A_DW-RV3029C2_A_SC] & 0x07) - 1; | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static int | ||
224 | rv3029c2_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
225 | { | ||
226 | return rv3029c2_i2c_read_alarm(to_i2c_client(dev), alarm); | ||
227 | } | ||
228 | |||
229 | static int rv3029c2_rtc_i2c_alarm_set_irq(struct i2c_client *client, | ||
230 | int enable) | ||
231 | { | ||
232 | int ret; | ||
233 | u8 buf[1]; | ||
234 | |||
235 | /* enable AIE irq */ | ||
236 | ret = rv3029c2_i2c_read_regs(client, RV3029C2_IRQ_CTRL, buf, 1); | ||
237 | if (ret < 0) { | ||
238 | dev_err(&client->dev, "can't read INT reg\n"); | ||
239 | return ret; | ||
240 | } | ||
241 | if (enable) | ||
242 | buf[0] |= RV3029C2_IRQ_CTRL_AIE; | ||
243 | else | ||
244 | buf[0] &= ~RV3029C2_IRQ_CTRL_AIE; | ||
245 | |||
246 | ret = rv3029c2_i2c_write_regs(client, RV3029C2_IRQ_CTRL, buf, 1); | ||
247 | if (ret < 0) { | ||
248 | dev_err(&client->dev, "can't set INT reg\n"); | ||
249 | return ret; | ||
250 | } | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static int rv3029c2_rtc_i2c_set_alarm(struct i2c_client *client, | ||
256 | struct rtc_wkalrm *alarm) | ||
257 | { | ||
258 | struct rtc_time *const tm = &alarm->time; | ||
259 | int ret; | ||
260 | u8 regs[8]; | ||
261 | |||
262 | /* | ||
263 | * The clock has an 8 bit wide bcd-coded register (they never learn) | ||
264 | * for the year. tm_year is an offset from 1900 and we are interested | ||
265 | * in the 2000-2099 range, so any value less than 100 is invalid. | ||
266 | */ | ||
267 | if (tm->tm_year < 100) | ||
268 | return -EINVAL; | ||
269 | |||
270 | ret = rv3029c2_i2c_get_sr(client, regs); | ||
271 | if (ret < 0) { | ||
272 | dev_err(&client->dev, "%s: reading SR failed\n", __func__); | ||
273 | return -EIO; | ||
274 | } | ||
275 | regs[RV3029C2_A_SC-RV3029C2_A_SC] = bin2bcd(tm->tm_sec & 0x7f); | ||
276 | regs[RV3029C2_A_MN-RV3029C2_A_SC] = bin2bcd(tm->tm_min & 0x7f); | ||
277 | regs[RV3029C2_A_HR-RV3029C2_A_SC] = bin2bcd(tm->tm_hour & 0x3f); | ||
278 | regs[RV3029C2_A_DT-RV3029C2_A_SC] = bin2bcd(tm->tm_mday & 0x3f); | ||
279 | regs[RV3029C2_A_MO-RV3029C2_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1); | ||
280 | regs[RV3029C2_A_DW-RV3029C2_A_SC] = bin2bcd((tm->tm_wday & 7) - 1); | ||
281 | regs[RV3029C2_A_YR-RV3029C2_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100); | ||
282 | |||
283 | ret = rv3029c2_i2c_write_regs(client, RV3029C2_A_SC, regs, | ||
284 | RV3029C2_ALARM_SECTION_LEN); | ||
285 | if (ret < 0) | ||
286 | return ret; | ||
287 | |||
288 | if (alarm->enabled) { | ||
289 | u8 buf[1]; | ||
290 | |||
291 | /* clear AF flag */ | ||
292 | ret = rv3029c2_i2c_read_regs(client, RV3029C2_IRQ_FLAGS, | ||
293 | buf, 1); | ||
294 | if (ret < 0) { | ||
295 | dev_err(&client->dev, "can't read alarm flag\n"); | ||
296 | return ret; | ||
297 | } | ||
298 | buf[0] &= ~RV3029C2_IRQ_FLAGS_AF; | ||
299 | ret = rv3029c2_i2c_write_regs(client, RV3029C2_IRQ_FLAGS, | ||
300 | buf, 1); | ||
301 | if (ret < 0) { | ||
302 | dev_err(&client->dev, "can't set alarm flag\n"); | ||
303 | return ret; | ||
304 | } | ||
305 | /* enable AIE irq */ | ||
306 | ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 1); | ||
307 | if (ret) | ||
308 | return ret; | ||
309 | |||
310 | dev_dbg(&client->dev, "alarm IRQ armed\n"); | ||
311 | } else { | ||
312 | /* disable AIE irq */ | ||
313 | ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 1); | ||
314 | if (ret) | ||
315 | return ret; | ||
316 | |||
317 | dev_dbg(&client->dev, "alarm IRQ disabled\n"); | ||
318 | } | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static int rv3029c2_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
324 | { | ||
325 | return rv3029c2_rtc_i2c_set_alarm(to_i2c_client(dev), alarm); | ||
326 | } | ||
327 | |||
328 | static int | ||
329 | rv3029c2_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) | ||
330 | { | ||
331 | u8 regs[8]; | ||
332 | int ret; | ||
333 | |||
334 | /* | ||
335 | * The clock has an 8 bit wide bcd-coded register (they never learn) | ||
336 | * for the year. tm_year is an offset from 1900 and we are interested | ||
337 | * in the 2000-2099 range, so any value less than 100 is invalid. | ||
338 | */ | ||
339 | if (tm->tm_year < 100) | ||
340 | return -EINVAL; | ||
341 | |||
342 | regs[RV3029C2_W_SEC-RV3029C2_W_SEC] = bin2bcd(tm->tm_sec); | ||
343 | regs[RV3029C2_W_MINUTES-RV3029C2_W_SEC] = bin2bcd(tm->tm_min); | ||
344 | regs[RV3029C2_W_HOURS-RV3029C2_W_SEC] = bin2bcd(tm->tm_hour); | ||
345 | regs[RV3029C2_W_DATE-RV3029C2_W_SEC] = bin2bcd(tm->tm_mday); | ||
346 | regs[RV3029C2_W_MONTHS-RV3029C2_W_SEC] = bin2bcd(tm->tm_mon+1); | ||
347 | regs[RV3029C2_W_DAYS-RV3029C2_W_SEC] = bin2bcd((tm->tm_wday & 7)+1); | ||
348 | regs[RV3029C2_W_YEARS-RV3029C2_W_SEC] = bin2bcd(tm->tm_year - 100); | ||
349 | |||
350 | ret = rv3029c2_i2c_write_regs(client, RV3029C2_W_SEC, regs, | ||
351 | RV3029C2_WATCH_SECTION_LEN); | ||
352 | if (ret < 0) | ||
353 | return ret; | ||
354 | |||
355 | ret = rv3029c2_i2c_get_sr(client, regs); | ||
356 | if (ret < 0) { | ||
357 | dev_err(&client->dev, "%s: reading SR failed\n", __func__); | ||
358 | return ret; | ||
359 | } | ||
360 | /* clear PON bit */ | ||
361 | ret = rv3029c2_i2c_set_sr(client, (regs[0] & ~RV3029C2_STATUS_PON)); | ||
362 | if (ret < 0) { | ||
363 | dev_err(&client->dev, "%s: reading SR failed\n", __func__); | ||
364 | return ret; | ||
365 | } | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int rv3029c2_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
371 | { | ||
372 | return rv3029c2_i2c_set_time(to_i2c_client(dev), tm); | ||
373 | } | ||
374 | |||
375 | static const struct rtc_class_ops rv3029c2_rtc_ops = { | ||
376 | .read_time = rv3029c2_rtc_read_time, | ||
377 | .set_time = rv3029c2_rtc_set_time, | ||
378 | .read_alarm = rv3029c2_rtc_read_alarm, | ||
379 | .set_alarm = rv3029c2_rtc_set_alarm, | ||
380 | }; | ||
381 | |||
382 | static struct i2c_device_id rv3029c2_id[] = { | ||
383 | { "rv3029c2", 0 }, | ||
384 | { } | ||
385 | }; | ||
386 | MODULE_DEVICE_TABLE(i2c, rv3029c2_id); | ||
387 | |||
388 | static int __devinit | ||
389 | rv3029c2_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
390 | { | ||
391 | struct rtc_device *rtc; | ||
392 | int rc = 0; | ||
393 | u8 buf[1]; | ||
394 | |||
395 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL)) | ||
396 | return -ENODEV; | ||
397 | |||
398 | rtc = rtc_device_register(client->name, | ||
399 | &client->dev, &rv3029c2_rtc_ops, | ||
400 | THIS_MODULE); | ||
401 | |||
402 | if (IS_ERR(rtc)) | ||
403 | return PTR_ERR(rtc); | ||
404 | |||
405 | i2c_set_clientdata(client, rtc); | ||
406 | |||
407 | rc = rv3029c2_i2c_get_sr(client, buf); | ||
408 | if (rc < 0) { | ||
409 | dev_err(&client->dev, "reading status failed\n"); | ||
410 | goto exit_unregister; | ||
411 | } | ||
412 | |||
413 | return 0; | ||
414 | |||
415 | exit_unregister: | ||
416 | rtc_device_unregister(rtc); | ||
417 | |||
418 | return rc; | ||
419 | } | ||
420 | |||
421 | static int __devexit rv3029c2_remove(struct i2c_client *client) | ||
422 | { | ||
423 | struct rtc_device *rtc = i2c_get_clientdata(client); | ||
424 | |||
425 | rtc_device_unregister(rtc); | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static struct i2c_driver rv3029c2_driver = { | ||
431 | .driver = { | ||
432 | .name = "rtc-rv3029c2", | ||
433 | }, | ||
434 | .probe = rv3029c2_probe, | ||
435 | .remove = __devexit_p(rv3029c2_remove), | ||
436 | .id_table = rv3029c2_id, | ||
437 | }; | ||
438 | |||
439 | static int __init rv3029c2_init(void) | ||
440 | { | ||
441 | return i2c_add_driver(&rv3029c2_driver); | ||
442 | } | ||
443 | |||
444 | static void __exit rv3029c2_exit(void) | ||
445 | { | ||
446 | i2c_del_driver(&rv3029c2_driver); | ||
447 | } | ||
448 | |||
449 | module_init(rv3029c2_init); | ||
450 | module_exit(rv3029c2_exit); | ||
451 | |||
452 | MODULE_AUTHOR("Gregory Hermant <gregory.hermant@calao-systems.com>"); | ||
453 | MODULE_DESCRIPTION("Micro Crystal RV3029C2 RTC driver"); | ||
454 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c new file mode 100644 index 000000000000..893bac2bb21b --- /dev/null +++ b/drivers/rtc/rtc-spear.c | |||
@@ -0,0 +1,534 @@ | |||
1 | /* | ||
2 | * drivers/rtc/rtc-spear.c | ||
3 | * | ||
4 | * Copyright (C) 2010 ST Microelectronics | ||
5 | * Rajeev Kumar<rajeev-dlh.kumar@st.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/bcd.h> | ||
13 | #include <linux/clk.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/rtc.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | |||
24 | /* RTC registers */ | ||
25 | #define TIME_REG 0x00 | ||
26 | #define DATE_REG 0x04 | ||
27 | #define ALARM_TIME_REG 0x08 | ||
28 | #define ALARM_DATE_REG 0x0C | ||
29 | #define CTRL_REG 0x10 | ||
30 | #define STATUS_REG 0x14 | ||
31 | |||
32 | /* TIME_REG & ALARM_TIME_REG */ | ||
33 | #define SECONDS_UNITS (0xf<<0) /* seconds units position */ | ||
34 | #define SECONDS_TENS (0x7<<4) /* seconds tens position */ | ||
35 | #define MINUTES_UNITS (0xf<<8) /* minutes units position */ | ||
36 | #define MINUTES_TENS (0x7<<12) /* minutes tens position */ | ||
37 | #define HOURS_UNITS (0xf<<16) /* hours units position */ | ||
38 | #define HOURS_TENS (0x3<<20) /* hours tens position */ | ||
39 | |||
40 | /* DATE_REG & ALARM_DATE_REG */ | ||
41 | #define DAYS_UNITS (0xf<<0) /* days units position */ | ||
42 | #define DAYS_TENS (0x3<<4) /* days tens position */ | ||
43 | #define MONTHS_UNITS (0xf<<8) /* months units position */ | ||
44 | #define MONTHS_TENS (0x1<<12) /* months tens position */ | ||
45 | #define YEARS_UNITS (0xf<<16) /* years units position */ | ||
46 | #define YEARS_TENS (0xf<<20) /* years tens position */ | ||
47 | #define YEARS_HUNDREDS (0xf<<24) /* years hundereds position */ | ||
48 | #define YEARS_MILLENIUMS (0xf<<28) /* years millenium position */ | ||
49 | |||
50 | /* MASK SHIFT TIME_REG & ALARM_TIME_REG*/ | ||
51 | #define SECOND_SHIFT 0x00 /* seconds units */ | ||
52 | #define MINUTE_SHIFT 0x08 /* minutes units position */ | ||
53 | #define HOUR_SHIFT 0x10 /* hours units position */ | ||
54 | #define MDAY_SHIFT 0x00 /* Month day shift */ | ||
55 | #define MONTH_SHIFT 0x08 /* Month shift */ | ||
56 | #define YEAR_SHIFT 0x10 /* Year shift */ | ||
57 | |||
58 | #define SECOND_MASK 0x7F | ||
59 | #define MIN_MASK 0x7F | ||
60 | #define HOUR_MASK 0x3F | ||
61 | #define DAY_MASK 0x3F | ||
62 | #define MONTH_MASK 0x7F | ||
63 | #define YEAR_MASK 0xFFFF | ||
64 | |||
65 | /* date reg equal to time reg, for debug only */ | ||
66 | #define TIME_BYP (1<<9) | ||
67 | #define INT_ENABLE (1<<31) /* interrupt enable */ | ||
68 | |||
69 | /* STATUS_REG */ | ||
70 | #define CLK_UNCONNECTED (1<<0) | ||
71 | #define PEND_WR_TIME (1<<2) | ||
72 | #define PEND_WR_DATE (1<<3) | ||
73 | #define LOST_WR_TIME (1<<4) | ||
74 | #define LOST_WR_DATE (1<<5) | ||
75 | #define RTC_INT_MASK (1<<31) | ||
76 | #define STATUS_BUSY (PEND_WR_TIME | PEND_WR_DATE) | ||
77 | #define STATUS_FAIL (LOST_WR_TIME | LOST_WR_DATE) | ||
78 | |||
79 | struct spear_rtc_config { | ||
80 | struct clk *clk; | ||
81 | spinlock_t lock; | ||
82 | void __iomem *ioaddr; | ||
83 | }; | ||
84 | |||
85 | static inline void spear_rtc_clear_interrupt(struct spear_rtc_config *config) | ||
86 | { | ||
87 | unsigned int val; | ||
88 | unsigned long flags; | ||
89 | |||
90 | spin_lock_irqsave(&config->lock, flags); | ||
91 | val = readl(config->ioaddr + STATUS_REG); | ||
92 | val |= RTC_INT_MASK; | ||
93 | writel(val, config->ioaddr + STATUS_REG); | ||
94 | spin_unlock_irqrestore(&config->lock, flags); | ||
95 | } | ||
96 | |||
97 | static inline void spear_rtc_enable_interrupt(struct spear_rtc_config *config) | ||
98 | { | ||
99 | unsigned int val; | ||
100 | |||
101 | val = readl(config->ioaddr + CTRL_REG); | ||
102 | if (!(val & INT_ENABLE)) { | ||
103 | spear_rtc_clear_interrupt(config); | ||
104 | val |= INT_ENABLE; | ||
105 | writel(val, config->ioaddr + CTRL_REG); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static inline void spear_rtc_disable_interrupt(struct spear_rtc_config *config) | ||
110 | { | ||
111 | unsigned int val; | ||
112 | |||
113 | val = readl(config->ioaddr + CTRL_REG); | ||
114 | if (val & INT_ENABLE) { | ||
115 | val &= ~INT_ENABLE; | ||
116 | writel(val, config->ioaddr + CTRL_REG); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | static inline int is_write_complete(struct spear_rtc_config *config) | ||
121 | { | ||
122 | int ret = 0; | ||
123 | unsigned long flags; | ||
124 | |||
125 | spin_lock_irqsave(&config->lock, flags); | ||
126 | if ((readl(config->ioaddr + STATUS_REG)) & STATUS_FAIL) | ||
127 | ret = -EIO; | ||
128 | spin_unlock_irqrestore(&config->lock, flags); | ||
129 | |||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | static void rtc_wait_not_busy(struct spear_rtc_config *config) | ||
134 | { | ||
135 | int status, count = 0; | ||
136 | unsigned long flags; | ||
137 | |||
138 | /* Assuming BUSY may stay active for 80 msec) */ | ||
139 | for (count = 0; count < 80; count++) { | ||
140 | spin_lock_irqsave(&config->lock, flags); | ||
141 | status = readl(config->ioaddr + STATUS_REG); | ||
142 | spin_unlock_irqrestore(&config->lock, flags); | ||
143 | if ((status & STATUS_BUSY) == 0) | ||
144 | break; | ||
145 | /* check status busy, after each msec */ | ||
146 | msleep(1); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static irqreturn_t spear_rtc_irq(int irq, void *dev_id) | ||
151 | { | ||
152 | struct rtc_device *rtc = (struct rtc_device *)dev_id; | ||
153 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
154 | unsigned long flags, events = 0; | ||
155 | unsigned int irq_data; | ||
156 | |||
157 | spin_lock_irqsave(&config->lock, flags); | ||
158 | irq_data = readl(config->ioaddr + STATUS_REG); | ||
159 | spin_unlock_irqrestore(&config->lock, flags); | ||
160 | |||
161 | if ((irq_data & RTC_INT_MASK)) { | ||
162 | spear_rtc_clear_interrupt(config); | ||
163 | events = RTC_IRQF | RTC_AF; | ||
164 | rtc_update_irq(rtc, 1, events); | ||
165 | return IRQ_HANDLED; | ||
166 | } else | ||
167 | return IRQ_NONE; | ||
168 | |||
169 | } | ||
170 | |||
171 | static int tm2bcd(struct rtc_time *tm) | ||
172 | { | ||
173 | if (rtc_valid_tm(tm) != 0) | ||
174 | return -EINVAL; | ||
175 | tm->tm_sec = bin2bcd(tm->tm_sec); | ||
176 | tm->tm_min = bin2bcd(tm->tm_min); | ||
177 | tm->tm_hour = bin2bcd(tm->tm_hour); | ||
178 | tm->tm_mday = bin2bcd(tm->tm_mday); | ||
179 | tm->tm_mon = bin2bcd(tm->tm_mon + 1); | ||
180 | tm->tm_year = bin2bcd(tm->tm_year); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static void bcd2tm(struct rtc_time *tm) | ||
186 | { | ||
187 | tm->tm_sec = bcd2bin(tm->tm_sec); | ||
188 | tm->tm_min = bcd2bin(tm->tm_min); | ||
189 | tm->tm_hour = bcd2bin(tm->tm_hour); | ||
190 | tm->tm_mday = bcd2bin(tm->tm_mday); | ||
191 | tm->tm_mon = bcd2bin(tm->tm_mon) - 1; | ||
192 | /* epoch == 1900 */ | ||
193 | tm->tm_year = bcd2bin(tm->tm_year); | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * spear_rtc_read_time - set the time | ||
198 | * @dev: rtc device in use | ||
199 | * @tm: holds date and time | ||
200 | * | ||
201 | * This function read time and date. On success it will return 0 | ||
202 | * otherwise -ve error is returned. | ||
203 | */ | ||
204 | static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
205 | { | ||
206 | struct platform_device *pdev = to_platform_device(dev); | ||
207 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
208 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
209 | unsigned int time, date; | ||
210 | |||
211 | /* we don't report wday/yday/isdst ... */ | ||
212 | rtc_wait_not_busy(config); | ||
213 | |||
214 | time = readl(config->ioaddr + TIME_REG); | ||
215 | date = readl(config->ioaddr + DATE_REG); | ||
216 | tm->tm_sec = (time >> SECOND_SHIFT) & SECOND_MASK; | ||
217 | tm->tm_min = (time >> MINUTE_SHIFT) & MIN_MASK; | ||
218 | tm->tm_hour = (time >> HOUR_SHIFT) & HOUR_MASK; | ||
219 | tm->tm_mday = (date >> MDAY_SHIFT) & DAY_MASK; | ||
220 | tm->tm_mon = (date >> MONTH_SHIFT) & MONTH_MASK; | ||
221 | tm->tm_year = (date >> YEAR_SHIFT) & YEAR_MASK; | ||
222 | |||
223 | bcd2tm(tm); | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | /* | ||
228 | * spear_rtc_set_time - set the time | ||
229 | * @dev: rtc device in use | ||
230 | * @tm: holds date and time | ||
231 | * | ||
232 | * This function set time and date. On success it will return 0 | ||
233 | * otherwise -ve error is returned. | ||
234 | */ | ||
235 | static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
236 | { | ||
237 | struct platform_device *pdev = to_platform_device(dev); | ||
238 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
239 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
240 | unsigned int time, date, err = 0; | ||
241 | |||
242 | if (tm2bcd(tm) < 0) | ||
243 | return -EINVAL; | ||
244 | |||
245 | rtc_wait_not_busy(config); | ||
246 | time = (tm->tm_sec << SECOND_SHIFT) | (tm->tm_min << MINUTE_SHIFT) | | ||
247 | (tm->tm_hour << HOUR_SHIFT); | ||
248 | date = (tm->tm_mday << MDAY_SHIFT) | (tm->tm_mon << MONTH_SHIFT) | | ||
249 | (tm->tm_year << YEAR_SHIFT); | ||
250 | writel(time, config->ioaddr + TIME_REG); | ||
251 | writel(date, config->ioaddr + DATE_REG); | ||
252 | err = is_write_complete(config); | ||
253 | if (err < 0) | ||
254 | return err; | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * spear_rtc_read_alarm - read the alarm time | ||
261 | * @dev: rtc device in use | ||
262 | * @alm: holds alarm date and time | ||
263 | * | ||
264 | * This function read alarm time and date. On success it will return 0 | ||
265 | * otherwise -ve error is returned. | ||
266 | */ | ||
267 | static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
268 | { | ||
269 | struct platform_device *pdev = to_platform_device(dev); | ||
270 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
271 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
272 | unsigned int time, date; | ||
273 | |||
274 | rtc_wait_not_busy(config); | ||
275 | |||
276 | time = readl(config->ioaddr + ALARM_TIME_REG); | ||
277 | date = readl(config->ioaddr + ALARM_DATE_REG); | ||
278 | alm->time.tm_sec = (time >> SECOND_SHIFT) & SECOND_MASK; | ||
279 | alm->time.tm_min = (time >> MINUTE_SHIFT) & MIN_MASK; | ||
280 | alm->time.tm_hour = (time >> HOUR_SHIFT) & HOUR_MASK; | ||
281 | alm->time.tm_mday = (date >> MDAY_SHIFT) & DAY_MASK; | ||
282 | alm->time.tm_mon = (date >> MONTH_SHIFT) & MONTH_MASK; | ||
283 | alm->time.tm_year = (date >> YEAR_SHIFT) & YEAR_MASK; | ||
284 | |||
285 | bcd2tm(&alm->time); | ||
286 | alm->enabled = readl(config->ioaddr + CTRL_REG) & INT_ENABLE; | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * spear_rtc_set_alarm - set the alarm time | ||
293 | * @dev: rtc device in use | ||
294 | * @alm: holds alarm date and time | ||
295 | * | ||
296 | * This function set alarm time and date. On success it will return 0 | ||
297 | * otherwise -ve error is returned. | ||
298 | */ | ||
299 | static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
300 | { | ||
301 | struct platform_device *pdev = to_platform_device(dev); | ||
302 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
303 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
304 | unsigned int time, date, err = 0; | ||
305 | |||
306 | if (tm2bcd(&alm->time) < 0) | ||
307 | return -EINVAL; | ||
308 | |||
309 | rtc_wait_not_busy(config); | ||
310 | |||
311 | time = (alm->time.tm_sec << SECOND_SHIFT) | (alm->time.tm_min << | ||
312 | MINUTE_SHIFT) | (alm->time.tm_hour << HOUR_SHIFT); | ||
313 | date = (alm->time.tm_mday << MDAY_SHIFT) | (alm->time.tm_mon << | ||
314 | MONTH_SHIFT) | (alm->time.tm_year << YEAR_SHIFT); | ||
315 | |||
316 | writel(time, config->ioaddr + ALARM_TIME_REG); | ||
317 | writel(date, config->ioaddr + ALARM_DATE_REG); | ||
318 | err = is_write_complete(config); | ||
319 | if (err < 0) | ||
320 | return err; | ||
321 | |||
322 | if (alm->enabled) | ||
323 | spear_rtc_enable_interrupt(config); | ||
324 | else | ||
325 | spear_rtc_disable_interrupt(config); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | static struct rtc_class_ops spear_rtc_ops = { | ||
330 | .read_time = spear_rtc_read_time, | ||
331 | .set_time = spear_rtc_set_time, | ||
332 | .read_alarm = spear_rtc_read_alarm, | ||
333 | .set_alarm = spear_rtc_set_alarm, | ||
334 | }; | ||
335 | |||
336 | static int __devinit spear_rtc_probe(struct platform_device *pdev) | ||
337 | { | ||
338 | struct resource *res; | ||
339 | struct rtc_device *rtc; | ||
340 | struct spear_rtc_config *config; | ||
341 | unsigned int status = 0; | ||
342 | int irq; | ||
343 | |||
344 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
345 | if (!res) { | ||
346 | dev_err(&pdev->dev, "no resource defined\n"); | ||
347 | return -EBUSY; | ||
348 | } | ||
349 | if (!request_mem_region(res->start, resource_size(res), pdev->name)) { | ||
350 | dev_err(&pdev->dev, "rtc region already claimed\n"); | ||
351 | return -EBUSY; | ||
352 | } | ||
353 | |||
354 | config = kzalloc(sizeof(*config), GFP_KERNEL); | ||
355 | if (!config) { | ||
356 | dev_err(&pdev->dev, "out of memory\n"); | ||
357 | status = -ENOMEM; | ||
358 | goto err_release_region; | ||
359 | } | ||
360 | |||
361 | config->clk = clk_get(&pdev->dev, NULL); | ||
362 | if (IS_ERR(config->clk)) { | ||
363 | status = PTR_ERR(config->clk); | ||
364 | goto err_kfree; | ||
365 | } | ||
366 | |||
367 | status = clk_enable(config->clk); | ||
368 | if (status < 0) | ||
369 | goto err_clk_put; | ||
370 | |||
371 | config->ioaddr = ioremap(res->start, resource_size(res)); | ||
372 | if (!config->ioaddr) { | ||
373 | dev_err(&pdev->dev, "ioremap fail\n"); | ||
374 | status = -ENOMEM; | ||
375 | goto err_disable_clock; | ||
376 | } | ||
377 | |||
378 | spin_lock_init(&config->lock); | ||
379 | |||
380 | rtc = rtc_device_register(pdev->name, &pdev->dev, &spear_rtc_ops, | ||
381 | THIS_MODULE); | ||
382 | if (IS_ERR(rtc)) { | ||
383 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | ||
384 | PTR_ERR(rtc)); | ||
385 | status = PTR_ERR(rtc); | ||
386 | goto err_iounmap; | ||
387 | } | ||
388 | |||
389 | platform_set_drvdata(pdev, rtc); | ||
390 | dev_set_drvdata(&rtc->dev, config); | ||
391 | |||
392 | /* alarm irqs */ | ||
393 | irq = platform_get_irq(pdev, 0); | ||
394 | if (irq < 0) { | ||
395 | dev_err(&pdev->dev, "no update irq?\n"); | ||
396 | status = irq; | ||
397 | goto err_clear_platdata; | ||
398 | } | ||
399 | |||
400 | status = request_irq(irq, spear_rtc_irq, 0, pdev->name, rtc); | ||
401 | if (status) { | ||
402 | dev_err(&pdev->dev, "Alarm interrupt IRQ%d already \ | ||
403 | claimed\n", irq); | ||
404 | goto err_clear_platdata; | ||
405 | } | ||
406 | |||
407 | if (!device_can_wakeup(&pdev->dev)) | ||
408 | device_init_wakeup(&pdev->dev, 1); | ||
409 | |||
410 | return 0; | ||
411 | |||
412 | err_clear_platdata: | ||
413 | platform_set_drvdata(pdev, NULL); | ||
414 | dev_set_drvdata(&rtc->dev, NULL); | ||
415 | rtc_device_unregister(rtc); | ||
416 | err_iounmap: | ||
417 | iounmap(config->ioaddr); | ||
418 | err_disable_clock: | ||
419 | clk_disable(config->clk); | ||
420 | err_clk_put: | ||
421 | clk_put(config->clk); | ||
422 | err_kfree: | ||
423 | kfree(config); | ||
424 | err_release_region: | ||
425 | release_mem_region(res->start, resource_size(res)); | ||
426 | |||
427 | return status; | ||
428 | } | ||
429 | |||
430 | static int __devexit spear_rtc_remove(struct platform_device *pdev) | ||
431 | { | ||
432 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
433 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
434 | int irq; | ||
435 | struct resource *res; | ||
436 | |||
437 | /* leave rtc running, but disable irqs */ | ||
438 | spear_rtc_disable_interrupt(config); | ||
439 | device_init_wakeup(&pdev->dev, 0); | ||
440 | irq = platform_get_irq(pdev, 0); | ||
441 | if (irq) | ||
442 | free_irq(irq, pdev); | ||
443 | clk_disable(config->clk); | ||
444 | clk_put(config->clk); | ||
445 | iounmap(config->ioaddr); | ||
446 | kfree(config); | ||
447 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
448 | if (res) | ||
449 | release_mem_region(res->start, resource_size(res)); | ||
450 | platform_set_drvdata(pdev, NULL); | ||
451 | dev_set_drvdata(&rtc->dev, NULL); | ||
452 | rtc_device_unregister(rtc); | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | #ifdef CONFIG_PM | ||
458 | |||
459 | static int spear_rtc_suspend(struct platform_device *pdev, pm_message_t state) | ||
460 | { | ||
461 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
462 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
463 | int irq; | ||
464 | |||
465 | irq = platform_get_irq(pdev, 0); | ||
466 | if (device_may_wakeup(&pdev->dev)) | ||
467 | enable_irq_wake(irq); | ||
468 | else { | ||
469 | spear_rtc_disable_interrupt(config); | ||
470 | clk_disable(config->clk); | ||
471 | } | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static int spear_rtc_resume(struct platform_device *pdev) | ||
477 | { | ||
478 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
479 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
480 | int irq; | ||
481 | |||
482 | irq = platform_get_irq(pdev, 0); | ||
483 | |||
484 | if (device_may_wakeup(&pdev->dev)) | ||
485 | disable_irq_wake(irq); | ||
486 | else { | ||
487 | clk_enable(config->clk); | ||
488 | spear_rtc_enable_interrupt(config); | ||
489 | } | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | #else | ||
495 | #define spear_rtc_suspend NULL | ||
496 | #define spear_rtc_resume NULL | ||
497 | #endif | ||
498 | |||
499 | static void spear_rtc_shutdown(struct platform_device *pdev) | ||
500 | { | ||
501 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
502 | struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev); | ||
503 | |||
504 | spear_rtc_disable_interrupt(config); | ||
505 | clk_disable(config->clk); | ||
506 | } | ||
507 | |||
508 | static struct platform_driver spear_rtc_driver = { | ||
509 | .probe = spear_rtc_probe, | ||
510 | .remove = __devexit_p(spear_rtc_remove), | ||
511 | .suspend = spear_rtc_suspend, | ||
512 | .resume = spear_rtc_resume, | ||
513 | .shutdown = spear_rtc_shutdown, | ||
514 | .driver = { | ||
515 | .name = "rtc-spear", | ||
516 | }, | ||
517 | }; | ||
518 | |||
519 | static int __init rtc_init(void) | ||
520 | { | ||
521 | return platform_driver_register(&spear_rtc_driver); | ||
522 | } | ||
523 | module_init(rtc_init); | ||
524 | |||
525 | static void __exit rtc_exit(void) | ||
526 | { | ||
527 | platform_driver_unregister(&spear_rtc_driver); | ||
528 | } | ||
529 | module_exit(rtc_exit); | ||
530 | |||
531 | MODULE_ALIAS("platform:rtc-spear"); | ||
532 | MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>"); | ||
533 | MODULE_DESCRIPTION("ST SPEAr Realtime Clock Driver (RTC)"); | ||
534 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c new file mode 100644 index 000000000000..b8bc862903ae --- /dev/null +++ b/drivers/rtc/rtc-vt8500.c | |||
@@ -0,0 +1,366 @@ | |||
1 | /* | ||
2 | * drivers/rtc/rtc-vt8500.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> | ||
5 | * | ||
6 | * Based on rtc-pxa.c | ||
7 | * | ||
8 | * This software is licensed under the terms of the GNU General Public | ||
9 | * License version 2, as published by the Free Software Foundation, and | ||
10 | * may be copied, distributed, and modified under those terms. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <linux/bcd.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | /* | ||
28 | * Register definitions | ||
29 | */ | ||
30 | #define VT8500_RTC_TS 0x00 /* Time set */ | ||
31 | #define VT8500_RTC_DS 0x04 /* Date set */ | ||
32 | #define VT8500_RTC_AS 0x08 /* Alarm set */ | ||
33 | #define VT8500_RTC_CR 0x0c /* Control */ | ||
34 | #define VT8500_RTC_TR 0x10 /* Time read */ | ||
35 | #define VT8500_RTC_DR 0x14 /* Date read */ | ||
36 | #define VT8500_RTC_WS 0x18 /* Write status */ | ||
37 | #define VT8500_RTC_CL 0x20 /* Calibration */ | ||
38 | #define VT8500_RTC_IS 0x24 /* Interrupt status */ | ||
39 | #define VT8500_RTC_ST 0x28 /* Status */ | ||
40 | |||
41 | #define INVALID_TIME_BIT (1 << 31) | ||
42 | |||
43 | #define DATE_CENTURY_S 19 | ||
44 | #define DATE_YEAR_S 11 | ||
45 | #define DATE_YEAR_MASK (0xff << DATE_YEAR_S) | ||
46 | #define DATE_MONTH_S 6 | ||
47 | #define DATE_MONTH_MASK (0x1f << DATE_MONTH_S) | ||
48 | #define DATE_DAY_MASK 0x3f | ||
49 | |||
50 | #define TIME_DOW_S 20 | ||
51 | #define TIME_DOW_MASK (0x07 << TIME_DOW_S) | ||
52 | #define TIME_HOUR_S 14 | ||
53 | #define TIME_HOUR_MASK (0x3f << TIME_HOUR_S) | ||
54 | #define TIME_MIN_S 7 | ||
55 | #define TIME_MIN_MASK (0x7f << TIME_MIN_S) | ||
56 | #define TIME_SEC_MASK 0x7f | ||
57 | |||
58 | #define ALARM_DAY_S 20 | ||
59 | #define ALARM_DAY_MASK (0x3f << ALARM_DAY_S) | ||
60 | |||
61 | #define ALARM_DAY_BIT (1 << 29) | ||
62 | #define ALARM_HOUR_BIT (1 << 28) | ||
63 | #define ALARM_MIN_BIT (1 << 27) | ||
64 | #define ALARM_SEC_BIT (1 << 26) | ||
65 | |||
66 | #define ALARM_ENABLE_MASK (ALARM_DAY_BIT \ | ||
67 | | ALARM_HOUR_BIT \ | ||
68 | | ALARM_MIN_BIT \ | ||
69 | | ALARM_SEC_BIT) | ||
70 | |||
71 | #define VT8500_RTC_CR_ENABLE (1 << 0) /* Enable RTC */ | ||
72 | #define VT8500_RTC_CR_24H (1 << 1) /* 24h time format */ | ||
73 | #define VT8500_RTC_CR_SM_ENABLE (1 << 2) /* Enable periodic irqs */ | ||
74 | #define VT8500_RTC_CR_SM_SEC (1 << 3) /* 0: 1Hz/60, 1: 1Hz */ | ||
75 | #define VT8500_RTC_CR_CALIB (1 << 4) /* Enable calibration */ | ||
76 | |||
77 | struct vt8500_rtc { | ||
78 | void __iomem *regbase; | ||
79 | struct resource *res; | ||
80 | int irq_alarm; | ||
81 | int irq_hz; | ||
82 | struct rtc_device *rtc; | ||
83 | spinlock_t lock; /* Protects this structure */ | ||
84 | }; | ||
85 | |||
86 | static irqreturn_t vt8500_rtc_irq(int irq, void *dev_id) | ||
87 | { | ||
88 | struct vt8500_rtc *vt8500_rtc = dev_id; | ||
89 | u32 isr; | ||
90 | unsigned long events = 0; | ||
91 | |||
92 | spin_lock(&vt8500_rtc->lock); | ||
93 | |||
94 | /* clear interrupt sources */ | ||
95 | isr = readl(vt8500_rtc->regbase + VT8500_RTC_IS); | ||
96 | writel(isr, vt8500_rtc->regbase + VT8500_RTC_IS); | ||
97 | |||
98 | spin_unlock(&vt8500_rtc->lock); | ||
99 | |||
100 | if (isr & 1) | ||
101 | events |= RTC_AF | RTC_IRQF; | ||
102 | |||
103 | /* Only second/minute interrupts are supported */ | ||
104 | if (isr & 2) | ||
105 | events |= RTC_UF | RTC_IRQF; | ||
106 | |||
107 | rtc_update_irq(vt8500_rtc->rtc, 1, events); | ||
108 | |||
109 | return IRQ_HANDLED; | ||
110 | } | ||
111 | |||
112 | static int vt8500_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
113 | { | ||
114 | struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); | ||
115 | u32 date, time; | ||
116 | |||
117 | date = readl(vt8500_rtc->regbase + VT8500_RTC_DR); | ||
118 | time = readl(vt8500_rtc->regbase + VT8500_RTC_TR); | ||
119 | |||
120 | tm->tm_sec = bcd2bin(time & TIME_SEC_MASK); | ||
121 | tm->tm_min = bcd2bin((time & TIME_MIN_MASK) >> TIME_MIN_S); | ||
122 | tm->tm_hour = bcd2bin((time & TIME_HOUR_MASK) >> TIME_HOUR_S); | ||
123 | tm->tm_mday = bcd2bin(date & DATE_DAY_MASK); | ||
124 | tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S); | ||
125 | tm->tm_year = bcd2bin((date & DATE_YEAR_MASK) >> DATE_YEAR_S) | ||
126 | + ((date >> DATE_CENTURY_S) & 1 ? 200 : 100); | ||
127 | tm->tm_wday = (time & TIME_DOW_MASK) >> TIME_DOW_S; | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
133 | { | ||
134 | struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); | ||
135 | |||
136 | if (tm->tm_year < 100) { | ||
137 | dev_warn(dev, "Only years 2000-2199 are supported by the " | ||
138 | "hardware!\n"); | ||
139 | return -EINVAL; | ||
140 | } | ||
141 | |||
142 | writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S) | ||
143 | | (bin2bcd(tm->tm_mon) << DATE_MONTH_S) | ||
144 | | (bin2bcd(tm->tm_mday)), | ||
145 | vt8500_rtc->regbase + VT8500_RTC_DS); | ||
146 | writel((bin2bcd(tm->tm_wday) << TIME_DOW_S) | ||
147 | | (bin2bcd(tm->tm_hour) << TIME_HOUR_S) | ||
148 | | (bin2bcd(tm->tm_min) << TIME_MIN_S) | ||
149 | | (bin2bcd(tm->tm_sec)), | ||
150 | vt8500_rtc->regbase + VT8500_RTC_TS); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int vt8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
156 | { | ||
157 | struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); | ||
158 | u32 isr, alarm; | ||
159 | |||
160 | alarm = readl(vt8500_rtc->regbase + VT8500_RTC_AS); | ||
161 | isr = readl(vt8500_rtc->regbase + VT8500_RTC_IS); | ||
162 | |||
163 | alrm->time.tm_mday = bcd2bin((alarm & ALARM_DAY_MASK) >> ALARM_DAY_S); | ||
164 | alrm->time.tm_hour = bcd2bin((alarm & TIME_HOUR_MASK) >> TIME_HOUR_S); | ||
165 | alrm->time.tm_min = bcd2bin((alarm & TIME_MIN_MASK) >> TIME_MIN_S); | ||
166 | alrm->time.tm_sec = bcd2bin((alarm & TIME_SEC_MASK)); | ||
167 | |||
168 | alrm->enabled = (alarm & ALARM_ENABLE_MASK) ? 1 : 0; | ||
169 | |||
170 | alrm->pending = (isr & 1) ? 1 : 0; | ||
171 | return rtc_valid_tm(&alrm->time); | ||
172 | } | ||
173 | |||
174 | static int vt8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
175 | { | ||
176 | struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); | ||
177 | |||
178 | writel((alrm->enabled ? ALARM_ENABLE_MASK : 0) | ||
179 | | (bin2bcd(alrm->time.tm_mday) << ALARM_DAY_S) | ||
180 | | (bin2bcd(alrm->time.tm_hour) << TIME_HOUR_S) | ||
181 | | (bin2bcd(alrm->time.tm_min) << TIME_MIN_S) | ||
182 | | (bin2bcd(alrm->time.tm_sec)), | ||
183 | vt8500_rtc->regbase + VT8500_RTC_AS); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int vt8500_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
189 | { | ||
190 | struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); | ||
191 | unsigned long tmp = readl(vt8500_rtc->regbase + VT8500_RTC_AS); | ||
192 | |||
193 | if (enabled) | ||
194 | tmp |= ALARM_ENABLE_MASK; | ||
195 | else | ||
196 | tmp &= ~ALARM_ENABLE_MASK; | ||
197 | |||
198 | writel(tmp, vt8500_rtc->regbase + VT8500_RTC_AS); | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int vt8500_update_irq_enable(struct device *dev, unsigned int enabled) | ||
203 | { | ||
204 | struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev); | ||
205 | unsigned long tmp = readl(vt8500_rtc->regbase + VT8500_RTC_CR); | ||
206 | |||
207 | if (enabled) | ||
208 | tmp |= VT8500_RTC_CR_SM_SEC | VT8500_RTC_CR_SM_ENABLE; | ||
209 | else | ||
210 | tmp &= ~VT8500_RTC_CR_SM_ENABLE; | ||
211 | |||
212 | writel(tmp, vt8500_rtc->regbase + VT8500_RTC_CR); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static const struct rtc_class_ops vt8500_rtc_ops = { | ||
217 | .read_time = vt8500_rtc_read_time, | ||
218 | .set_time = vt8500_rtc_set_time, | ||
219 | .read_alarm = vt8500_rtc_read_alarm, | ||
220 | .set_alarm = vt8500_rtc_set_alarm, | ||
221 | .alarm_irq_enable = vt8500_alarm_irq_enable, | ||
222 | .update_irq_enable = vt8500_update_irq_enable, | ||
223 | }; | ||
224 | |||
225 | static int __devinit vt8500_rtc_probe(struct platform_device *pdev) | ||
226 | { | ||
227 | struct vt8500_rtc *vt8500_rtc; | ||
228 | int ret; | ||
229 | |||
230 | vt8500_rtc = kzalloc(sizeof(struct vt8500_rtc), GFP_KERNEL); | ||
231 | if (!vt8500_rtc) | ||
232 | return -ENOMEM; | ||
233 | |||
234 | spin_lock_init(&vt8500_rtc->lock); | ||
235 | platform_set_drvdata(pdev, vt8500_rtc); | ||
236 | |||
237 | vt8500_rtc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
238 | if (!vt8500_rtc->res) { | ||
239 | dev_err(&pdev->dev, "No I/O memory resource defined\n"); | ||
240 | ret = -ENXIO; | ||
241 | goto err_free; | ||
242 | } | ||
243 | |||
244 | vt8500_rtc->irq_alarm = platform_get_irq(pdev, 0); | ||
245 | if (vt8500_rtc->irq_alarm < 0) { | ||
246 | dev_err(&pdev->dev, "No alarm IRQ resource defined\n"); | ||
247 | ret = -ENXIO; | ||
248 | goto err_free; | ||
249 | } | ||
250 | |||
251 | vt8500_rtc->irq_hz = platform_get_irq(pdev, 1); | ||
252 | if (vt8500_rtc->irq_hz < 0) { | ||
253 | dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n"); | ||
254 | ret = -ENXIO; | ||
255 | goto err_free; | ||
256 | } | ||
257 | |||
258 | vt8500_rtc->res = request_mem_region(vt8500_rtc->res->start, | ||
259 | resource_size(vt8500_rtc->res), | ||
260 | "vt8500-rtc"); | ||
261 | if (vt8500_rtc->res == NULL) { | ||
262 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
263 | ret = -EBUSY; | ||
264 | goto err_free; | ||
265 | } | ||
266 | |||
267 | vt8500_rtc->regbase = ioremap(vt8500_rtc->res->start, | ||
268 | resource_size(vt8500_rtc->res)); | ||
269 | if (!vt8500_rtc->regbase) { | ||
270 | dev_err(&pdev->dev, "Unable to map RTC I/O memory\n"); | ||
271 | ret = -EBUSY; | ||
272 | goto err_release; | ||
273 | } | ||
274 | |||
275 | /* Enable the second/minute interrupt generation and enable RTC */ | ||
276 | writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H | ||
277 | | VT8500_RTC_CR_SM_ENABLE | VT8500_RTC_CR_SM_SEC, | ||
278 | vt8500_rtc->regbase + VT8500_RTC_CR); | ||
279 | |||
280 | vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev, | ||
281 | &vt8500_rtc_ops, THIS_MODULE); | ||
282 | if (IS_ERR(vt8500_rtc->rtc)) { | ||
283 | ret = PTR_ERR(vt8500_rtc->rtc); | ||
284 | dev_err(&pdev->dev, | ||
285 | "Failed to register RTC device -> %d\n", ret); | ||
286 | goto err_unmap; | ||
287 | } | ||
288 | |||
289 | ret = request_irq(vt8500_rtc->irq_hz, vt8500_rtc_irq, 0, | ||
290 | "rtc 1Hz", vt8500_rtc); | ||
291 | if (ret < 0) { | ||
292 | dev_err(&pdev->dev, "can't get irq %i, err %d\n", | ||
293 | vt8500_rtc->irq_hz, ret); | ||
294 | goto err_unreg; | ||
295 | } | ||
296 | |||
297 | ret = request_irq(vt8500_rtc->irq_alarm, vt8500_rtc_irq, 0, | ||
298 | "rtc alarm", vt8500_rtc); | ||
299 | if (ret < 0) { | ||
300 | dev_err(&pdev->dev, "can't get irq %i, err %d\n", | ||
301 | vt8500_rtc->irq_alarm, ret); | ||
302 | goto err_free_hz; | ||
303 | } | ||
304 | |||
305 | return 0; | ||
306 | |||
307 | err_free_hz: | ||
308 | free_irq(vt8500_rtc->irq_hz, vt8500_rtc); | ||
309 | err_unreg: | ||
310 | rtc_device_unregister(vt8500_rtc->rtc); | ||
311 | err_unmap: | ||
312 | iounmap(vt8500_rtc->regbase); | ||
313 | err_release: | ||
314 | release_mem_region(vt8500_rtc->res->start, | ||
315 | resource_size(vt8500_rtc->res)); | ||
316 | err_free: | ||
317 | kfree(vt8500_rtc); | ||
318 | return ret; | ||
319 | } | ||
320 | |||
321 | static int __devexit vt8500_rtc_remove(struct platform_device *pdev) | ||
322 | { | ||
323 | struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev); | ||
324 | |||
325 | free_irq(vt8500_rtc->irq_alarm, vt8500_rtc); | ||
326 | free_irq(vt8500_rtc->irq_hz, vt8500_rtc); | ||
327 | |||
328 | rtc_device_unregister(vt8500_rtc->rtc); | ||
329 | |||
330 | /* Disable alarm matching */ | ||
331 | writel(0, vt8500_rtc->regbase + VT8500_RTC_IS); | ||
332 | iounmap(vt8500_rtc->regbase); | ||
333 | release_mem_region(vt8500_rtc->res->start, | ||
334 | resource_size(vt8500_rtc->res)); | ||
335 | |||
336 | kfree(vt8500_rtc); | ||
337 | platform_set_drvdata(pdev, NULL); | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static struct platform_driver vt8500_rtc_driver = { | ||
343 | .probe = vt8500_rtc_probe, | ||
344 | .remove = __devexit_p(vt8500_rtc_remove), | ||
345 | .driver = { | ||
346 | .name = "vt8500-rtc", | ||
347 | .owner = THIS_MODULE, | ||
348 | }, | ||
349 | }; | ||
350 | |||
351 | static int __init vt8500_rtc_init(void) | ||
352 | { | ||
353 | return platform_driver_register(&vt8500_rtc_driver); | ||
354 | } | ||
355 | module_init(vt8500_rtc_init); | ||
356 | |||
357 | static void __exit vt8500_rtc_exit(void) | ||
358 | { | ||
359 | platform_driver_unregister(&vt8500_rtc_driver); | ||
360 | } | ||
361 | module_exit(vt8500_rtc_exit); | ||
362 | |||
363 | MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); | ||
364 | MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)"); | ||
365 | MODULE_LICENSE("GPL"); | ||
366 | MODULE_ALIAS("platform:vt8500-rtc"); | ||
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 85dddb1e4126..46784b83c5c4 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <asm/debug.h> | 24 | #include <asm/debug.h> |
25 | #include <asm/ebcdic.h> | 25 | #include <asm/ebcdic.h> |
26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
27 | #include <asm/s390_ext.h> | 27 | #include <asm/irq.h> |
28 | #include <asm/vtoc.h> | 28 | #include <asm/vtoc.h> |
29 | #include <asm/diag.h> | 29 | #include <asm/diag.h> |
30 | 30 | ||
@@ -642,7 +642,7 @@ dasd_diag_init(void) | |||
642 | } | 642 | } |
643 | ASCEBC(dasd_diag_discipline.ebcname, 4); | 643 | ASCEBC(dasd_diag_discipline.ebcname, 4); |
644 | 644 | ||
645 | ctl_set_bit(0, 9); | 645 | service_subclass_irq_register(); |
646 | register_external_interrupt(0x2603, dasd_ext_handler); | 646 | register_external_interrupt(0x2603, dasd_ext_handler); |
647 | dasd_diag_discipline_pointer = &dasd_diag_discipline; | 647 | dasd_diag_discipline_pointer = &dasd_diag_discipline; |
648 | return 0; | 648 | return 0; |
@@ -652,7 +652,7 @@ static void __exit | |||
652 | dasd_diag_cleanup(void) | 652 | dasd_diag_cleanup(void) |
653 | { | 653 | { |
654 | unregister_external_interrupt(0x2603, dasd_ext_handler); | 654 | unregister_external_interrupt(0x2603, dasd_ext_handler); |
655 | ctl_clear_bit(0, 9); | 655 | service_subclass_irq_unregister(); |
656 | dasd_diag_discipline_pointer = NULL; | 656 | dasd_diag_discipline_pointer = NULL; |
657 | } | 657 | } |
658 | 658 | ||
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index b76c61f82485..eaa7e78186f9 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/suspend.h> | 19 | #include <linux/suspend.h> |
20 | #include <linux/completion.h> | 20 | #include <linux/completion.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <asm/s390_ext.h> | ||
23 | #include <asm/types.h> | 22 | #include <asm/types.h> |
24 | #include <asm/irq.h> | 23 | #include <asm/irq.h> |
25 | 24 | ||
@@ -885,12 +884,12 @@ sclp_check_interface(void) | |||
885 | spin_unlock_irqrestore(&sclp_lock, flags); | 884 | spin_unlock_irqrestore(&sclp_lock, flags); |
886 | /* Enable service-signal interruption - needs to happen | 885 | /* Enable service-signal interruption - needs to happen |
887 | * with IRQs enabled. */ | 886 | * with IRQs enabled. */ |
888 | ctl_set_bit(0, 9); | 887 | service_subclass_irq_register(); |
889 | /* Wait for signal from interrupt or timeout */ | 888 | /* Wait for signal from interrupt or timeout */ |
890 | sclp_sync_wait(); | 889 | sclp_sync_wait(); |
891 | /* Disable service-signal interruption - needs to happen | 890 | /* Disable service-signal interruption - needs to happen |
892 | * with IRQs enabled. */ | 891 | * with IRQs enabled. */ |
893 | ctl_clear_bit(0,9); | 892 | service_subclass_irq_unregister(); |
894 | spin_lock_irqsave(&sclp_lock, flags); | 893 | spin_lock_irqsave(&sclp_lock, flags); |
895 | del_timer(&sclp_request_timer); | 894 | del_timer(&sclp_request_timer); |
896 | if (sclp_init_req.status == SCLP_REQ_DONE && | 895 | if (sclp_init_req.status == SCLP_REQ_DONE && |
@@ -1070,7 +1069,7 @@ sclp_init(void) | |||
1070 | spin_unlock_irqrestore(&sclp_lock, flags); | 1069 | spin_unlock_irqrestore(&sclp_lock, flags); |
1071 | /* Enable service-signal external interruption - needs to happen with | 1070 | /* Enable service-signal external interruption - needs to happen with |
1072 | * IRQs enabled. */ | 1071 | * IRQs enabled. */ |
1073 | ctl_set_bit(0, 9); | 1072 | service_subclass_irq_register(); |
1074 | sclp_init_mask(1); | 1073 | sclp_init_mask(1); |
1075 | return 0; | 1074 | return 0; |
1076 | 1075 | ||
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 607998f0b7d8..aec60d55b10d 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <asm/kvm_para.h> | 25 | #include <asm/kvm_para.h> |
26 | #include <asm/kvm_virtio.h> | 26 | #include <asm/kvm_virtio.h> |
27 | #include <asm/setup.h> | 27 | #include <asm/setup.h> |
28 | #include <asm/s390_ext.h> | ||
29 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
30 | 29 | ||
31 | #define VIRTIO_SUBCODE_64 0x0D00 | 30 | #define VIRTIO_SUBCODE_64 0x0D00 |
@@ -441,7 +440,7 @@ static int __init kvm_devices_init(void) | |||
441 | 440 | ||
442 | INIT_WORK(&hotplug_work, hotplug_devices); | 441 | INIT_WORK(&hotplug_work, hotplug_devices); |
443 | 442 | ||
444 | ctl_set_bit(0, 9); | 443 | service_subclass_irq_register(); |
445 | register_external_interrupt(0x2603, kvm_extint_handler); | 444 | register_external_interrupt(0x2603, kvm_extint_handler); |
446 | 445 | ||
447 | scan_devices(); | 446 | scan_devices(); |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 4ff26521d75f..3382475dc22d 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
@@ -59,7 +59,6 @@ | |||
59 | #ifndef AAC_DRIVER_BRANCH | 59 | #ifndef AAC_DRIVER_BRANCH |
60 | #define AAC_DRIVER_BRANCH "" | 60 | #define AAC_DRIVER_BRANCH "" |
61 | #endif | 61 | #endif |
62 | #define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__ | ||
63 | #define AAC_DRIVERNAME "aacraid" | 62 | #define AAC_DRIVERNAME "aacraid" |
64 | 63 | ||
65 | #ifdef AAC_DRIVER_BUILD | 64 | #ifdef AAC_DRIVER_BUILD |
@@ -67,7 +66,7 @@ | |||
67 | #define str(x) _str(x) | 66 | #define str(x) _str(x) |
68 | #define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION "[" str(AAC_DRIVER_BUILD) "]" AAC_DRIVER_BRANCH | 67 | #define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION "[" str(AAC_DRIVER_BUILD) "]" AAC_DRIVER_BRANCH |
69 | #else | 68 | #else |
70 | #define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION AAC_DRIVER_BRANCH " " AAC_DRIVER_BUILD_DATE | 69 | #define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION AAC_DRIVER_BRANCH |
71 | #endif | 70 | #endif |
72 | 71 | ||
73 | MODULE_AUTHOR("Red Hat Inc and Adaptec"); | 72 | MODULE_AUTHOR("Red Hat Inc and Adaptec"); |
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 3b7e83d2dab4..d5ff142c93a2 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c | |||
@@ -486,7 +486,7 @@ static ssize_t asd_show_update_bios(struct device *dev, | |||
486 | flash_error_table[i].reason); | 486 | flash_error_table[i].reason); |
487 | } | 487 | } |
488 | 488 | ||
489 | static DEVICE_ATTR(update_bios, S_IRUGO|S_IWUGO, | 489 | static DEVICE_ATTR(update_bios, S_IRUGO|S_IWUSR, |
490 | asd_show_update_bios, asd_store_update_bios); | 490 | asd_show_update_bios, asd_store_update_bios); |
491 | 491 | ||
492 | static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha) | 492 | static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha) |
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index c1f72c49196f..6c7e0339dda4 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c | |||
@@ -56,6 +56,8 @@ BFA_TRC_FILE(CNA, IOC); | |||
56 | #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc)) | 56 | #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc)) |
57 | #define bfa_ioc_notify_fail(__ioc) \ | 57 | #define bfa_ioc_notify_fail(__ioc) \ |
58 | ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc)) | 58 | ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc)) |
59 | #define bfa_ioc_sync_start(__ioc) \ | ||
60 | ((__ioc)->ioc_hwif->ioc_sync_start(__ioc)) | ||
59 | #define bfa_ioc_sync_join(__ioc) \ | 61 | #define bfa_ioc_sync_join(__ioc) \ |
60 | ((__ioc)->ioc_hwif->ioc_sync_join(__ioc)) | 62 | ((__ioc)->ioc_hwif->ioc_sync_join(__ioc)) |
61 | #define bfa_ioc_sync_leave(__ioc) \ | 63 | #define bfa_ioc_sync_leave(__ioc) \ |
@@ -647,7 +649,7 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
647 | switch (event) { | 649 | switch (event) { |
648 | case IOCPF_E_SEMLOCKED: | 650 | case IOCPF_E_SEMLOCKED: |
649 | if (bfa_ioc_firmware_lock(ioc)) { | 651 | if (bfa_ioc_firmware_lock(ioc)) { |
650 | if (bfa_ioc_sync_complete(ioc)) { | 652 | if (bfa_ioc_sync_start(ioc)) { |
651 | iocpf->retry_count = 0; | 653 | iocpf->retry_count = 0; |
652 | bfa_ioc_sync_join(ioc); | 654 | bfa_ioc_sync_join(ioc); |
653 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); | 655 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); |
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index ec9cf08b0e7f..c85182a704fb 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h | |||
@@ -263,6 +263,7 @@ struct bfa_ioc_hwif_s { | |||
263 | bfa_boolean_t msix); | 263 | bfa_boolean_t msix); |
264 | void (*ioc_notify_fail) (struct bfa_ioc_s *ioc); | 264 | void (*ioc_notify_fail) (struct bfa_ioc_s *ioc); |
265 | void (*ioc_ownership_reset) (struct bfa_ioc_s *ioc); | 265 | void (*ioc_ownership_reset) (struct bfa_ioc_s *ioc); |
266 | bfa_boolean_t (*ioc_sync_start) (struct bfa_ioc_s *ioc); | ||
266 | void (*ioc_sync_join) (struct bfa_ioc_s *ioc); | 267 | void (*ioc_sync_join) (struct bfa_ioc_s *ioc); |
267 | void (*ioc_sync_leave) (struct bfa_ioc_s *ioc); | 268 | void (*ioc_sync_leave) (struct bfa_ioc_s *ioc); |
268 | void (*ioc_sync_ack) (struct bfa_ioc_s *ioc); | 269 | void (*ioc_sync_ack) (struct bfa_ioc_s *ioc); |
diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c index e4a0713185b6..89ae4c8f95a2 100644 --- a/drivers/scsi/bfa/bfa_ioc_cb.c +++ b/drivers/scsi/bfa/bfa_ioc_cb.c | |||
@@ -32,6 +32,7 @@ static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc); | |||
32 | static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); | 32 | static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); |
33 | static void bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc); | 33 | static void bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc); |
34 | static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc); | 34 | static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc); |
35 | static bfa_boolean_t bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc); | ||
35 | static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc); | 36 | static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc); |
36 | static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc); | 37 | static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc); |
37 | static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc); | 38 | static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc); |
@@ -53,6 +54,7 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc) | |||
53 | hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set; | 54 | hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set; |
54 | hwif_cb.ioc_notify_fail = bfa_ioc_cb_notify_fail; | 55 | hwif_cb.ioc_notify_fail = bfa_ioc_cb_notify_fail; |
55 | hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset; | 56 | hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset; |
57 | hwif_cb.ioc_sync_start = bfa_ioc_cb_sync_start; | ||
56 | hwif_cb.ioc_sync_join = bfa_ioc_cb_sync_join; | 58 | hwif_cb.ioc_sync_join = bfa_ioc_cb_sync_join; |
57 | hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave; | 59 | hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave; |
58 | hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack; | 60 | hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack; |
@@ -195,6 +197,15 @@ bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix) | |||
195 | } | 197 | } |
196 | 198 | ||
197 | /* | 199 | /* |
200 | * Synchronized IOC failure processing routines | ||
201 | */ | ||
202 | static bfa_boolean_t | ||
203 | bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc) | ||
204 | { | ||
205 | return bfa_ioc_cb_sync_complete(ioc); | ||
206 | } | ||
207 | |||
208 | /* | ||
198 | * Cleanup hw semaphore and usecnt registers | 209 | * Cleanup hw semaphore and usecnt registers |
199 | */ | 210 | */ |
200 | static void | 211 | static void |
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index 008d129ddfcd..93612520f0d2 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c | |||
@@ -41,6 +41,7 @@ static void bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc); | |||
41 | static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); | 41 | static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); |
42 | static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc); | 42 | static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc); |
43 | static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc); | 43 | static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc); |
44 | static bfa_boolean_t bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc); | ||
44 | static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc); | 45 | static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc); |
45 | static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc); | 46 | static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc); |
46 | static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc); | 47 | static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc); |
@@ -62,6 +63,7 @@ bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc) | |||
62 | hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; | 63 | hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; |
63 | hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail; | 64 | hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail; |
64 | hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; | 65 | hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; |
66 | hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start; | ||
65 | hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join; | 67 | hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join; |
66 | hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave; | 68 | hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave; |
67 | hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack; | 69 | hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack; |
@@ -351,6 +353,30 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc) | |||
351 | writel(1, ioc->ioc_regs.ioc_sem_reg); | 353 | writel(1, ioc->ioc_regs.ioc_sem_reg); |
352 | } | 354 | } |
353 | 355 | ||
356 | static bfa_boolean_t | ||
357 | bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc) | ||
358 | { | ||
359 | uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); | ||
360 | uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32); | ||
361 | |||
362 | /* | ||
363 | * Driver load time. If the sync required bit for this PCI fn | ||
364 | * is set, it is due to an unclean exit by the driver for this | ||
365 | * PCI fn in the previous incarnation. Whoever comes here first | ||
366 | * should clean it up, no matter which PCI fn. | ||
367 | */ | ||
368 | |||
369 | if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) { | ||
370 | writel(0, ioc->ioc_regs.ioc_fail_sync); | ||
371 | writel(1, ioc->ioc_regs.ioc_usage_reg); | ||
372 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); | ||
373 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate); | ||
374 | return BFA_TRUE; | ||
375 | } | ||
376 | |||
377 | return bfa_ioc_ct_sync_complete(ioc); | ||
378 | } | ||
379 | |||
354 | /* | 380 | /* |
355 | * Synchronized IOC failure processing routines | 381 | * Synchronized IOC failure processing routines |
356 | */ | 382 | */ |
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index cfd59023227b..6bdd25a93db9 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h | |||
@@ -66,11 +66,11 @@ | |||
66 | #define BD_SPLIT_SIZE 32768 | 66 | #define BD_SPLIT_SIZE 32768 |
67 | 67 | ||
68 | /* min, max & default values for SQ/RQ/CQ size, configurable via' modparam */ | 68 | /* min, max & default values for SQ/RQ/CQ size, configurable via' modparam */ |
69 | #define BNX2I_SQ_WQES_MIN 16 | 69 | #define BNX2I_SQ_WQES_MIN 16 |
70 | #define BNX2I_570X_SQ_WQES_MAX 128 | 70 | #define BNX2I_570X_SQ_WQES_MAX 128 |
71 | #define BNX2I_5770X_SQ_WQES_MAX 512 | 71 | #define BNX2I_5770X_SQ_WQES_MAX 512 |
72 | #define BNX2I_570X_SQ_WQES_DEFAULT 128 | 72 | #define BNX2I_570X_SQ_WQES_DEFAULT 128 |
73 | #define BNX2I_5770X_SQ_WQES_DEFAULT 256 | 73 | #define BNX2I_5770X_SQ_WQES_DEFAULT 128 |
74 | 74 | ||
75 | #define BNX2I_570X_CQ_WQES_MAX 128 | 75 | #define BNX2I_570X_CQ_WQES_MAX 128 |
76 | #define BNX2I_5770X_CQ_WQES_MAX 512 | 76 | #define BNX2I_5770X_CQ_WQES_MAX 512 |
@@ -115,6 +115,7 @@ | |||
115 | #define BNX2X_MAX_CQS 8 | 115 | #define BNX2X_MAX_CQS 8 |
116 | 116 | ||
117 | #define CNIC_ARM_CQE 1 | 117 | #define CNIC_ARM_CQE 1 |
118 | #define CNIC_ARM_CQE_FP 2 | ||
118 | #define CNIC_DISARM_CQE 0 | 119 | #define CNIC_DISARM_CQE 0 |
119 | 120 | ||
120 | #define REG_RD(__hba, offset) \ | 121 | #define REG_RD(__hba, offset) \ |
@@ -666,7 +667,9 @@ enum { | |||
666 | * after HBA reset is completed by bnx2i/cnic/bnx2 | 667 | * after HBA reset is completed by bnx2i/cnic/bnx2 |
667 | * modules | 668 | * modules |
668 | * @state: tracks offload connection state machine | 669 | * @state: tracks offload connection state machine |
669 | * @teardown_mode: indicates if conn teardown is abortive or orderly | 670 | * @timestamp: tracks the start time when the ep begins to connect |
671 | * @num_active_cmds: tracks the number of outstanding commands for this ep | ||
672 | * @ec_shift: the amount of shift as part of the event coal calc | ||
670 | * @qp: QP information | 673 | * @qp: QP information |
671 | * @ids: contains chip allocated *context id* & driver assigned | 674 | * @ids: contains chip allocated *context id* & driver assigned |
672 | * *iscsi cid* | 675 | * *iscsi cid* |
@@ -685,6 +688,7 @@ struct bnx2i_endpoint { | |||
685 | u32 state; | 688 | u32 state; |
686 | unsigned long timestamp; | 689 | unsigned long timestamp; |
687 | int num_active_cmds; | 690 | int num_active_cmds; |
691 | u32 ec_shift; | ||
688 | 692 | ||
689 | struct qp_info qp; | 693 | struct qp_info qp; |
690 | struct ep_handles ids; | 694 | struct ep_handles ids; |
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index f0b89513faed..5c54a2d9b834 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c | |||
@@ -138,7 +138,6 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action) | |||
138 | u16 next_index; | 138 | u16 next_index; |
139 | u32 num_active_cmds; | 139 | u32 num_active_cmds; |
140 | 140 | ||
141 | |||
142 | /* Coalesce CQ entries only on 10G devices */ | 141 | /* Coalesce CQ entries only on 10G devices */ |
143 | if (!test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) | 142 | if (!test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) |
144 | return; | 143 | return; |
@@ -148,16 +147,19 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action) | |||
148 | * interrupts and other unwanted results | 147 | * interrupts and other unwanted results |
149 | */ | 148 | */ |
150 | cq_db = (struct bnx2i_5771x_cq_db *) ep->qp.cq_pgtbl_virt; | 149 | cq_db = (struct bnx2i_5771x_cq_db *) ep->qp.cq_pgtbl_virt; |
151 | if (cq_db->sqn[0] && cq_db->sqn[0] != 0xFFFF) | ||
152 | return; | ||
153 | 150 | ||
154 | if (action == CNIC_ARM_CQE) { | 151 | if (action != CNIC_ARM_CQE_FP) |
152 | if (cq_db->sqn[0] && cq_db->sqn[0] != 0xFFFF) | ||
153 | return; | ||
154 | |||
155 | if (action == CNIC_ARM_CQE || action == CNIC_ARM_CQE_FP) { | ||
155 | num_active_cmds = ep->num_active_cmds; | 156 | num_active_cmds = ep->num_active_cmds; |
156 | if (num_active_cmds <= event_coal_min) | 157 | if (num_active_cmds <= event_coal_min) |
157 | next_index = 1; | 158 | next_index = 1; |
158 | else | 159 | else |
159 | next_index = event_coal_min + | 160 | next_index = event_coal_min + |
160 | (num_active_cmds - event_coal_min) / event_coal_div; | 161 | ((num_active_cmds - event_coal_min) >> |
162 | ep->ec_shift); | ||
161 | if (!next_index) | 163 | if (!next_index) |
162 | next_index = 1; | 164 | next_index = 1; |
163 | cq_index = ep->qp.cqe_exp_seq_sn + next_index - 1; | 165 | cq_index = ep->qp.cqe_exp_seq_sn + next_index - 1; |
@@ -1274,6 +1276,7 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba) | |||
1274 | iscsi_init.dummy_buffer_addr_hi = | 1276 | iscsi_init.dummy_buffer_addr_hi = |
1275 | (u32) ((u64) hba->dummy_buf_dma >> 32); | 1277 | (u32) ((u64) hba->dummy_buf_dma >> 32); |
1276 | 1278 | ||
1279 | hba->num_ccell = hba->max_sqes >> 1; | ||
1277 | hba->ctx_ccell_tasks = | 1280 | hba->ctx_ccell_tasks = |
1278 | ((hba->num_ccell & 0xFFFF) | (hba->max_sqes << 16)); | 1281 | ((hba->num_ccell & 0xFFFF) | (hba->max_sqes << 16)); |
1279 | iscsi_init.num_ccells_per_conn = hba->num_ccell; | 1282 | iscsi_init.num_ccells_per_conn = hba->num_ccell; |
@@ -1934,7 +1937,6 @@ cqe_out: | |||
1934 | qp->cq_cons_idx++; | 1937 | qp->cq_cons_idx++; |
1935 | } | 1938 | } |
1936 | } | 1939 | } |
1937 | bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE); | ||
1938 | } | 1940 | } |
1939 | 1941 | ||
1940 | /** | 1942 | /** |
@@ -1948,22 +1950,23 @@ cqe_out: | |||
1948 | static void bnx2i_fastpath_notification(struct bnx2i_hba *hba, | 1950 | static void bnx2i_fastpath_notification(struct bnx2i_hba *hba, |
1949 | struct iscsi_kcqe *new_cqe_kcqe) | 1951 | struct iscsi_kcqe *new_cqe_kcqe) |
1950 | { | 1952 | { |
1951 | struct bnx2i_conn *conn; | 1953 | struct bnx2i_conn *bnx2i_conn; |
1952 | u32 iscsi_cid; | 1954 | u32 iscsi_cid; |
1953 | 1955 | ||
1954 | iscsi_cid = new_cqe_kcqe->iscsi_conn_id; | 1956 | iscsi_cid = new_cqe_kcqe->iscsi_conn_id; |
1955 | conn = bnx2i_get_conn_from_id(hba, iscsi_cid); | 1957 | bnx2i_conn = bnx2i_get_conn_from_id(hba, iscsi_cid); |
1956 | 1958 | ||
1957 | if (!conn) { | 1959 | if (!bnx2i_conn) { |
1958 | printk(KERN_ALERT "cid #%x not valid\n", iscsi_cid); | 1960 | printk(KERN_ALERT "cid #%x not valid\n", iscsi_cid); |
1959 | return; | 1961 | return; |
1960 | } | 1962 | } |
1961 | if (!conn->ep) { | 1963 | if (!bnx2i_conn->ep) { |
1962 | printk(KERN_ALERT "cid #%x - ep not bound\n", iscsi_cid); | 1964 | printk(KERN_ALERT "cid #%x - ep not bound\n", iscsi_cid); |
1963 | return; | 1965 | return; |
1964 | } | 1966 | } |
1965 | 1967 | bnx2i_process_new_cqes(bnx2i_conn); | |
1966 | bnx2i_process_new_cqes(conn); | 1968 | bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE_FP); |
1969 | bnx2i_process_new_cqes(bnx2i_conn); | ||
1967 | } | 1970 | } |
1968 | 1971 | ||
1969 | 1972 | ||
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 1d24a2819736..6adbdc34a9a5 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c | |||
@@ -244,7 +244,7 @@ void bnx2i_stop(void *handle) | |||
244 | wait_event_interruptible_timeout(hba->eh_wait, | 244 | wait_event_interruptible_timeout(hba->eh_wait, |
245 | (list_empty(&hba->ep_ofld_list) && | 245 | (list_empty(&hba->ep_ofld_list) && |
246 | list_empty(&hba->ep_destroy_list)), | 246 | list_empty(&hba->ep_destroy_list)), |
247 | 10 * HZ); | 247 | 2 * HZ); |
248 | /* Wait for all endpoints to be torn down, Chip will be reset once | 248 | /* Wait for all endpoints to be torn down, Chip will be reset once |
249 | * control returns to network driver. So it is required to cleanup and | 249 | * control returns to network driver. So it is required to cleanup and |
250 | * release all connection resources before returning from this routine. | 250 | * release all connection resources before returning from this routine. |
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 1809f9ccc4ce..041928b23cb0 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c | |||
@@ -379,6 +379,7 @@ static struct iscsi_endpoint *bnx2i_alloc_ep(struct bnx2i_hba *hba) | |||
379 | { | 379 | { |
380 | struct iscsi_endpoint *ep; | 380 | struct iscsi_endpoint *ep; |
381 | struct bnx2i_endpoint *bnx2i_ep; | 381 | struct bnx2i_endpoint *bnx2i_ep; |
382 | u32 ec_div; | ||
382 | 383 | ||
383 | ep = iscsi_create_endpoint(sizeof(*bnx2i_ep)); | 384 | ep = iscsi_create_endpoint(sizeof(*bnx2i_ep)); |
384 | if (!ep) { | 385 | if (!ep) { |
@@ -393,6 +394,11 @@ static struct iscsi_endpoint *bnx2i_alloc_ep(struct bnx2i_hba *hba) | |||
393 | bnx2i_ep->ep_iscsi_cid = (u16) -1; | 394 | bnx2i_ep->ep_iscsi_cid = (u16) -1; |
394 | bnx2i_ep->hba = hba; | 395 | bnx2i_ep->hba = hba; |
395 | bnx2i_ep->hba_age = hba->age; | 396 | bnx2i_ep->hba_age = hba->age; |
397 | |||
398 | ec_div = event_coal_div; | ||
399 | while (ec_div >>= 1) | ||
400 | bnx2i_ep->ec_shift += 1; | ||
401 | |||
396 | hba->ofld_conns_active++; | 402 | hba->ofld_conns_active++; |
397 | init_waitqueue_head(&bnx2i_ep->ofld_wait); | 403 | init_waitqueue_head(&bnx2i_ep->ofld_wait); |
398 | return ep; | 404 | return ep; |
@@ -858,7 +864,7 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic) | |||
858 | mutex_init(&hba->net_dev_lock); | 864 | mutex_init(&hba->net_dev_lock); |
859 | init_waitqueue_head(&hba->eh_wait); | 865 | init_waitqueue_head(&hba->eh_wait); |
860 | if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) { | 866 | if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) { |
861 | hba->hba_shutdown_tmo = 20 * HZ; | 867 | hba->hba_shutdown_tmo = 30 * HZ; |
862 | hba->conn_teardown_tmo = 20 * HZ; | 868 | hba->conn_teardown_tmo = 20 * HZ; |
863 | hba->conn_ctx_destroy_tmo = 6 * HZ; | 869 | hba->conn_ctx_destroy_tmo = 6 * HZ; |
864 | } else { /* 5706/5708/5709 */ | 870 | } else { /* 5706/5708/5709 */ |
@@ -1208,6 +1214,9 @@ static int bnx2i_task_xmit(struct iscsi_task *task) | |||
1208 | struct bnx2i_cmd *cmd = task->dd_data; | 1214 | struct bnx2i_cmd *cmd = task->dd_data; |
1209 | struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr; | 1215 | struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr; |
1210 | 1216 | ||
1217 | if (bnx2i_conn->ep->num_active_cmds + 1 > hba->max_sqes) | ||
1218 | return -ENOMEM; | ||
1219 | |||
1211 | /* | 1220 | /* |
1212 | * If there is no scsi_cmnd this must be a mgmt task | 1221 | * If there is no scsi_cmnd this must be a mgmt task |
1213 | */ | 1222 | */ |
@@ -2156,7 +2165,7 @@ static struct scsi_host_template bnx2i_host_template = { | |||
2156 | .change_queue_depth = iscsi_change_queue_depth, | 2165 | .change_queue_depth = iscsi_change_queue_depth, |
2157 | .can_queue = 1024, | 2166 | .can_queue = 1024, |
2158 | .max_sectors = 127, | 2167 | .max_sectors = 127, |
2159 | .cmd_per_lun = 32, | 2168 | .cmd_per_lun = 24, |
2160 | .this_id = -1, | 2169 | .this_id = -1, |
2161 | .use_clustering = ENABLE_CLUSTERING, | 2170 | .use_clustering = ENABLE_CLUSTERING, |
2162 | .sg_tablesize = ISCSI_MAX_BDS_PER_CMD, | 2171 | .sg_tablesize = ISCSI_MAX_BDS_PER_CMD, |
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index cc23bd9480b2..155d7b9bdeae 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -137,6 +137,7 @@ static int fcoe_vport_create(struct fc_vport *, bool disabled); | |||
137 | static int fcoe_vport_disable(struct fc_vport *, bool disable); | 137 | static int fcoe_vport_disable(struct fc_vport *, bool disable); |
138 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); | 138 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); |
139 | static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); | 139 | static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); |
140 | static int fcoe_validate_vport_create(struct fc_vport *); | ||
140 | 141 | ||
141 | static struct libfc_function_template fcoe_libfc_fcn_templ = { | 142 | static struct libfc_function_template fcoe_libfc_fcn_templ = { |
142 | .frame_send = fcoe_xmit, | 143 | .frame_send = fcoe_xmit, |
@@ -2351,6 +2352,17 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled) | |||
2351 | struct fcoe_interface *fcoe = port->priv; | 2352 | struct fcoe_interface *fcoe = port->priv; |
2352 | struct net_device *netdev = fcoe->netdev; | 2353 | struct net_device *netdev = fcoe->netdev; |
2353 | struct fc_lport *vn_port; | 2354 | struct fc_lport *vn_port; |
2355 | int rc; | ||
2356 | char buf[32]; | ||
2357 | |||
2358 | rc = fcoe_validate_vport_create(vport); | ||
2359 | if (rc) { | ||
2360 | wwn_to_str(vport->port_name, buf, sizeof(buf)); | ||
2361 | printk(KERN_ERR "fcoe: Failed to create vport, " | ||
2362 | "WWPN (0x%s) already exists\n", | ||
2363 | buf); | ||
2364 | return rc; | ||
2365 | } | ||
2354 | 2366 | ||
2355 | mutex_lock(&fcoe_config_mutex); | 2367 | mutex_lock(&fcoe_config_mutex); |
2356 | vn_port = fcoe_if_create(fcoe, &vport->dev, 1); | 2368 | vn_port = fcoe_if_create(fcoe, &vport->dev, 1); |
@@ -2497,3 +2509,49 @@ static void fcoe_set_port_id(struct fc_lport *lport, | |||
2497 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) | 2509 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) |
2498 | fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); | 2510 | fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); |
2499 | } | 2511 | } |
2512 | |||
2513 | /** | ||
2514 | * fcoe_validate_vport_create() - Validate a vport before creating it | ||
2515 | * @vport: NPIV port to be created | ||
2516 | * | ||
2517 | * This routine is meant to add validation for a vport before creating it | ||
2518 | * via fcoe_vport_create(). | ||
2519 | * Current validations are: | ||
2520 | * - WWPN supplied is unique for given lport | ||
2521 | * | ||
2522 | * | ||
2523 | */ | ||
2524 | static int fcoe_validate_vport_create(struct fc_vport *vport) | ||
2525 | { | ||
2526 | struct Scsi_Host *shost = vport_to_shost(vport); | ||
2527 | struct fc_lport *n_port = shost_priv(shost); | ||
2528 | struct fc_lport *vn_port; | ||
2529 | int rc = 0; | ||
2530 | char buf[32]; | ||
2531 | |||
2532 | mutex_lock(&n_port->lp_mutex); | ||
2533 | |||
2534 | wwn_to_str(vport->port_name, buf, sizeof(buf)); | ||
2535 | /* Check if the wwpn is not same as that of the lport */ | ||
2536 | if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) { | ||
2537 | FCOE_DBG("vport WWPN 0x%s is same as that of the " | ||
2538 | "base port WWPN\n", buf); | ||
2539 | rc = -EINVAL; | ||
2540 | goto out; | ||
2541 | } | ||
2542 | |||
2543 | /* Check if there is any existing vport with same wwpn */ | ||
2544 | list_for_each_entry(vn_port, &n_port->vports, list) { | ||
2545 | if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) { | ||
2546 | FCOE_DBG("vport with given WWPN 0x%s already " | ||
2547 | "exists\n", buf); | ||
2548 | rc = -EINVAL; | ||
2549 | break; | ||
2550 | } | ||
2551 | } | ||
2552 | |||
2553 | out: | ||
2554 | mutex_unlock(&n_port->lp_mutex); | ||
2555 | |||
2556 | return rc; | ||
2557 | } | ||
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index 408a6fd78fb4..c4a93993c0cf 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h | |||
@@ -99,4 +99,14 @@ static inline struct net_device *fcoe_netdev(const struct fc_lport *lport) | |||
99 | ((struct fcoe_port *)lport_priv(lport))->priv)->netdev; | 99 | ((struct fcoe_port *)lport_priv(lport))->priv)->netdev; |
100 | } | 100 | } |
101 | 101 | ||
102 | static inline void wwn_to_str(u64 wwn, char *buf, int len) | ||
103 | { | ||
104 | u8 wwpn[8]; | ||
105 | |||
106 | u64_to_wwn(wwn, wwpn); | ||
107 | snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x", | ||
108 | wwpn[0], wwpn[1], wwpn[2], wwpn[3], | ||
109 | wwpn[4], wwpn[5], wwpn[6], wwpn[7]); | ||
110 | } | ||
111 | |||
102 | #endif /* _FCOE_H_ */ | 112 | #endif /* _FCOE_H_ */ |
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 229e4af5508a..c74c4b8e71ef 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c | |||
@@ -1173,7 +1173,9 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
1173 | struct fc_lport *lport = fip->lp; | 1173 | struct fc_lport *lport = fip->lp; |
1174 | struct fc_lport *vn_port = NULL; | 1174 | struct fc_lport *vn_port = NULL; |
1175 | u32 desc_mask; | 1175 | u32 desc_mask; |
1176 | int is_vn_port = 0; | 1176 | int num_vlink_desc; |
1177 | int reset_phys_port = 0; | ||
1178 | struct fip_vn_desc **vlink_desc_arr = NULL; | ||
1177 | 1179 | ||
1178 | LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n"); | 1180 | LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n"); |
1179 | 1181 | ||
@@ -1183,70 +1185,73 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
1183 | /* | 1185 | /* |
1184 | * mask of required descriptors. Validating each one clears its bit. | 1186 | * mask of required descriptors. Validating each one clears its bit. |
1185 | */ | 1187 | */ |
1186 | desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | BIT(FIP_DT_VN_ID); | 1188 | desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME); |
1187 | 1189 | ||
1188 | rlen = ntohs(fh->fip_dl_len) * FIP_BPW; | 1190 | rlen = ntohs(fh->fip_dl_len) * FIP_BPW; |
1189 | desc = (struct fip_desc *)(fh + 1); | 1191 | desc = (struct fip_desc *)(fh + 1); |
1192 | |||
1193 | /* | ||
1194 | * Actually need to subtract 'sizeof(*mp) - sizeof(*wp)' from 'rlen' | ||
1195 | * before determining max Vx_Port descriptor but a buggy FCF could have | ||
1196 | * omited either or both MAC Address and Name Identifier descriptors | ||
1197 | */ | ||
1198 | num_vlink_desc = rlen / sizeof(*vp); | ||
1199 | if (num_vlink_desc) | ||
1200 | vlink_desc_arr = kmalloc(sizeof(vp) * num_vlink_desc, | ||
1201 | GFP_ATOMIC); | ||
1202 | if (!vlink_desc_arr) | ||
1203 | return; | ||
1204 | num_vlink_desc = 0; | ||
1205 | |||
1190 | while (rlen >= sizeof(*desc)) { | 1206 | while (rlen >= sizeof(*desc)) { |
1191 | dlen = desc->fip_dlen * FIP_BPW; | 1207 | dlen = desc->fip_dlen * FIP_BPW; |
1192 | if (dlen > rlen) | 1208 | if (dlen > rlen) |
1193 | return; | 1209 | goto err; |
1194 | /* Drop CVL if there are duplicate critical descriptors */ | 1210 | /* Drop CVL if there are duplicate critical descriptors */ |
1195 | if ((desc->fip_dtype < 32) && | 1211 | if ((desc->fip_dtype < 32) && |
1212 | (desc->fip_dtype != FIP_DT_VN_ID) && | ||
1196 | !(desc_mask & 1U << desc->fip_dtype)) { | 1213 | !(desc_mask & 1U << desc->fip_dtype)) { |
1197 | LIBFCOE_FIP_DBG(fip, "Duplicate Critical " | 1214 | LIBFCOE_FIP_DBG(fip, "Duplicate Critical " |
1198 | "Descriptors in FIP CVL\n"); | 1215 | "Descriptors in FIP CVL\n"); |
1199 | return; | 1216 | goto err; |
1200 | } | 1217 | } |
1201 | switch (desc->fip_dtype) { | 1218 | switch (desc->fip_dtype) { |
1202 | case FIP_DT_MAC: | 1219 | case FIP_DT_MAC: |
1203 | mp = (struct fip_mac_desc *)desc; | 1220 | mp = (struct fip_mac_desc *)desc; |
1204 | if (dlen < sizeof(*mp)) | 1221 | if (dlen < sizeof(*mp)) |
1205 | return; | 1222 | goto err; |
1206 | if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac)) | 1223 | if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac)) |
1207 | return; | 1224 | goto err; |
1208 | desc_mask &= ~BIT(FIP_DT_MAC); | 1225 | desc_mask &= ~BIT(FIP_DT_MAC); |
1209 | break; | 1226 | break; |
1210 | case FIP_DT_NAME: | 1227 | case FIP_DT_NAME: |
1211 | wp = (struct fip_wwn_desc *)desc; | 1228 | wp = (struct fip_wwn_desc *)desc; |
1212 | if (dlen < sizeof(*wp)) | 1229 | if (dlen < sizeof(*wp)) |
1213 | return; | 1230 | goto err; |
1214 | if (get_unaligned_be64(&wp->fd_wwn) != fcf->switch_name) | 1231 | if (get_unaligned_be64(&wp->fd_wwn) != fcf->switch_name) |
1215 | return; | 1232 | goto err; |
1216 | desc_mask &= ~BIT(FIP_DT_NAME); | 1233 | desc_mask &= ~BIT(FIP_DT_NAME); |
1217 | break; | 1234 | break; |
1218 | case FIP_DT_VN_ID: | 1235 | case FIP_DT_VN_ID: |
1219 | vp = (struct fip_vn_desc *)desc; | 1236 | vp = (struct fip_vn_desc *)desc; |
1220 | if (dlen < sizeof(*vp)) | 1237 | if (dlen < sizeof(*vp)) |
1221 | return; | 1238 | goto err; |
1222 | if (compare_ether_addr(vp->fd_mac, | 1239 | vlink_desc_arr[num_vlink_desc++] = vp; |
1223 | fip->get_src_addr(lport)) == 0 && | 1240 | vn_port = fc_vport_id_lookup(lport, |
1224 | get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn && | 1241 | ntoh24(vp->fd_fc_id)); |
1225 | ntoh24(vp->fd_fc_id) == lport->port_id) { | 1242 | if (vn_port && (vn_port == lport)) { |
1226 | desc_mask &= ~BIT(FIP_DT_VN_ID); | 1243 | mutex_lock(&fip->ctlr_mutex); |
1227 | break; | 1244 | per_cpu_ptr(lport->dev_stats, |
1245 | get_cpu())->VLinkFailureCount++; | ||
1246 | put_cpu(); | ||
1247 | fcoe_ctlr_reset(fip); | ||
1248 | mutex_unlock(&fip->ctlr_mutex); | ||
1228 | } | 1249 | } |
1229 | /* check if clr_vlink is for NPIV port */ | ||
1230 | mutex_lock(&lport->lp_mutex); | ||
1231 | list_for_each_entry(vn_port, &lport->vports, list) { | ||
1232 | if (compare_ether_addr(vp->fd_mac, | ||
1233 | fip->get_src_addr(vn_port)) == 0 && | ||
1234 | (get_unaligned_be64(&vp->fd_wwpn) | ||
1235 | == vn_port->wwpn) && | ||
1236 | (ntoh24(vp->fd_fc_id) == | ||
1237 | fc_host_port_id(vn_port->host))) { | ||
1238 | desc_mask &= ~BIT(FIP_DT_VN_ID); | ||
1239 | is_vn_port = 1; | ||
1240 | break; | ||
1241 | } | ||
1242 | } | ||
1243 | mutex_unlock(&lport->lp_mutex); | ||
1244 | |||
1245 | break; | 1250 | break; |
1246 | default: | 1251 | default: |
1247 | /* standard says ignore unknown descriptors >= 128 */ | 1252 | /* standard says ignore unknown descriptors >= 128 */ |
1248 | if (desc->fip_dtype < FIP_DT_VENDOR_BASE) | 1253 | if (desc->fip_dtype < FIP_DT_VENDOR_BASE) |
1249 | return; | 1254 | goto err; |
1250 | break; | 1255 | break; |
1251 | } | 1256 | } |
1252 | desc = (struct fip_desc *)((char *)desc + dlen); | 1257 | desc = (struct fip_desc *)((char *)desc + dlen); |
@@ -1256,26 +1261,68 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
1256 | /* | 1261 | /* |
1257 | * reset only if all required descriptors were present and valid. | 1262 | * reset only if all required descriptors were present and valid. |
1258 | */ | 1263 | */ |
1259 | if (desc_mask) { | 1264 | if (desc_mask) |
1260 | LIBFCOE_FIP_DBG(fip, "missing descriptors mask %x\n", | 1265 | LIBFCOE_FIP_DBG(fip, "missing descriptors mask %x\n", |
1261 | desc_mask); | 1266 | desc_mask); |
1267 | else if (!num_vlink_desc) { | ||
1268 | LIBFCOE_FIP_DBG(fip, "CVL: no Vx_Port descriptor found\n"); | ||
1269 | /* | ||
1270 | * No Vx_Port description. Clear all NPIV ports, | ||
1271 | * followed by physical port | ||
1272 | */ | ||
1273 | mutex_lock(&lport->lp_mutex); | ||
1274 | list_for_each_entry(vn_port, &lport->vports, list) | ||
1275 | fc_lport_reset(vn_port); | ||
1276 | mutex_unlock(&lport->lp_mutex); | ||
1277 | |||
1278 | mutex_lock(&fip->ctlr_mutex); | ||
1279 | per_cpu_ptr(lport->dev_stats, | ||
1280 | get_cpu())->VLinkFailureCount++; | ||
1281 | put_cpu(); | ||
1282 | fcoe_ctlr_reset(fip); | ||
1283 | mutex_unlock(&fip->ctlr_mutex); | ||
1284 | |||
1285 | fc_lport_reset(fip->lp); | ||
1286 | fcoe_ctlr_solicit(fip, NULL); | ||
1262 | } else { | 1287 | } else { |
1263 | LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n"); | 1288 | int i; |
1264 | 1289 | ||
1265 | if (is_vn_port) | 1290 | LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n"); |
1266 | fc_lport_reset(vn_port); | 1291 | for (i = 0; i < num_vlink_desc; i++) { |
1267 | else { | 1292 | vp = vlink_desc_arr[i]; |
1268 | mutex_lock(&fip->ctlr_mutex); | 1293 | vn_port = fc_vport_id_lookup(lport, |
1269 | per_cpu_ptr(lport->dev_stats, | 1294 | ntoh24(vp->fd_fc_id)); |
1270 | get_cpu())->VLinkFailureCount++; | 1295 | if (!vn_port) |
1271 | put_cpu(); | 1296 | continue; |
1272 | fcoe_ctlr_reset(fip); | 1297 | |
1273 | mutex_unlock(&fip->ctlr_mutex); | 1298 | /* |
1299 | * 'port_id' is already validated, check MAC address and | ||
1300 | * wwpn | ||
1301 | */ | ||
1302 | if (compare_ether_addr(fip->get_src_addr(vn_port), | ||
1303 | vp->fd_mac) != 0 || | ||
1304 | get_unaligned_be64(&vp->fd_wwpn) != | ||
1305 | vn_port->wwpn) | ||
1306 | continue; | ||
1307 | |||
1308 | if (vn_port == lport) | ||
1309 | /* | ||
1310 | * Physical port, defer processing till all | ||
1311 | * listed NPIV ports are cleared | ||
1312 | */ | ||
1313 | reset_phys_port = 1; | ||
1314 | else /* NPIV port */ | ||
1315 | fc_lport_reset(vn_port); | ||
1316 | } | ||
1274 | 1317 | ||
1318 | if (reset_phys_port) { | ||
1275 | fc_lport_reset(fip->lp); | 1319 | fc_lport_reset(fip->lp); |
1276 | fcoe_ctlr_solicit(fip, NULL); | 1320 | fcoe_ctlr_solicit(fip, NULL); |
1277 | } | 1321 | } |
1278 | } | 1322 | } |
1323 | |||
1324 | err: | ||
1325 | kfree(vlink_desc_arr); | ||
1279 | } | 1326 | } |
1280 | 1327 | ||
1281 | /** | 1328 | /** |
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index f81f77c8569e..41068e8748e7 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c | |||
@@ -544,16 +544,6 @@ static int fcoe_transport_create(const char *buffer, struct kernel_param *kp) | |||
544 | struct fcoe_transport *ft = NULL; | 544 | struct fcoe_transport *ft = NULL; |
545 | enum fip_state fip_mode = (enum fip_state)(long)kp->arg; | 545 | enum fip_state fip_mode = (enum fip_state)(long)kp->arg; |
546 | 546 | ||
547 | #ifdef CONFIG_LIBFCOE_MODULE | ||
548 | /* | ||
549 | * Make sure the module has been initialized, and is not about to be | ||
550 | * removed. Module parameter sysfs files are writable before the | ||
551 | * module_init function is called and after module_exit. | ||
552 | */ | ||
553 | if (THIS_MODULE->state != MODULE_STATE_LIVE) | ||
554 | goto out_nodev; | ||
555 | #endif | ||
556 | |||
557 | mutex_lock(&ft_mutex); | 547 | mutex_lock(&ft_mutex); |
558 | 548 | ||
559 | netdev = fcoe_if_to_netdev(buffer); | 549 | netdev = fcoe_if_to_netdev(buffer); |
@@ -618,16 +608,6 @@ static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp) | |||
618 | struct net_device *netdev = NULL; | 608 | struct net_device *netdev = NULL; |
619 | struct fcoe_transport *ft = NULL; | 609 | struct fcoe_transport *ft = NULL; |
620 | 610 | ||
621 | #ifdef CONFIG_LIBFCOE_MODULE | ||
622 | /* | ||
623 | * Make sure the module has been initialized, and is not about to be | ||
624 | * removed. Module parameter sysfs files are writable before the | ||
625 | * module_init function is called and after module_exit. | ||
626 | */ | ||
627 | if (THIS_MODULE->state != MODULE_STATE_LIVE) | ||
628 | goto out_nodev; | ||
629 | #endif | ||
630 | |||
631 | mutex_lock(&ft_mutex); | 611 | mutex_lock(&ft_mutex); |
632 | 612 | ||
633 | netdev = fcoe_if_to_netdev(buffer); | 613 | netdev = fcoe_if_to_netdev(buffer); |
@@ -672,16 +652,6 @@ static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp) | |||
672 | struct net_device *netdev = NULL; | 652 | struct net_device *netdev = NULL; |
673 | struct fcoe_transport *ft = NULL; | 653 | struct fcoe_transport *ft = NULL; |
674 | 654 | ||
675 | #ifdef CONFIG_LIBFCOE_MODULE | ||
676 | /* | ||
677 | * Make sure the module has been initialized, and is not about to be | ||
678 | * removed. Module parameter sysfs files are writable before the | ||
679 | * module_init function is called and after module_exit. | ||
680 | */ | ||
681 | if (THIS_MODULE->state != MODULE_STATE_LIVE) | ||
682 | goto out_nodev; | ||
683 | #endif | ||
684 | |||
685 | mutex_lock(&ft_mutex); | 655 | mutex_lock(&ft_mutex); |
686 | 656 | ||
687 | netdev = fcoe_if_to_netdev(buffer); | 657 | netdev = fcoe_if_to_netdev(buffer); |
@@ -720,16 +690,6 @@ static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp) | |||
720 | struct net_device *netdev = NULL; | 690 | struct net_device *netdev = NULL; |
721 | struct fcoe_transport *ft = NULL; | 691 | struct fcoe_transport *ft = NULL; |
722 | 692 | ||
723 | #ifdef CONFIG_LIBFCOE_MODULE | ||
724 | /* | ||
725 | * Make sure the module has been initialized, and is not about to be | ||
726 | * removed. Module parameter sysfs files are writable before the | ||
727 | * module_init function is called and after module_exit. | ||
728 | */ | ||
729 | if (THIS_MODULE->state != MODULE_STATE_LIVE) | ||
730 | goto out_nodev; | ||
731 | #endif | ||
732 | |||
733 | mutex_lock(&ft_mutex); | 693 | mutex_lock(&ft_mutex); |
734 | 694 | ||
735 | netdev = fcoe_if_to_netdev(buffer); | 695 | netdev = fcoe_if_to_netdev(buffer); |
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c index 92109b126391..112f1bec7756 100644 --- a/drivers/scsi/in2000.c +++ b/drivers/scsi/in2000.c | |||
@@ -2227,7 +2227,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start, | |||
2227 | bp = buf; | 2227 | bp = buf; |
2228 | *bp = '\0'; | 2228 | *bp = '\0'; |
2229 | if (hd->proc & PR_VERSION) { | 2229 | if (hd->proc & PR_VERSION) { |
2230 | sprintf(tbuf, "\nVersion %s - %s. Compiled %s %s", IN2000_VERSION, IN2000_DATE, __DATE__, __TIME__); | 2230 | sprintf(tbuf, "\nVersion %s - %s.", IN2000_VERSION, IN2000_DATE); |
2231 | strcat(bp, tbuf); | 2231 | strcat(bp, tbuf); |
2232 | } | 2232 | } |
2233 | if (hd->proc & PR_INFO) { | 2233 | if (hd->proc & PR_INFO) { |
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 12868ca46110..888086c4e709 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -5149,21 +5149,21 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
5149 | 5149 | ||
5150 | if (ipr_cmd != NULL) { | 5150 | if (ipr_cmd != NULL) { |
5151 | /* Clear the PCI interrupt */ | 5151 | /* Clear the PCI interrupt */ |
5152 | num_hrrq = 0; | ||
5152 | do { | 5153 | do { |
5153 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); | 5154 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); |
5154 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); | 5155 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); |
5155 | } while (int_reg & IPR_PCII_HRRQ_UPDATED && | 5156 | } while (int_reg & IPR_PCII_HRRQ_UPDATED && |
5156 | num_hrrq++ < IPR_MAX_HRRQ_RETRIES); | 5157 | num_hrrq++ < IPR_MAX_HRRQ_RETRIES); |
5157 | 5158 | ||
5158 | if (int_reg & IPR_PCII_HRRQ_UPDATED) { | ||
5159 | ipr_isr_eh(ioa_cfg, "Error clearing HRRQ"); | ||
5160 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
5161 | return IRQ_HANDLED; | ||
5162 | } | ||
5163 | |||
5164 | } else if (rc == IRQ_NONE && irq_none == 0) { | 5159 | } else if (rc == IRQ_NONE && irq_none == 0) { |
5165 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); | 5160 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); |
5166 | irq_none++; | 5161 | irq_none++; |
5162 | } else if (num_hrrq == IPR_MAX_HRRQ_RETRIES && | ||
5163 | int_reg & IPR_PCII_HRRQ_UPDATED) { | ||
5164 | ipr_isr_eh(ioa_cfg, "Error clearing HRRQ"); | ||
5165 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
5166 | return IRQ_HANDLED; | ||
5167 | } else | 5167 | } else |
5168 | break; | 5168 | break; |
5169 | } | 5169 | } |
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 911b2736cafa..b9cb8140b398 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c | |||
@@ -205,6 +205,7 @@ static void fc_disc_recv_req(struct fc_lport *lport, struct fc_frame *fp) | |||
205 | default: | 205 | default: |
206 | FC_DISC_DBG(disc, "Received an unsupported request, " | 206 | FC_DISC_DBG(disc, "Received an unsupported request, " |
207 | "the opcode is (%x)\n", op); | 207 | "the opcode is (%x)\n", op); |
208 | fc_frame_free(fp); | ||
208 | break; | 209 | break; |
209 | } | 210 | } |
210 | } | 211 | } |
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 77035a746f60..3b8a6451ea28 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c | |||
@@ -1434,6 +1434,7 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) | |||
1434 | (f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) == | 1434 | (f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) == |
1435 | (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) { | 1435 | (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) { |
1436 | spin_lock_bh(&ep->ex_lock); | 1436 | spin_lock_bh(&ep->ex_lock); |
1437 | resp = ep->resp; | ||
1437 | rc = fc_exch_done_locked(ep); | 1438 | rc = fc_exch_done_locked(ep); |
1438 | WARN_ON(fc_seq_exch(sp) != ep); | 1439 | WARN_ON(fc_seq_exch(sp) != ep); |
1439 | spin_unlock_bh(&ep->ex_lock); | 1440 | spin_unlock_bh(&ep->ex_lock); |
@@ -1978,6 +1979,7 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport, | |||
1978 | spin_unlock_bh(&ep->ex_lock); | 1979 | spin_unlock_bh(&ep->ex_lock); |
1979 | return sp; | 1980 | return sp; |
1980 | err: | 1981 | err: |
1982 | fc_fcp_ddp_done(fr_fsp(fp)); | ||
1981 | rc = fc_exch_done_locked(ep); | 1983 | rc = fc_exch_done_locked(ep); |
1982 | spin_unlock_bh(&ep->ex_lock); | 1984 | spin_unlock_bh(&ep->ex_lock); |
1983 | if (!rc) | 1985 | if (!rc) |
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 2a3a4720a771..9cd2149519ac 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c | |||
@@ -312,7 +312,7 @@ void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid) | |||
312 | * DDP related resources for a fcp_pkt | 312 | * DDP related resources for a fcp_pkt |
313 | * @fsp: The FCP packet that DDP had been used on | 313 | * @fsp: The FCP packet that DDP had been used on |
314 | */ | 314 | */ |
315 | static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp) | 315 | void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp) |
316 | { | 316 | { |
317 | struct fc_lport *lport; | 317 | struct fc_lport *lport; |
318 | 318 | ||
@@ -681,8 +681,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, | |||
681 | error = lport->tt.seq_send(lport, seq, fp); | 681 | error = lport->tt.seq_send(lport, seq, fp); |
682 | if (error) { | 682 | if (error) { |
683 | WARN_ON(1); /* send error should be rare */ | 683 | WARN_ON(1); /* send error should be rare */ |
684 | fc_fcp_retry_cmd(fsp); | 684 | return error; |
685 | return 0; | ||
686 | } | 685 | } |
687 | fp = NULL; | 686 | fp = NULL; |
688 | } | 687 | } |
@@ -1673,7 +1672,8 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) | |||
1673 | FC_FCTL_REQ, 0); | 1672 | FC_FCTL_REQ, 0); |
1674 | 1673 | ||
1675 | rec_tov = get_fsp_rec_tov(fsp); | 1674 | rec_tov = get_fsp_rec_tov(fsp); |
1676 | seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL, | 1675 | seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, |
1676 | fc_fcp_pkt_destroy, | ||
1677 | fsp, jiffies_to_msecs(rec_tov)); | 1677 | fsp, jiffies_to_msecs(rec_tov)); |
1678 | if (!seq) | 1678 | if (!seq) |
1679 | goto retry; | 1679 | goto retry; |
@@ -1720,7 +1720,6 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) | |||
1720 | return; | 1720 | return; |
1721 | } | 1721 | } |
1722 | 1722 | ||
1723 | fsp->recov_seq = NULL; | ||
1724 | switch (fc_frame_payload_op(fp)) { | 1723 | switch (fc_frame_payload_op(fp)) { |
1725 | case ELS_LS_ACC: | 1724 | case ELS_LS_ACC: |
1726 | fsp->recov_retry = 0; | 1725 | fsp->recov_retry = 0; |
@@ -1732,10 +1731,9 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) | |||
1732 | break; | 1731 | break; |
1733 | } | 1732 | } |
1734 | fc_fcp_unlock_pkt(fsp); | 1733 | fc_fcp_unlock_pkt(fsp); |
1735 | fsp->lp->tt.exch_done(seq); | ||
1736 | out: | 1734 | out: |
1735 | fsp->lp->tt.exch_done(seq); | ||
1737 | fc_frame_free(fp); | 1736 | fc_frame_free(fp); |
1738 | fc_fcp_pkt_release(fsp); /* drop hold for outstanding SRR */ | ||
1739 | } | 1737 | } |
1740 | 1738 | ||
1741 | /** | 1739 | /** |
@@ -1747,8 +1745,6 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) | |||
1747 | { | 1745 | { |
1748 | if (fc_fcp_lock_pkt(fsp)) | 1746 | if (fc_fcp_lock_pkt(fsp)) |
1749 | goto out; | 1747 | goto out; |
1750 | fsp->lp->tt.exch_done(fsp->recov_seq); | ||
1751 | fsp->recov_seq = NULL; | ||
1752 | switch (PTR_ERR(fp)) { | 1748 | switch (PTR_ERR(fp)) { |
1753 | case -FC_EX_TIMEOUT: | 1749 | case -FC_EX_TIMEOUT: |
1754 | if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) | 1750 | if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) |
@@ -1764,7 +1760,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) | |||
1764 | } | 1760 | } |
1765 | fc_fcp_unlock_pkt(fsp); | 1761 | fc_fcp_unlock_pkt(fsp); |
1766 | out: | 1762 | out: |
1767 | fc_fcp_pkt_release(fsp); /* drop hold for outstanding SRR */ | 1763 | fsp->lp->tt.exch_done(fsp->recov_seq); |
1768 | } | 1764 | } |
1769 | 1765 | ||
1770 | /** | 1766 | /** |
diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h index fedc819d70c0..c7d071289af5 100644 --- a/drivers/scsi/libfc/fc_libfc.h +++ b/drivers/scsi/libfc/fc_libfc.h | |||
@@ -108,6 +108,7 @@ extern struct fc4_prov fc_rport_fcp_init; /* FCP initiator provider */ | |||
108 | * Set up direct-data placement for this I/O request | 108 | * Set up direct-data placement for this I/O request |
109 | */ | 109 | */ |
110 | void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid); | 110 | void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid); |
111 | void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp); | ||
111 | 112 | ||
112 | /* | 113 | /* |
113 | * Module setup functions | 114 | * Module setup functions |
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 31fc21f4d831..db9238f2ecb8 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c | |||
@@ -99,19 +99,29 @@ static void sas_ata_task_done(struct sas_task *task) | |||
99 | struct sas_ha_struct *sas_ha; | 99 | struct sas_ha_struct *sas_ha; |
100 | enum ata_completion_errors ac; | 100 | enum ata_completion_errors ac; |
101 | unsigned long flags; | 101 | unsigned long flags; |
102 | struct ata_link *link; | ||
102 | 103 | ||
103 | if (!qc) | 104 | if (!qc) |
104 | goto qc_already_gone; | 105 | goto qc_already_gone; |
105 | 106 | ||
106 | dev = qc->ap->private_data; | 107 | dev = qc->ap->private_data; |
107 | sas_ha = dev->port->ha; | 108 | sas_ha = dev->port->ha; |
109 | link = &dev->sata_dev.ap->link; | ||
108 | 110 | ||
109 | spin_lock_irqsave(dev->sata_dev.ap->lock, flags); | 111 | spin_lock_irqsave(dev->sata_dev.ap->lock, flags); |
110 | if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD || | 112 | if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD || |
111 | ((stat->stat == SAM_STAT_CHECK_CONDITION && | 113 | ((stat->stat == SAM_STAT_CHECK_CONDITION && |
112 | dev->sata_dev.command_set == ATAPI_COMMAND_SET))) { | 114 | dev->sata_dev.command_set == ATAPI_COMMAND_SET))) { |
113 | ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf); | 115 | ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf); |
114 | qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command); | 116 | |
117 | if (!link->sactive) { | ||
118 | qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command); | ||
119 | } else { | ||
120 | link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.tf.command); | ||
121 | if (unlikely(link->eh_info.err_mask)) | ||
122 | qc->flags |= ATA_QCFLAG_FAILED; | ||
123 | } | ||
124 | |||
115 | dev->sata_dev.sstatus = resp->sstatus; | 125 | dev->sata_dev.sstatus = resp->sstatus; |
116 | dev->sata_dev.serror = resp->serror; | 126 | dev->sata_dev.serror = resp->serror; |
117 | dev->sata_dev.scontrol = resp->scontrol; | 127 | dev->sata_dev.scontrol = resp->scontrol; |
@@ -121,7 +131,13 @@ static void sas_ata_task_done(struct sas_task *task) | |||
121 | SAS_DPRINTK("%s: SAS error %x\n", __func__, | 131 | SAS_DPRINTK("%s: SAS error %x\n", __func__, |
122 | stat->stat); | 132 | stat->stat); |
123 | /* We saw a SAS error. Send a vague error. */ | 133 | /* We saw a SAS error. Send a vague error. */ |
124 | qc->err_mask = ac; | 134 | if (!link->sactive) { |
135 | qc->err_mask = ac; | ||
136 | } else { | ||
137 | link->eh_info.err_mask |= AC_ERR_DEV; | ||
138 | qc->flags |= ATA_QCFLAG_FAILED; | ||
139 | } | ||
140 | |||
125 | dev->sata_dev.tf.feature = 0x04; /* status err */ | 141 | dev->sata_dev.tf.feature = 0x04; /* status err */ |
126 | dev->sata_dev.tf.command = ATA_ERR; | 142 | dev->sata_dev.tf.command = ATA_ERR; |
127 | } | 143 | } |
@@ -279,6 +295,44 @@ static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class, | |||
279 | return ret; | 295 | return ret; |
280 | } | 296 | } |
281 | 297 | ||
298 | static int sas_ata_soft_reset(struct ata_link *link, unsigned int *class, | ||
299 | unsigned long deadline) | ||
300 | { | ||
301 | struct ata_port *ap = link->ap; | ||
302 | struct domain_device *dev = ap->private_data; | ||
303 | struct sas_internal *i = | ||
304 | to_sas_internal(dev->port->ha->core.shost->transportt); | ||
305 | int res = TMF_RESP_FUNC_FAILED; | ||
306 | int ret = 0; | ||
307 | |||
308 | if (i->dft->lldd_ata_soft_reset) | ||
309 | res = i->dft->lldd_ata_soft_reset(dev); | ||
310 | |||
311 | if (res != TMF_RESP_FUNC_COMPLETE) { | ||
312 | SAS_DPRINTK("%s: Unable to soft reset\n", __func__); | ||
313 | ret = -EAGAIN; | ||
314 | } | ||
315 | |||
316 | switch (dev->sata_dev.command_set) { | ||
317 | case ATA_COMMAND_SET: | ||
318 | SAS_DPRINTK("%s: Found ATA device.\n", __func__); | ||
319 | *class = ATA_DEV_ATA; | ||
320 | break; | ||
321 | case ATAPI_COMMAND_SET: | ||
322 | SAS_DPRINTK("%s: Found ATAPI device.\n", __func__); | ||
323 | *class = ATA_DEV_ATAPI; | ||
324 | break; | ||
325 | default: | ||
326 | SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", | ||
327 | __func__, dev->sata_dev.command_set); | ||
328 | *class = ATA_DEV_UNKNOWN; | ||
329 | break; | ||
330 | } | ||
331 | |||
332 | ap->cbl = ATA_CBL_SATA; | ||
333 | return ret; | ||
334 | } | ||
335 | |||
282 | static void sas_ata_post_internal(struct ata_queued_cmd *qc) | 336 | static void sas_ata_post_internal(struct ata_queued_cmd *qc) |
283 | { | 337 | { |
284 | if (qc->flags & ATA_QCFLAG_FAILED) | 338 | if (qc->flags & ATA_QCFLAG_FAILED) |
@@ -309,7 +363,7 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc) | |||
309 | 363 | ||
310 | static struct ata_port_operations sas_sata_ops = { | 364 | static struct ata_port_operations sas_sata_ops = { |
311 | .prereset = ata_std_prereset, | 365 | .prereset = ata_std_prereset, |
312 | .softreset = NULL, | 366 | .softreset = sas_ata_soft_reset, |
313 | .hardreset = sas_ata_hard_reset, | 367 | .hardreset = sas_ata_hard_reset, |
314 | .postreset = ata_std_postreset, | 368 | .postreset = ata_std_postreset, |
315 | .error_handler = ata_std_error_handler, | 369 | .error_handler = ata_std_error_handler, |
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index 8b538bd1ff2b..14e21b5fb8ba 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h | |||
@@ -57,7 +57,7 @@ int sas_init_queue(struct sas_ha_struct *sas_ha); | |||
57 | int sas_init_events(struct sas_ha_struct *sas_ha); | 57 | int sas_init_events(struct sas_ha_struct *sas_ha); |
58 | void sas_shutdown_queue(struct sas_ha_struct *sas_ha); | 58 | void sas_shutdown_queue(struct sas_ha_struct *sas_ha); |
59 | 59 | ||
60 | void sas_deform_port(struct asd_sas_phy *phy); | 60 | void sas_deform_port(struct asd_sas_phy *phy, int gone); |
61 | 61 | ||
62 | void sas_porte_bytes_dmaed(struct work_struct *work); | 62 | void sas_porte_bytes_dmaed(struct work_struct *work); |
63 | void sas_porte_broadcast_rcvd(struct work_struct *work); | 63 | void sas_porte_broadcast_rcvd(struct work_struct *work); |
diff --git a/drivers/scsi/libsas/sas_phy.c b/drivers/scsi/libsas/sas_phy.c index b459c4b635b1..e0f5018e9071 100644 --- a/drivers/scsi/libsas/sas_phy.c +++ b/drivers/scsi/libsas/sas_phy.c | |||
@@ -39,7 +39,7 @@ static void sas_phye_loss_of_signal(struct work_struct *work) | |||
39 | sas_begin_event(PHYE_LOSS_OF_SIGNAL, &phy->ha->event_lock, | 39 | sas_begin_event(PHYE_LOSS_OF_SIGNAL, &phy->ha->event_lock, |
40 | &phy->phy_events_pending); | 40 | &phy->phy_events_pending); |
41 | phy->error = 0; | 41 | phy->error = 0; |
42 | sas_deform_port(phy); | 42 | sas_deform_port(phy, 1); |
43 | } | 43 | } |
44 | 44 | ||
45 | static void sas_phye_oob_done(struct work_struct *work) | 45 | static void sas_phye_oob_done(struct work_struct *work) |
@@ -66,7 +66,7 @@ static void sas_phye_oob_error(struct work_struct *work) | |||
66 | sas_begin_event(PHYE_OOB_ERROR, &phy->ha->event_lock, | 66 | sas_begin_event(PHYE_OOB_ERROR, &phy->ha->event_lock, |
67 | &phy->phy_events_pending); | 67 | &phy->phy_events_pending); |
68 | 68 | ||
69 | sas_deform_port(phy); | 69 | sas_deform_port(phy, 1); |
70 | 70 | ||
71 | if (!port && phy->enabled && i->dft->lldd_control_phy) { | 71 | if (!port && phy->enabled && i->dft->lldd_control_phy) { |
72 | phy->error++; | 72 | phy->error++; |
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index 5257fdfe699a..42fd1f25b664 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c | |||
@@ -57,7 +57,7 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
57 | 57 | ||
58 | if (port) { | 58 | if (port) { |
59 | if (!phy_is_wideport_member(port, phy)) | 59 | if (!phy_is_wideport_member(port, phy)) |
60 | sas_deform_port(phy); | 60 | sas_deform_port(phy, 0); |
61 | else { | 61 | else { |
62 | SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n", | 62 | SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n", |
63 | __func__, phy->id, phy->port->id, | 63 | __func__, phy->id, phy->port->id, |
@@ -153,28 +153,31 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
153 | * This is called when the physical link to the other phy has been | 153 | * This is called when the physical link to the other phy has been |
154 | * lost (on this phy), in Event thread context. We cannot delay here. | 154 | * lost (on this phy), in Event thread context. We cannot delay here. |
155 | */ | 155 | */ |
156 | void sas_deform_port(struct asd_sas_phy *phy) | 156 | void sas_deform_port(struct asd_sas_phy *phy, int gone) |
157 | { | 157 | { |
158 | struct sas_ha_struct *sas_ha = phy->ha; | 158 | struct sas_ha_struct *sas_ha = phy->ha; |
159 | struct asd_sas_port *port = phy->port; | 159 | struct asd_sas_port *port = phy->port; |
160 | struct sas_internal *si = | 160 | struct sas_internal *si = |
161 | to_sas_internal(sas_ha->core.shost->transportt); | 161 | to_sas_internal(sas_ha->core.shost->transportt); |
162 | struct domain_device *dev; | ||
162 | unsigned long flags; | 163 | unsigned long flags; |
163 | 164 | ||
164 | if (!port) | 165 | if (!port) |
165 | return; /* done by a phy event */ | 166 | return; /* done by a phy event */ |
166 | 167 | ||
167 | if (port->port_dev) | 168 | dev = port->port_dev; |
168 | port->port_dev->pathways--; | 169 | if (dev) |
170 | dev->pathways--; | ||
169 | 171 | ||
170 | if (port->num_phys == 1) { | 172 | if (port->num_phys == 1) { |
173 | if (dev && gone) | ||
174 | dev->gone = 1; | ||
171 | sas_unregister_domain_devices(port); | 175 | sas_unregister_domain_devices(port); |
172 | sas_port_delete(port->port); | 176 | sas_port_delete(port->port); |
173 | port->port = NULL; | 177 | port->port = NULL; |
174 | } else | 178 | } else |
175 | sas_port_delete_phy(port->port, phy->phy); | 179 | sas_port_delete_phy(port->port, phy->phy); |
176 | 180 | ||
177 | |||
178 | if (si->dft->lldd_port_deformed) | 181 | if (si->dft->lldd_port_deformed) |
179 | si->dft->lldd_port_deformed(phy); | 182 | si->dft->lldd_port_deformed(phy); |
180 | 183 | ||
@@ -244,7 +247,7 @@ void sas_porte_link_reset_err(struct work_struct *work) | |||
244 | sas_begin_event(PORTE_LINK_RESET_ERR, &phy->ha->event_lock, | 247 | sas_begin_event(PORTE_LINK_RESET_ERR, &phy->ha->event_lock, |
245 | &phy->port_events_pending); | 248 | &phy->port_events_pending); |
246 | 249 | ||
247 | sas_deform_port(phy); | 250 | sas_deform_port(phy, 1); |
248 | } | 251 | } |
249 | 252 | ||
250 | void sas_porte_timer_event(struct work_struct *work) | 253 | void sas_porte_timer_event(struct work_struct *work) |
@@ -256,7 +259,7 @@ void sas_porte_timer_event(struct work_struct *work) | |||
256 | sas_begin_event(PORTE_TIMER_EVENT, &phy->ha->event_lock, | 259 | sas_begin_event(PORTE_TIMER_EVENT, &phy->ha->event_lock, |
257 | &phy->port_events_pending); | 260 | &phy->port_events_pending); |
258 | 261 | ||
259 | sas_deform_port(phy); | 262 | sas_deform_port(phy, 1); |
260 | } | 263 | } |
261 | 264 | ||
262 | void sas_porte_hard_reset(struct work_struct *work) | 265 | void sas_porte_hard_reset(struct work_struct *work) |
@@ -268,7 +271,7 @@ void sas_porte_hard_reset(struct work_struct *work) | |||
268 | sas_begin_event(PORTE_HARD_RESET, &phy->ha->event_lock, | 271 | sas_begin_event(PORTE_HARD_RESET, &phy->ha->event_lock, |
269 | &phy->port_events_pending); | 272 | &phy->port_events_pending); |
270 | 273 | ||
271 | sas_deform_port(phy); | 274 | sas_deform_port(phy, 1); |
272 | } | 275 | } |
273 | 276 | ||
274 | /* ---------- SAS port registration ---------- */ | 277 | /* ---------- SAS port registration ---------- */ |
@@ -306,6 +309,6 @@ void sas_unregister_ports(struct sas_ha_struct *sas_ha) | |||
306 | 309 | ||
307 | for (i = 0; i < sas_ha->num_phys; i++) | 310 | for (i = 0; i < sas_ha->num_phys; i++) |
308 | if (sas_ha->sas_phy[i]->port) | 311 | if (sas_ha->sas_phy[i]->port) |
309 | sas_deform_port(sas_ha->sas_phy[i]); | 312 | sas_deform_port(sas_ha->sas_phy[i], 0); |
310 | 313 | ||
311 | } | 314 | } |
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index f6e189f40917..eeba76cdf774 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -207,6 +207,13 @@ static int sas_queuecommand_lck(struct scsi_cmnd *cmd, | |||
207 | struct sas_ha_struct *sas_ha = dev->port->ha; | 207 | struct sas_ha_struct *sas_ha = dev->port->ha; |
208 | struct sas_task *task; | 208 | struct sas_task *task; |
209 | 209 | ||
210 | /* If the device fell off, no sense in issuing commands */ | ||
211 | if (dev->gone) { | ||
212 | cmd->result = DID_BAD_TARGET << 16; | ||
213 | scsi_done(cmd); | ||
214 | goto out; | ||
215 | } | ||
216 | |||
210 | if (dev_is_sata(dev)) { | 217 | if (dev_is_sata(dev)) { |
211 | unsigned long flags; | 218 | unsigned long flags; |
212 | 219 | ||
@@ -216,13 +223,6 @@ static int sas_queuecommand_lck(struct scsi_cmnd *cmd, | |||
216 | goto out; | 223 | goto out; |
217 | } | 224 | } |
218 | 225 | ||
219 | /* If the device fell off, no sense in issuing commands */ | ||
220 | if (dev->gone) { | ||
221 | cmd->result = DID_BAD_TARGET << 16; | ||
222 | scsi_done(cmd); | ||
223 | goto out; | ||
224 | } | ||
225 | |||
226 | res = -ENOMEM; | 226 | res = -ENOMEM; |
227 | task = sas_create_task(cmd, dev, GFP_ATOMIC); | 227 | task = sas_create_task(cmd, dev, GFP_ATOMIC); |
228 | if (!task) | 228 | if (!task) |
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 02d53d89534f..8ec2c86a49d4 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -41,6 +41,7 @@ struct lpfc_sli2_slim; | |||
41 | downloads using bsg */ | 41 | downloads using bsg */ |
42 | #define LPFC_DEFAULT_PROT_SG_SEG_CNT 4096 /* sg protection elements count */ | 42 | #define LPFC_DEFAULT_PROT_SG_SEG_CNT 4096 /* sg protection elements count */ |
43 | #define LPFC_MAX_SG_SEG_CNT 4096 /* sg element count per scsi cmnd */ | 43 | #define LPFC_MAX_SG_SEG_CNT 4096 /* sg element count per scsi cmnd */ |
44 | #define LPFC_MAX_SGE_SIZE 0x80000000 /* Maximum data allowed in a SGE */ | ||
44 | #define LPFC_MAX_PROT_SG_SEG_CNT 4096 /* prot sg element count per scsi cmd*/ | 45 | #define LPFC_MAX_PROT_SG_SEG_CNT 4096 /* prot sg element count per scsi cmd*/ |
45 | #define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */ | 46 | #define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */ |
46 | #define LPFC_Q_RAMP_UP_INTERVAL 120 /* lun q_depth ramp up interval */ | 47 | #define LPFC_Q_RAMP_UP_INTERVAL 120 /* lun q_depth ramp up interval */ |
@@ -486,6 +487,42 @@ struct unsol_rcv_ct_ctx { | |||
486 | (1 << LPFC_USER_LINK_SPEED_AUTO)) | 487 | (1 << LPFC_USER_LINK_SPEED_AUTO)) |
487 | #define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16" | 488 | #define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16" |
488 | 489 | ||
490 | enum nemb_type { | ||
491 | nemb_mse = 1, | ||
492 | nemb_hbd | ||
493 | }; | ||
494 | |||
495 | enum mbox_type { | ||
496 | mbox_rd = 1, | ||
497 | mbox_wr | ||
498 | }; | ||
499 | |||
500 | enum dma_type { | ||
501 | dma_mbox = 1, | ||
502 | dma_ebuf | ||
503 | }; | ||
504 | |||
505 | enum sta_type { | ||
506 | sta_pre_addr = 1, | ||
507 | sta_pos_addr | ||
508 | }; | ||
509 | |||
510 | struct lpfc_mbox_ext_buf_ctx { | ||
511 | uint32_t state; | ||
512 | #define LPFC_BSG_MBOX_IDLE 0 | ||
513 | #define LPFC_BSG_MBOX_HOST 1 | ||
514 | #define LPFC_BSG_MBOX_PORT 2 | ||
515 | #define LPFC_BSG_MBOX_DONE 3 | ||
516 | #define LPFC_BSG_MBOX_ABTS 4 | ||
517 | enum nemb_type nembType; | ||
518 | enum mbox_type mboxType; | ||
519 | uint32_t numBuf; | ||
520 | uint32_t mbxTag; | ||
521 | uint32_t seqNum; | ||
522 | struct lpfc_dmabuf *mbx_dmabuf; | ||
523 | struct list_head ext_dmabuf_list; | ||
524 | }; | ||
525 | |||
489 | struct lpfc_hba { | 526 | struct lpfc_hba { |
490 | /* SCSI interface function jump table entries */ | 527 | /* SCSI interface function jump table entries */ |
491 | int (*lpfc_new_scsi_buf) | 528 | int (*lpfc_new_scsi_buf) |
@@ -589,6 +626,7 @@ struct lpfc_hba { | |||
589 | 626 | ||
590 | MAILBOX_t *mbox; | 627 | MAILBOX_t *mbox; |
591 | uint32_t *mbox_ext; | 628 | uint32_t *mbox_ext; |
629 | struct lpfc_mbox_ext_buf_ctx mbox_ext_buf_ctx; | ||
592 | uint32_t ha_copy; | 630 | uint32_t ha_copy; |
593 | struct _PCB *pcb; | 631 | struct _PCB *pcb; |
594 | struct _IOCB *IOCBs; | 632 | struct _IOCB *IOCBs; |
@@ -659,6 +697,7 @@ struct lpfc_hba { | |||
659 | uint32_t cfg_hostmem_hgp; | 697 | uint32_t cfg_hostmem_hgp; |
660 | uint32_t cfg_log_verbose; | 698 | uint32_t cfg_log_verbose; |
661 | uint32_t cfg_aer_support; | 699 | uint32_t cfg_aer_support; |
700 | uint32_t cfg_sriov_nr_virtfn; | ||
662 | uint32_t cfg_iocb_cnt; | 701 | uint32_t cfg_iocb_cnt; |
663 | uint32_t cfg_suppress_link_up; | 702 | uint32_t cfg_suppress_link_up; |
664 | #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ | 703 | #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ |
@@ -706,7 +745,6 @@ struct lpfc_hba { | |||
706 | uint32_t *hbq_get; /* Host mem address of HBQ get ptrs */ | 745 | uint32_t *hbq_get; /* Host mem address of HBQ get ptrs */ |
707 | 746 | ||
708 | int brd_no; /* FC board number */ | 747 | int brd_no; /* FC board number */ |
709 | |||
710 | char SerialNumber[32]; /* adapter Serial Number */ | 748 | char SerialNumber[32]; /* adapter Serial Number */ |
711 | char OptionROMVersion[32]; /* adapter BIOS / Fcode version */ | 749 | char OptionROMVersion[32]; /* adapter BIOS / Fcode version */ |
712 | char ModelDesc[256]; /* Model Description */ | 750 | char ModelDesc[256]; /* Model Description */ |
@@ -778,6 +816,9 @@ struct lpfc_hba { | |||
778 | uint16_t vpi_base; | 816 | uint16_t vpi_base; |
779 | uint16_t vfi_base; | 817 | uint16_t vfi_base; |
780 | unsigned long *vpi_bmask; /* vpi allocation table */ | 818 | unsigned long *vpi_bmask; /* vpi allocation table */ |
819 | uint16_t *vpi_ids; | ||
820 | uint16_t vpi_count; | ||
821 | struct list_head lpfc_vpi_blk_list; | ||
781 | 822 | ||
782 | /* Data structure used by fabric iocb scheduler */ | 823 | /* Data structure used by fabric iocb scheduler */ |
783 | struct list_head fabric_iocb_list; | 824 | struct list_head fabric_iocb_list; |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 8dcbf8fff673..135a53baa735 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -755,6 +755,73 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr, | |||
755 | } | 755 | } |
756 | 756 | ||
757 | /** | 757 | /** |
758 | * lpfc_sli4_pdev_reg_request - Request physical dev to perform a register acc | ||
759 | * @phba: lpfc_hba pointer. | ||
760 | * | ||
761 | * Description: | ||
762 | * Request SLI4 interface type-2 device to perform a physical register set | ||
763 | * access. | ||
764 | * | ||
765 | * Returns: | ||
766 | * zero for success | ||
767 | **/ | ||
768 | static ssize_t | ||
769 | lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) | ||
770 | { | ||
771 | struct completion online_compl; | ||
772 | uint32_t reg_val; | ||
773 | int status = 0; | ||
774 | int rc; | ||
775 | |||
776 | if (!phba->cfg_enable_hba_reset) | ||
777 | return -EIO; | ||
778 | |||
779 | if ((phba->sli_rev < LPFC_SLI_REV4) || | ||
780 | (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
781 | LPFC_SLI_INTF_IF_TYPE_2)) | ||
782 | return -EPERM; | ||
783 | |||
784 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); | ||
785 | |||
786 | if (status != 0) | ||
787 | return status; | ||
788 | |||
789 | /* wait for the device to be quiesced before firmware reset */ | ||
790 | msleep(100); | ||
791 | |||
792 | reg_val = readl(phba->sli4_hba.conf_regs_memmap_p + | ||
793 | LPFC_CTL_PDEV_CTL_OFFSET); | ||
794 | |||
795 | if (opcode == LPFC_FW_DUMP) | ||
796 | reg_val |= LPFC_FW_DUMP_REQUEST; | ||
797 | else if (opcode == LPFC_FW_RESET) | ||
798 | reg_val |= LPFC_CTL_PDEV_CTL_FRST; | ||
799 | else if (opcode == LPFC_DV_RESET) | ||
800 | reg_val |= LPFC_CTL_PDEV_CTL_DRST; | ||
801 | |||
802 | writel(reg_val, phba->sli4_hba.conf_regs_memmap_p + | ||
803 | LPFC_CTL_PDEV_CTL_OFFSET); | ||
804 | /* flush */ | ||
805 | readl(phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET); | ||
806 | |||
807 | /* delay driver action following IF_TYPE_2 reset */ | ||
808 | msleep(100); | ||
809 | |||
810 | init_completion(&online_compl); | ||
811 | rc = lpfc_workq_post_event(phba, &status, &online_compl, | ||
812 | LPFC_EVT_ONLINE); | ||
813 | if (rc == 0) | ||
814 | return -ENOMEM; | ||
815 | |||
816 | wait_for_completion(&online_compl); | ||
817 | |||
818 | if (status != 0) | ||
819 | return -EIO; | ||
820 | |||
821 | return 0; | ||
822 | } | ||
823 | |||
824 | /** | ||
758 | * lpfc_nport_evt_cnt_show - Return the number of nport events | 825 | * lpfc_nport_evt_cnt_show - Return the number of nport events |
759 | * @dev: class device that is converted into a Scsi_host. | 826 | * @dev: class device that is converted into a Scsi_host. |
760 | * @attr: device attribute, not used. | 827 | * @attr: device attribute, not used. |
@@ -848,6 +915,12 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr, | |||
848 | return -EINVAL; | 915 | return -EINVAL; |
849 | else | 916 | else |
850 | status = lpfc_do_offline(phba, LPFC_EVT_KILL); | 917 | status = lpfc_do_offline(phba, LPFC_EVT_KILL); |
918 | else if (strncmp(buf, "dump", sizeof("dump") - 1) == 0) | ||
919 | status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_DUMP); | ||
920 | else if (strncmp(buf, "fw_reset", sizeof("fw_reset") - 1) == 0) | ||
921 | status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_RESET); | ||
922 | else if (strncmp(buf, "dv_reset", sizeof("dv_reset") - 1) == 0) | ||
923 | status = lpfc_sli4_pdev_reg_request(phba, LPFC_DV_RESET); | ||
851 | else | 924 | else |
852 | return -EINVAL; | 925 | return -EINVAL; |
853 | 926 | ||
@@ -1322,6 +1395,102 @@ lpfc_dss_show(struct device *dev, struct device_attribute *attr, | |||
1322 | } | 1395 | } |
1323 | 1396 | ||
1324 | /** | 1397 | /** |
1398 | * lpfc_sriov_hw_max_virtfn_show - Return maximum number of virtual functions | ||
1399 | * @dev: class converted to a Scsi_host structure. | ||
1400 | * @attr: device attribute, not used. | ||
1401 | * @buf: on return contains the formatted support level. | ||
1402 | * | ||
1403 | * Description: | ||
1404 | * Returns the maximum number of virtual functions a physical function can | ||
1405 | * support, 0 will be returned if called on virtual function. | ||
1406 | * | ||
1407 | * Returns: size of formatted string. | ||
1408 | **/ | ||
1409 | static ssize_t | ||
1410 | lpfc_sriov_hw_max_virtfn_show(struct device *dev, | ||
1411 | struct device_attribute *attr, | ||
1412 | char *buf) | ||
1413 | { | ||
1414 | struct Scsi_Host *shost = class_to_shost(dev); | ||
1415 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
1416 | struct lpfc_hba *phba = vport->phba; | ||
1417 | struct pci_dev *pdev = phba->pcidev; | ||
1418 | union lpfc_sli4_cfg_shdr *shdr; | ||
1419 | uint32_t shdr_status, shdr_add_status; | ||
1420 | LPFC_MBOXQ_t *mboxq; | ||
1421 | struct lpfc_mbx_get_prof_cfg *get_prof_cfg; | ||
1422 | struct lpfc_rsrc_desc_pcie *desc; | ||
1423 | uint32_t max_nr_virtfn; | ||
1424 | uint32_t desc_count; | ||
1425 | int length, rc, i; | ||
1426 | |||
1427 | if ((phba->sli_rev < LPFC_SLI_REV4) || | ||
1428 | (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
1429 | LPFC_SLI_INTF_IF_TYPE_2)) | ||
1430 | return -EPERM; | ||
1431 | |||
1432 | if (!pdev->is_physfn) | ||
1433 | return snprintf(buf, PAGE_SIZE, "%d\n", 0); | ||
1434 | |||
1435 | mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
1436 | if (!mboxq) | ||
1437 | return -ENOMEM; | ||
1438 | |||
1439 | /* get the maximum number of virtfn support by physfn */ | ||
1440 | length = (sizeof(struct lpfc_mbx_get_prof_cfg) - | ||
1441 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
1442 | lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
1443 | LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG, | ||
1444 | length, LPFC_SLI4_MBX_EMBED); | ||
1445 | shdr = (union lpfc_sli4_cfg_shdr *) | ||
1446 | &mboxq->u.mqe.un.sli4_config.header.cfg_shdr; | ||
1447 | bf_set(lpfc_mbox_hdr_pf_num, &shdr->request, | ||
1448 | phba->sli4_hba.iov.pf_number + 1); | ||
1449 | |||
1450 | get_prof_cfg = &mboxq->u.mqe.un.get_prof_cfg; | ||
1451 | bf_set(lpfc_mbx_get_prof_cfg_prof_tp, &get_prof_cfg->u.request, | ||
1452 | LPFC_CFG_TYPE_CURRENT_ACTIVE); | ||
1453 | |||
1454 | rc = lpfc_sli_issue_mbox_wait(phba, mboxq, | ||
1455 | lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG)); | ||
1456 | |||
1457 | if (rc != MBX_TIMEOUT) { | ||
1458 | /* check return status */ | ||
1459 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
1460 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, | ||
1461 | &shdr->response); | ||
1462 | if (shdr_status || shdr_add_status || rc) | ||
1463 | goto error_out; | ||
1464 | |||
1465 | } else | ||
1466 | goto error_out; | ||
1467 | |||
1468 | desc_count = get_prof_cfg->u.response.prof_cfg.rsrc_desc_count; | ||
1469 | |||
1470 | for (i = 0; i < LPFC_RSRC_DESC_MAX_NUM; i++) { | ||
1471 | desc = (struct lpfc_rsrc_desc_pcie *) | ||
1472 | &get_prof_cfg->u.response.prof_cfg.desc[i]; | ||
1473 | if (LPFC_RSRC_DESC_TYPE_PCIE == | ||
1474 | bf_get(lpfc_rsrc_desc_pcie_type, desc)) { | ||
1475 | max_nr_virtfn = bf_get(lpfc_rsrc_desc_pcie_nr_virtfn, | ||
1476 | desc); | ||
1477 | break; | ||
1478 | } | ||
1479 | } | ||
1480 | |||
1481 | if (i < LPFC_RSRC_DESC_MAX_NUM) { | ||
1482 | if (rc != MBX_TIMEOUT) | ||
1483 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
1484 | return snprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn); | ||
1485 | } | ||
1486 | |||
1487 | error_out: | ||
1488 | if (rc != MBX_TIMEOUT) | ||
1489 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
1490 | return -EIO; | ||
1491 | } | ||
1492 | |||
1493 | /** | ||
1325 | * lpfc_param_show - Return a cfg attribute value in decimal | 1494 | * lpfc_param_show - Return a cfg attribute value in decimal |
1326 | * | 1495 | * |
1327 | * Description: | 1496 | * Description: |
@@ -1762,6 +1931,8 @@ static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); | |||
1762 | static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL); | 1931 | static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL); |
1763 | static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); | 1932 | static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); |
1764 | static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL); | 1933 | static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL); |
1934 | static DEVICE_ATTR(lpfc_sriov_hw_max_virtfn, S_IRUGO, | ||
1935 | lpfc_sriov_hw_max_virtfn_show, NULL); | ||
1765 | 1936 | ||
1766 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; | 1937 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; |
1767 | 1938 | ||
@@ -3014,7 +3185,7 @@ static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR, | |||
3014 | * | 3185 | * |
3015 | * @dev: class device that is converted into a Scsi_host. | 3186 | * @dev: class device that is converted into a Scsi_host. |
3016 | * @attr: device attribute, not used. | 3187 | * @attr: device attribute, not used. |
3017 | * @buf: containing the string "selective". | 3188 | * @buf: containing enable or disable aer flag. |
3018 | * @count: unused variable. | 3189 | * @count: unused variable. |
3019 | * | 3190 | * |
3020 | * Description: | 3191 | * Description: |
@@ -3098,7 +3269,7 @@ lpfc_param_show(aer_support) | |||
3098 | /** | 3269 | /** |
3099 | * lpfc_aer_support_init - Set the initial adapters aer support flag | 3270 | * lpfc_aer_support_init - Set the initial adapters aer support flag |
3100 | * @phba: lpfc_hba pointer. | 3271 | * @phba: lpfc_hba pointer. |
3101 | * @val: link speed value. | 3272 | * @val: enable aer or disable aer flag. |
3102 | * | 3273 | * |
3103 | * Description: | 3274 | * Description: |
3104 | * If val is in a valid range [0,1], then set the adapter's initial | 3275 | * If val is in a valid range [0,1], then set the adapter's initial |
@@ -3137,7 +3308,7 @@ static DEVICE_ATTR(lpfc_aer_support, S_IRUGO | S_IWUSR, | |||
3137 | * lpfc_aer_cleanup_state - Clean up aer state to the aer enabled device | 3308 | * lpfc_aer_cleanup_state - Clean up aer state to the aer enabled device |
3138 | * @dev: class device that is converted into a Scsi_host. | 3309 | * @dev: class device that is converted into a Scsi_host. |
3139 | * @attr: device attribute, not used. | 3310 | * @attr: device attribute, not used. |
3140 | * @buf: containing the string "selective". | 3311 | * @buf: containing flag 1 for aer cleanup state. |
3141 | * @count: unused variable. | 3312 | * @count: unused variable. |
3142 | * | 3313 | * |
3143 | * Description: | 3314 | * Description: |
@@ -3180,6 +3351,136 @@ lpfc_aer_cleanup_state(struct device *dev, struct device_attribute *attr, | |||
3180 | static DEVICE_ATTR(lpfc_aer_state_cleanup, S_IWUSR, NULL, | 3351 | static DEVICE_ATTR(lpfc_aer_state_cleanup, S_IWUSR, NULL, |
3181 | lpfc_aer_cleanup_state); | 3352 | lpfc_aer_cleanup_state); |
3182 | 3353 | ||
3354 | /** | ||
3355 | * lpfc_sriov_nr_virtfn_store - Enable the adapter for sr-iov virtual functions | ||
3356 | * | ||
3357 | * @dev: class device that is converted into a Scsi_host. | ||
3358 | * @attr: device attribute, not used. | ||
3359 | * @buf: containing the string the number of vfs to be enabled. | ||
3360 | * @count: unused variable. | ||
3361 | * | ||
3362 | * Description: | ||
3363 | * When this api is called either through user sysfs, the driver shall | ||
3364 | * try to enable or disable SR-IOV virtual functions according to the | ||
3365 | * following: | ||
3366 | * | ||
3367 | * If zero virtual function has been enabled to the physical function, | ||
3368 | * the driver shall invoke the pci enable virtual function api trying | ||
3369 | * to enable the virtual functions. If the nr_vfn provided is greater | ||
3370 | * than the maximum supported, the maximum virtual function number will | ||
3371 | * be used for invoking the api; otherwise, the nr_vfn provided shall | ||
3372 | * be used for invoking the api. If the api call returned success, the | ||
3373 | * actual number of virtual functions enabled will be set to the driver | ||
3374 | * cfg_sriov_nr_virtfn; otherwise, -EINVAL shall be returned and driver | ||
3375 | * cfg_sriov_nr_virtfn remains zero. | ||
3376 | * | ||
3377 | * If none-zero virtual functions have already been enabled to the | ||
3378 | * physical function, as reflected by the driver's cfg_sriov_nr_virtfn, | ||
3379 | * -EINVAL will be returned and the driver does nothing; | ||
3380 | * | ||
3381 | * If the nr_vfn provided is zero and none-zero virtual functions have | ||
3382 | * been enabled, as indicated by the driver's cfg_sriov_nr_virtfn, the | ||
3383 | * disabling virtual function api shall be invoded to disable all the | ||
3384 | * virtual functions and driver's cfg_sriov_nr_virtfn shall be set to | ||
3385 | * zero. Otherwise, if zero virtual function has been enabled, do | ||
3386 | * nothing. | ||
3387 | * | ||
3388 | * Returns: | ||
3389 | * length of the buf on success if val is in range the intended mode | ||
3390 | * is supported. | ||
3391 | * -EINVAL if val out of range or intended mode is not supported. | ||
3392 | **/ | ||
3393 | static ssize_t | ||
3394 | lpfc_sriov_nr_virtfn_store(struct device *dev, struct device_attribute *attr, | ||
3395 | const char *buf, size_t count) | ||
3396 | { | ||
3397 | struct Scsi_Host *shost = class_to_shost(dev); | ||
3398 | struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; | ||
3399 | struct lpfc_hba *phba = vport->phba; | ||
3400 | struct pci_dev *pdev = phba->pcidev; | ||
3401 | int val = 0, rc = -EINVAL; | ||
3402 | |||
3403 | /* Sanity check on user data */ | ||
3404 | if (!isdigit(buf[0])) | ||
3405 | return -EINVAL; | ||
3406 | if (sscanf(buf, "%i", &val) != 1) | ||
3407 | return -EINVAL; | ||
3408 | if (val < 0) | ||
3409 | return -EINVAL; | ||
3410 | |||
3411 | /* Request disabling virtual functions */ | ||
3412 | if (val == 0) { | ||
3413 | if (phba->cfg_sriov_nr_virtfn > 0) { | ||
3414 | pci_disable_sriov(pdev); | ||
3415 | phba->cfg_sriov_nr_virtfn = 0; | ||
3416 | } | ||
3417 | return strlen(buf); | ||
3418 | } | ||
3419 | |||
3420 | /* Request enabling virtual functions */ | ||
3421 | if (phba->cfg_sriov_nr_virtfn > 0) { | ||
3422 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
3423 | "3018 There are %d virtual functions " | ||
3424 | "enabled on physical function.\n", | ||
3425 | phba->cfg_sriov_nr_virtfn); | ||
3426 | return -EEXIST; | ||
3427 | } | ||
3428 | |||
3429 | if (val <= LPFC_MAX_VFN_PER_PFN) | ||
3430 | phba->cfg_sriov_nr_virtfn = val; | ||
3431 | else { | ||
3432 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
3433 | "3019 Enabling %d virtual functions is not " | ||
3434 | "allowed.\n", val); | ||
3435 | return -EINVAL; | ||
3436 | } | ||
3437 | |||
3438 | rc = lpfc_sli_probe_sriov_nr_virtfn(phba, phba->cfg_sriov_nr_virtfn); | ||
3439 | if (rc) { | ||
3440 | phba->cfg_sriov_nr_virtfn = 0; | ||
3441 | rc = -EPERM; | ||
3442 | } else | ||
3443 | rc = strlen(buf); | ||
3444 | |||
3445 | return rc; | ||
3446 | } | ||
3447 | |||
3448 | static int lpfc_sriov_nr_virtfn = LPFC_DEF_VFN_PER_PFN; | ||
3449 | module_param(lpfc_sriov_nr_virtfn, int, S_IRUGO|S_IWUSR); | ||
3450 | MODULE_PARM_DESC(lpfc_sriov_nr_virtfn, "Enable PCIe device SR-IOV virtual fn"); | ||
3451 | lpfc_param_show(sriov_nr_virtfn) | ||
3452 | |||
3453 | /** | ||
3454 | * lpfc_sriov_nr_virtfn_init - Set the initial sr-iov virtual function enable | ||
3455 | * @phba: lpfc_hba pointer. | ||
3456 | * @val: link speed value. | ||
3457 | * | ||
3458 | * Description: | ||
3459 | * If val is in a valid range [0,255], then set the adapter's initial | ||
3460 | * cfg_sriov_nr_virtfn field. If it's greater than the maximum, the maximum | ||
3461 | * number shall be used instead. It will be up to the driver's probe_one | ||
3462 | * routine to determine whether the device's SR-IOV is supported or not. | ||
3463 | * | ||
3464 | * Returns: | ||
3465 | * zero if val saved. | ||
3466 | * -EINVAL val out of range | ||
3467 | **/ | ||
3468 | static int | ||
3469 | lpfc_sriov_nr_virtfn_init(struct lpfc_hba *phba, int val) | ||
3470 | { | ||
3471 | if (val >= 0 && val <= LPFC_MAX_VFN_PER_PFN) { | ||
3472 | phba->cfg_sriov_nr_virtfn = val; | ||
3473 | return 0; | ||
3474 | } | ||
3475 | |||
3476 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
3477 | "3017 Enabling %d virtual functions is not " | ||
3478 | "allowed.\n", val); | ||
3479 | return -EINVAL; | ||
3480 | } | ||
3481 | static DEVICE_ATTR(lpfc_sriov_nr_virtfn, S_IRUGO | S_IWUSR, | ||
3482 | lpfc_sriov_nr_virtfn_show, lpfc_sriov_nr_virtfn_store); | ||
3483 | |||
3183 | /* | 3484 | /* |
3184 | # lpfc_fcp_class: Determines FC class to use for the FCP protocol. | 3485 | # lpfc_fcp_class: Determines FC class to use for the FCP protocol. |
3185 | # Value range is [2,3]. Default value is 3. | 3486 | # Value range is [2,3]. Default value is 3. |
@@ -3497,6 +3798,7 @@ struct device_attribute *lpfc_hba_attrs[] = { | |||
3497 | &dev_attr_lpfc_prot_sg_seg_cnt, | 3798 | &dev_attr_lpfc_prot_sg_seg_cnt, |
3498 | &dev_attr_lpfc_aer_support, | 3799 | &dev_attr_lpfc_aer_support, |
3499 | &dev_attr_lpfc_aer_state_cleanup, | 3800 | &dev_attr_lpfc_aer_state_cleanup, |
3801 | &dev_attr_lpfc_sriov_nr_virtfn, | ||
3500 | &dev_attr_lpfc_suppress_link_up, | 3802 | &dev_attr_lpfc_suppress_link_up, |
3501 | &dev_attr_lpfc_iocb_cnt, | 3803 | &dev_attr_lpfc_iocb_cnt, |
3502 | &dev_attr_iocb_hw, | 3804 | &dev_attr_iocb_hw, |
@@ -3505,6 +3807,7 @@ struct device_attribute *lpfc_hba_attrs[] = { | |||
3505 | &dev_attr_lpfc_fips_level, | 3807 | &dev_attr_lpfc_fips_level, |
3506 | &dev_attr_lpfc_fips_rev, | 3808 | &dev_attr_lpfc_fips_rev, |
3507 | &dev_attr_lpfc_dss, | 3809 | &dev_attr_lpfc_dss, |
3810 | &dev_attr_lpfc_sriov_hw_max_virtfn, | ||
3508 | NULL, | 3811 | NULL, |
3509 | }; | 3812 | }; |
3510 | 3813 | ||
@@ -3961,7 +4264,7 @@ static struct bin_attribute sysfs_mbox_attr = { | |||
3961 | .name = "mbox", | 4264 | .name = "mbox", |
3962 | .mode = S_IRUSR | S_IWUSR, | 4265 | .mode = S_IRUSR | S_IWUSR, |
3963 | }, | 4266 | }, |
3964 | .size = MAILBOX_CMD_SIZE, | 4267 | .size = MAILBOX_SYSFS_MAX, |
3965 | .read = sysfs_mbox_read, | 4268 | .read = sysfs_mbox_read, |
3966 | .write = sysfs_mbox_write, | 4269 | .write = sysfs_mbox_write, |
3967 | }; | 4270 | }; |
@@ -4705,6 +5008,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
4705 | lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); | 5008 | lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); |
4706 | lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); | 5009 | lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); |
4707 | lpfc_aer_support_init(phba, lpfc_aer_support); | 5010 | lpfc_aer_support_init(phba, lpfc_aer_support); |
5011 | lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn); | ||
4708 | lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); | 5012 | lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); |
4709 | lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt); | 5013 | lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt); |
4710 | phba->cfg_enable_dss = 1; | 5014 | phba->cfg_enable_dss = 1; |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 853e5042f39c..7fb0ba4cbfa7 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/list.h> | ||
26 | 27 | ||
27 | #include <scsi/scsi.h> | 28 | #include <scsi/scsi.h> |
28 | #include <scsi/scsi_host.h> | 29 | #include <scsi/scsi_host.h> |
@@ -79,8 +80,7 @@ struct lpfc_bsg_iocb { | |||
79 | struct lpfc_bsg_mbox { | 80 | struct lpfc_bsg_mbox { |
80 | LPFC_MBOXQ_t *pmboxq; | 81 | LPFC_MBOXQ_t *pmboxq; |
81 | MAILBOX_t *mb; | 82 | MAILBOX_t *mb; |
82 | struct lpfc_dmabuf *rxbmp; /* for BIU diags */ | 83 | struct lpfc_dmabuf *dmabuffers; /* for BIU diags */ |
83 | struct lpfc_dmabufext *dmp; /* for BIU diags */ | ||
84 | uint8_t *ext; /* extended mailbox data */ | 84 | uint8_t *ext; /* extended mailbox data */ |
85 | uint32_t mbOffset; /* from app */ | 85 | uint32_t mbOffset; /* from app */ |
86 | uint32_t inExtWLen; /* from app */ | 86 | uint32_t inExtWLen; /* from app */ |
@@ -332,6 +332,8 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) | |||
332 | cmd->ulpLe = 1; | 332 | cmd->ulpLe = 1; |
333 | cmd->ulpClass = CLASS3; | 333 | cmd->ulpClass = CLASS3; |
334 | cmd->ulpContext = ndlp->nlp_rpi; | 334 | cmd->ulpContext = ndlp->nlp_rpi; |
335 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
336 | cmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | ||
335 | cmd->ulpOwner = OWN_CHIP; | 337 | cmd->ulpOwner = OWN_CHIP; |
336 | cmdiocbq->vport = phba->pport; | 338 | cmdiocbq->vport = phba->pport; |
337 | cmdiocbq->context3 = bmp; | 339 | cmdiocbq->context3 = bmp; |
@@ -1336,6 +1338,10 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag, | |||
1336 | } | 1338 | } |
1337 | 1339 | ||
1338 | icmd->un.ulpWord[3] = ndlp->nlp_rpi; | 1340 | icmd->un.ulpWord[3] = ndlp->nlp_rpi; |
1341 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
1342 | icmd->ulpContext = | ||
1343 | phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | ||
1344 | |||
1339 | /* The exchange is done, mark the entry as invalid */ | 1345 | /* The exchange is done, mark the entry as invalid */ |
1340 | phba->ct_ctx[tag].flags &= ~UNSOL_VALID; | 1346 | phba->ct_ctx[tag].flags &= ~UNSOL_VALID; |
1341 | } else | 1347 | } else |
@@ -1463,11 +1469,91 @@ send_mgmt_rsp_exit: | |||
1463 | } | 1469 | } |
1464 | 1470 | ||
1465 | /** | 1471 | /** |
1466 | * lpfc_bsg_diag_mode - process a LPFC_BSG_VENDOR_DIAG_MODE bsg vendor command | 1472 | * lpfc_bsg_diag_mode_enter - process preparing into device diag loopback mode |
1473 | * @phba: Pointer to HBA context object. | ||
1467 | * @job: LPFC_BSG_VENDOR_DIAG_MODE | 1474 | * @job: LPFC_BSG_VENDOR_DIAG_MODE |
1468 | * | 1475 | * |
1469 | * This function is responsible for placing a port into diagnostic loopback | 1476 | * This function is responsible for preparing driver for diag loopback |
1470 | * mode in order to perform a diagnostic loopback test. | 1477 | * on device. |
1478 | */ | ||
1479 | static int | ||
1480 | lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba, struct fc_bsg_job *job) | ||
1481 | { | ||
1482 | struct lpfc_vport **vports; | ||
1483 | struct Scsi_Host *shost; | ||
1484 | struct lpfc_sli *psli; | ||
1485 | struct lpfc_sli_ring *pring; | ||
1486 | int i = 0; | ||
1487 | |||
1488 | psli = &phba->sli; | ||
1489 | if (!psli) | ||
1490 | return -ENODEV; | ||
1491 | |||
1492 | pring = &psli->ring[LPFC_FCP_RING]; | ||
1493 | if (!pring) | ||
1494 | return -ENODEV; | ||
1495 | |||
1496 | if ((phba->link_state == LPFC_HBA_ERROR) || | ||
1497 | (psli->sli_flag & LPFC_BLOCK_MGMT_IO) || | ||
1498 | (!(psli->sli_flag & LPFC_SLI_ACTIVE))) | ||
1499 | return -EACCES; | ||
1500 | |||
1501 | vports = lpfc_create_vport_work_array(phba); | ||
1502 | if (vports) { | ||
1503 | for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | ||
1504 | shost = lpfc_shost_from_vport(vports[i]); | ||
1505 | scsi_block_requests(shost); | ||
1506 | } | ||
1507 | lpfc_destroy_vport_work_array(phba, vports); | ||
1508 | } else { | ||
1509 | shost = lpfc_shost_from_vport(phba->pport); | ||
1510 | scsi_block_requests(shost); | ||
1511 | } | ||
1512 | |||
1513 | while (pring->txcmplq_cnt) { | ||
1514 | if (i++ > 500) /* wait up to 5 seconds */ | ||
1515 | break; | ||
1516 | msleep(10); | ||
1517 | } | ||
1518 | return 0; | ||
1519 | } | ||
1520 | |||
1521 | /** | ||
1522 | * lpfc_bsg_diag_mode_exit - exit process from device diag loopback mode | ||
1523 | * @phba: Pointer to HBA context object. | ||
1524 | * @job: LPFC_BSG_VENDOR_DIAG_MODE | ||
1525 | * | ||
1526 | * This function is responsible for driver exit processing of setting up | ||
1527 | * diag loopback mode on device. | ||
1528 | */ | ||
1529 | static void | ||
1530 | lpfc_bsg_diag_mode_exit(struct lpfc_hba *phba) | ||
1531 | { | ||
1532 | struct Scsi_Host *shost; | ||
1533 | struct lpfc_vport **vports; | ||
1534 | int i; | ||
1535 | |||
1536 | vports = lpfc_create_vport_work_array(phba); | ||
1537 | if (vports) { | ||
1538 | for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | ||
1539 | shost = lpfc_shost_from_vport(vports[i]); | ||
1540 | scsi_unblock_requests(shost); | ||
1541 | } | ||
1542 | lpfc_destroy_vport_work_array(phba, vports); | ||
1543 | } else { | ||
1544 | shost = lpfc_shost_from_vport(phba->pport); | ||
1545 | scsi_unblock_requests(shost); | ||
1546 | } | ||
1547 | return; | ||
1548 | } | ||
1549 | |||
1550 | /** | ||
1551 | * lpfc_sli3_bsg_diag_loopback_mode - process an sli3 bsg vendor command | ||
1552 | * @phba: Pointer to HBA context object. | ||
1553 | * @job: LPFC_BSG_VENDOR_DIAG_MODE | ||
1554 | * | ||
1555 | * This function is responsible for placing an sli3 port into diagnostic | ||
1556 | * loopback mode in order to perform a diagnostic loopback test. | ||
1471 | * All new scsi requests are blocked, a small delay is used to allow the | 1557 | * All new scsi requests are blocked, a small delay is used to allow the |
1472 | * scsi requests to complete then the link is brought down. If the link is | 1558 | * scsi requests to complete then the link is brought down. If the link is |
1473 | * is placed in loopback mode then scsi requests are again allowed | 1559 | * is placed in loopback mode then scsi requests are again allowed |
@@ -1475,17 +1561,11 @@ send_mgmt_rsp_exit: | |||
1475 | * All of this is done in-line. | 1561 | * All of this is done in-line. |
1476 | */ | 1562 | */ |
1477 | static int | 1563 | static int |
1478 | lpfc_bsg_diag_mode(struct fc_bsg_job *job) | 1564 | lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) |
1479 | { | 1565 | { |
1480 | struct Scsi_Host *shost = job->shost; | ||
1481 | struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; | ||
1482 | struct lpfc_hba *phba = vport->phba; | ||
1483 | struct diag_mode_set *loopback_mode; | 1566 | struct diag_mode_set *loopback_mode; |
1484 | struct lpfc_sli *psli = &phba->sli; | ||
1485 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_FCP_RING]; | ||
1486 | uint32_t link_flags; | 1567 | uint32_t link_flags; |
1487 | uint32_t timeout; | 1568 | uint32_t timeout; |
1488 | struct lpfc_vport **vports; | ||
1489 | LPFC_MBOXQ_t *pmboxq; | 1569 | LPFC_MBOXQ_t *pmboxq; |
1490 | int mbxstatus; | 1570 | int mbxstatus; |
1491 | int i = 0; | 1571 | int i = 0; |
@@ -1494,53 +1574,33 @@ lpfc_bsg_diag_mode(struct fc_bsg_job *job) | |||
1494 | /* no data to return just the return code */ | 1574 | /* no data to return just the return code */ |
1495 | job->reply->reply_payload_rcv_len = 0; | 1575 | job->reply->reply_payload_rcv_len = 0; |
1496 | 1576 | ||
1497 | if (job->request_len < | 1577 | if (job->request_len < sizeof(struct fc_bsg_request) + |
1498 | sizeof(struct fc_bsg_request) + sizeof(struct diag_mode_set)) { | 1578 | sizeof(struct diag_mode_set)) { |
1499 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | 1579 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, |
1500 | "2738 Received DIAG MODE request below minimum " | 1580 | "2738 Received DIAG MODE request size:%d " |
1501 | "size\n"); | 1581 | "below the minimum size:%d\n", |
1582 | job->request_len, | ||
1583 | (int)(sizeof(struct fc_bsg_request) + | ||
1584 | sizeof(struct diag_mode_set))); | ||
1502 | rc = -EINVAL; | 1585 | rc = -EINVAL; |
1503 | goto job_error; | 1586 | goto job_error; |
1504 | } | 1587 | } |
1505 | 1588 | ||
1589 | rc = lpfc_bsg_diag_mode_enter(phba, job); | ||
1590 | if (rc) | ||
1591 | goto job_error; | ||
1592 | |||
1593 | /* bring the link to diagnostic mode */ | ||
1506 | loopback_mode = (struct diag_mode_set *) | 1594 | loopback_mode = (struct diag_mode_set *) |
1507 | job->request->rqst_data.h_vendor.vendor_cmd; | 1595 | job->request->rqst_data.h_vendor.vendor_cmd; |
1508 | link_flags = loopback_mode->type; | 1596 | link_flags = loopback_mode->type; |
1509 | timeout = loopback_mode->timeout * 100; | 1597 | timeout = loopback_mode->timeout * 100; |
1510 | 1598 | ||
1511 | if ((phba->link_state == LPFC_HBA_ERROR) || | ||
1512 | (psli->sli_flag & LPFC_BLOCK_MGMT_IO) || | ||
1513 | (!(psli->sli_flag & LPFC_SLI_ACTIVE))) { | ||
1514 | rc = -EACCES; | ||
1515 | goto job_error; | ||
1516 | } | ||
1517 | |||
1518 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 1599 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
1519 | if (!pmboxq) { | 1600 | if (!pmboxq) { |
1520 | rc = -ENOMEM; | 1601 | rc = -ENOMEM; |
1521 | goto job_error; | 1602 | goto loopback_mode_exit; |
1522 | } | ||
1523 | |||
1524 | vports = lpfc_create_vport_work_array(phba); | ||
1525 | if (vports) { | ||
1526 | for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | ||
1527 | shost = lpfc_shost_from_vport(vports[i]); | ||
1528 | scsi_block_requests(shost); | ||
1529 | } | ||
1530 | |||
1531 | lpfc_destroy_vport_work_array(phba, vports); | ||
1532 | } else { | ||
1533 | shost = lpfc_shost_from_vport(phba->pport); | ||
1534 | scsi_block_requests(shost); | ||
1535 | } | 1603 | } |
1536 | |||
1537 | while (pring->txcmplq_cnt) { | ||
1538 | if (i++ > 500) /* wait up to 5 seconds */ | ||
1539 | break; | ||
1540 | |||
1541 | msleep(10); | ||
1542 | } | ||
1543 | |||
1544 | memset((void *)pmboxq, 0, sizeof(LPFC_MBOXQ_t)); | 1604 | memset((void *)pmboxq, 0, sizeof(LPFC_MBOXQ_t)); |
1545 | pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK; | 1605 | pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK; |
1546 | pmboxq->u.mb.mbxOwner = OWN_HOST; | 1606 | pmboxq->u.mb.mbxOwner = OWN_HOST; |
@@ -1594,22 +1654,186 @@ lpfc_bsg_diag_mode(struct fc_bsg_job *job) | |||
1594 | rc = -ENODEV; | 1654 | rc = -ENODEV; |
1595 | 1655 | ||
1596 | loopback_mode_exit: | 1656 | loopback_mode_exit: |
1597 | vports = lpfc_create_vport_work_array(phba); | 1657 | lpfc_bsg_diag_mode_exit(phba); |
1598 | if (vports) { | 1658 | |
1599 | for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | 1659 | /* |
1600 | shost = lpfc_shost_from_vport(vports[i]); | 1660 | * Let SLI layer release mboxq if mbox command completed after timeout. |
1601 | scsi_unblock_requests(shost); | 1661 | */ |
1662 | if (mbxstatus != MBX_TIMEOUT) | ||
1663 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
1664 | |||
1665 | job_error: | ||
1666 | /* make error code available to userspace */ | ||
1667 | job->reply->result = rc; | ||
1668 | /* complete the job back to userspace if no error */ | ||
1669 | if (rc == 0) | ||
1670 | job->job_done(job); | ||
1671 | return rc; | ||
1672 | } | ||
1673 | |||
1674 | /** | ||
1675 | * lpfc_sli4_bsg_set_link_diag_state - set sli4 link diag state | ||
1676 | * @phba: Pointer to HBA context object. | ||
1677 | * @diag: Flag for set link to diag or nomral operation state. | ||
1678 | * | ||
1679 | * This function is responsible for issuing a sli4 mailbox command for setting | ||
1680 | * link to either diag state or normal operation state. | ||
1681 | */ | ||
1682 | static int | ||
1683 | lpfc_sli4_bsg_set_link_diag_state(struct lpfc_hba *phba, uint32_t diag) | ||
1684 | { | ||
1685 | LPFC_MBOXQ_t *pmboxq; | ||
1686 | struct lpfc_mbx_set_link_diag_state *link_diag_state; | ||
1687 | uint32_t req_len, alloc_len; | ||
1688 | int mbxstatus = MBX_SUCCESS, rc; | ||
1689 | |||
1690 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
1691 | if (!pmboxq) | ||
1692 | return -ENOMEM; | ||
1693 | |||
1694 | req_len = (sizeof(struct lpfc_mbx_set_link_diag_state) - | ||
1695 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
1696 | alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | ||
1697 | LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE, | ||
1698 | req_len, LPFC_SLI4_MBX_EMBED); | ||
1699 | if (alloc_len != req_len) { | ||
1700 | rc = -ENOMEM; | ||
1701 | goto link_diag_state_set_out; | ||
1702 | } | ||
1703 | link_diag_state = &pmboxq->u.mqe.un.link_diag_state; | ||
1704 | bf_set(lpfc_mbx_set_diag_state_link_num, &link_diag_state->u.req, | ||
1705 | phba->sli4_hba.link_state.number); | ||
1706 | bf_set(lpfc_mbx_set_diag_state_link_type, &link_diag_state->u.req, | ||
1707 | phba->sli4_hba.link_state.type); | ||
1708 | if (diag) | ||
1709 | bf_set(lpfc_mbx_set_diag_state_diag, | ||
1710 | &link_diag_state->u.req, 1); | ||
1711 | else | ||
1712 | bf_set(lpfc_mbx_set_diag_state_diag, | ||
1713 | &link_diag_state->u.req, 0); | ||
1714 | |||
1715 | mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO); | ||
1716 | |||
1717 | if ((mbxstatus == MBX_SUCCESS) && (pmboxq->u.mb.mbxStatus == 0)) | ||
1718 | rc = 0; | ||
1719 | else | ||
1720 | rc = -ENODEV; | ||
1721 | |||
1722 | link_diag_state_set_out: | ||
1723 | if (pmboxq && (mbxstatus != MBX_TIMEOUT)) | ||
1724 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
1725 | |||
1726 | return rc; | ||
1727 | } | ||
1728 | |||
1729 | /** | ||
1730 | * lpfc_sli4_bsg_diag_loopback_mode - process an sli4 bsg vendor command | ||
1731 | * @phba: Pointer to HBA context object. | ||
1732 | * @job: LPFC_BSG_VENDOR_DIAG_MODE | ||
1733 | * | ||
1734 | * This function is responsible for placing an sli4 port into diagnostic | ||
1735 | * loopback mode in order to perform a diagnostic loopback test. | ||
1736 | */ | ||
1737 | static int | ||
1738 | lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) | ||
1739 | { | ||
1740 | struct diag_mode_set *loopback_mode; | ||
1741 | uint32_t link_flags, timeout, req_len, alloc_len; | ||
1742 | struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback; | ||
1743 | LPFC_MBOXQ_t *pmboxq = NULL; | ||
1744 | int mbxstatus, i, rc = 0; | ||
1745 | |||
1746 | /* no data to return just the return code */ | ||
1747 | job->reply->reply_payload_rcv_len = 0; | ||
1748 | |||
1749 | if (job->request_len < sizeof(struct fc_bsg_request) + | ||
1750 | sizeof(struct diag_mode_set)) { | ||
1751 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
1752 | "3011 Received DIAG MODE request size:%d " | ||
1753 | "below the minimum size:%d\n", | ||
1754 | job->request_len, | ||
1755 | (int)(sizeof(struct fc_bsg_request) + | ||
1756 | sizeof(struct diag_mode_set))); | ||
1757 | rc = -EINVAL; | ||
1758 | goto job_error; | ||
1759 | } | ||
1760 | |||
1761 | rc = lpfc_bsg_diag_mode_enter(phba, job); | ||
1762 | if (rc) | ||
1763 | goto job_error; | ||
1764 | |||
1765 | /* bring the link to diagnostic mode */ | ||
1766 | loopback_mode = (struct diag_mode_set *) | ||
1767 | job->request->rqst_data.h_vendor.vendor_cmd; | ||
1768 | link_flags = loopback_mode->type; | ||
1769 | timeout = loopback_mode->timeout * 100; | ||
1770 | |||
1771 | rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1); | ||
1772 | if (rc) | ||
1773 | goto loopback_mode_exit; | ||
1774 | |||
1775 | /* wait for link down before proceeding */ | ||
1776 | i = 0; | ||
1777 | while (phba->link_state != LPFC_LINK_DOWN) { | ||
1778 | if (i++ > timeout) { | ||
1779 | rc = -ETIMEDOUT; | ||
1780 | goto loopback_mode_exit; | ||
1781 | } | ||
1782 | msleep(10); | ||
1783 | } | ||
1784 | /* set up loopback mode */ | ||
1785 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
1786 | if (!pmboxq) { | ||
1787 | rc = -ENOMEM; | ||
1788 | goto loopback_mode_exit; | ||
1789 | } | ||
1790 | req_len = (sizeof(struct lpfc_mbx_set_link_diag_loopback) - | ||
1791 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
1792 | alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | ||
1793 | LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK, | ||
1794 | req_len, LPFC_SLI4_MBX_EMBED); | ||
1795 | if (alloc_len != req_len) { | ||
1796 | rc = -ENOMEM; | ||
1797 | goto loopback_mode_exit; | ||
1798 | } | ||
1799 | link_diag_loopback = &pmboxq->u.mqe.un.link_diag_loopback; | ||
1800 | bf_set(lpfc_mbx_set_diag_state_link_num, | ||
1801 | &link_diag_loopback->u.req, phba->sli4_hba.link_state.number); | ||
1802 | bf_set(lpfc_mbx_set_diag_state_link_type, | ||
1803 | &link_diag_loopback->u.req, phba->sli4_hba.link_state.type); | ||
1804 | if (link_flags == INTERNAL_LOOP_BACK) | ||
1805 | bf_set(lpfc_mbx_set_diag_lpbk_type, | ||
1806 | &link_diag_loopback->u.req, | ||
1807 | LPFC_DIAG_LOOPBACK_TYPE_INTERNAL); | ||
1808 | else | ||
1809 | bf_set(lpfc_mbx_set_diag_lpbk_type, | ||
1810 | &link_diag_loopback->u.req, | ||
1811 | LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL); | ||
1812 | |||
1813 | mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO); | ||
1814 | if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) | ||
1815 | rc = -ENODEV; | ||
1816 | else { | ||
1817 | phba->link_flag |= LS_LOOPBACK_MODE; | ||
1818 | /* wait for the link attention interrupt */ | ||
1819 | msleep(100); | ||
1820 | i = 0; | ||
1821 | while (phba->link_state != LPFC_HBA_READY) { | ||
1822 | if (i++ > timeout) { | ||
1823 | rc = -ETIMEDOUT; | ||
1824 | break; | ||
1825 | } | ||
1826 | msleep(10); | ||
1602 | } | 1827 | } |
1603 | lpfc_destroy_vport_work_array(phba, vports); | ||
1604 | } else { | ||
1605 | shost = lpfc_shost_from_vport(phba->pport); | ||
1606 | scsi_unblock_requests(shost); | ||
1607 | } | 1828 | } |
1608 | 1829 | ||
1830 | loopback_mode_exit: | ||
1831 | lpfc_bsg_diag_mode_exit(phba); | ||
1832 | |||
1609 | /* | 1833 | /* |
1610 | * Let SLI layer release mboxq if mbox command completed after timeout. | 1834 | * Let SLI layer release mboxq if mbox command completed after timeout. |
1611 | */ | 1835 | */ |
1612 | if (mbxstatus != MBX_TIMEOUT) | 1836 | if (pmboxq && (mbxstatus != MBX_TIMEOUT)) |
1613 | mempool_free(pmboxq, phba->mbox_mem_pool); | 1837 | mempool_free(pmboxq, phba->mbox_mem_pool); |
1614 | 1838 | ||
1615 | job_error: | 1839 | job_error: |
@@ -1622,6 +1846,234 @@ job_error: | |||
1622 | } | 1846 | } |
1623 | 1847 | ||
1624 | /** | 1848 | /** |
1849 | * lpfc_bsg_diag_loopback_mode - bsg vendor command for diag loopback mode | ||
1850 | * @job: LPFC_BSG_VENDOR_DIAG_MODE | ||
1851 | * | ||
1852 | * This function is responsible for responding to check and dispatch bsg diag | ||
1853 | * command from the user to proper driver action routines. | ||
1854 | */ | ||
1855 | static int | ||
1856 | lpfc_bsg_diag_loopback_mode(struct fc_bsg_job *job) | ||
1857 | { | ||
1858 | struct Scsi_Host *shost; | ||
1859 | struct lpfc_vport *vport; | ||
1860 | struct lpfc_hba *phba; | ||
1861 | int rc; | ||
1862 | |||
1863 | shost = job->shost; | ||
1864 | if (!shost) | ||
1865 | return -ENODEV; | ||
1866 | vport = (struct lpfc_vport *)job->shost->hostdata; | ||
1867 | if (!vport) | ||
1868 | return -ENODEV; | ||
1869 | phba = vport->phba; | ||
1870 | if (!phba) | ||
1871 | return -ENODEV; | ||
1872 | |||
1873 | if (phba->sli_rev < LPFC_SLI_REV4) | ||
1874 | rc = lpfc_sli3_bsg_diag_loopback_mode(phba, job); | ||
1875 | else if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == | ||
1876 | LPFC_SLI_INTF_IF_TYPE_2) | ||
1877 | rc = lpfc_sli4_bsg_diag_loopback_mode(phba, job); | ||
1878 | else | ||
1879 | rc = -ENODEV; | ||
1880 | |||
1881 | return rc; | ||
1882 | |||
1883 | } | ||
1884 | |||
1885 | /** | ||
1886 | * lpfc_sli4_bsg_diag_mode_end - sli4 bsg vendor command for ending diag mode | ||
1887 | * @job: LPFC_BSG_VENDOR_DIAG_MODE_END | ||
1888 | * | ||
1889 | * This function is responsible for responding to check and dispatch bsg diag | ||
1890 | * command from the user to proper driver action routines. | ||
1891 | */ | ||
1892 | static int | ||
1893 | lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job) | ||
1894 | { | ||
1895 | struct Scsi_Host *shost; | ||
1896 | struct lpfc_vport *vport; | ||
1897 | struct lpfc_hba *phba; | ||
1898 | int rc; | ||
1899 | |||
1900 | shost = job->shost; | ||
1901 | if (!shost) | ||
1902 | return -ENODEV; | ||
1903 | vport = (struct lpfc_vport *)job->shost->hostdata; | ||
1904 | if (!vport) | ||
1905 | return -ENODEV; | ||
1906 | phba = vport->phba; | ||
1907 | if (!phba) | ||
1908 | return -ENODEV; | ||
1909 | |||
1910 | if (phba->sli_rev < LPFC_SLI_REV4) | ||
1911 | return -ENODEV; | ||
1912 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
1913 | LPFC_SLI_INTF_IF_TYPE_2) | ||
1914 | return -ENODEV; | ||
1915 | |||
1916 | rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0); | ||
1917 | |||
1918 | if (!rc) | ||
1919 | rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); | ||
1920 | |||
1921 | return rc; | ||
1922 | } | ||
1923 | |||
1924 | /** | ||
1925 | * lpfc_sli4_bsg_link_diag_test - sli4 bsg vendor command for diag link test | ||
1926 | * @job: LPFC_BSG_VENDOR_DIAG_LINK_TEST | ||
1927 | * | ||
1928 | * This function is to perform SLI4 diag link test request from the user | ||
1929 | * applicaiton. | ||
1930 | */ | ||
1931 | static int | ||
1932 | lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job) | ||
1933 | { | ||
1934 | struct Scsi_Host *shost; | ||
1935 | struct lpfc_vport *vport; | ||
1936 | struct lpfc_hba *phba; | ||
1937 | LPFC_MBOXQ_t *pmboxq; | ||
1938 | struct sli4_link_diag *link_diag_test_cmd; | ||
1939 | uint32_t req_len, alloc_len; | ||
1940 | uint32_t timeout; | ||
1941 | struct lpfc_mbx_run_link_diag_test *run_link_diag_test; | ||
1942 | union lpfc_sli4_cfg_shdr *shdr; | ||
1943 | uint32_t shdr_status, shdr_add_status; | ||
1944 | struct diag_status *diag_status_reply; | ||
1945 | int mbxstatus, rc = 0; | ||
1946 | |||
1947 | shost = job->shost; | ||
1948 | if (!shost) { | ||
1949 | rc = -ENODEV; | ||
1950 | goto job_error; | ||
1951 | } | ||
1952 | vport = (struct lpfc_vport *)job->shost->hostdata; | ||
1953 | if (!vport) { | ||
1954 | rc = -ENODEV; | ||
1955 | goto job_error; | ||
1956 | } | ||
1957 | phba = vport->phba; | ||
1958 | if (!phba) { | ||
1959 | rc = -ENODEV; | ||
1960 | goto job_error; | ||
1961 | } | ||
1962 | |||
1963 | if (phba->sli_rev < LPFC_SLI_REV4) { | ||
1964 | rc = -ENODEV; | ||
1965 | goto job_error; | ||
1966 | } | ||
1967 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
1968 | LPFC_SLI_INTF_IF_TYPE_2) { | ||
1969 | rc = -ENODEV; | ||
1970 | goto job_error; | ||
1971 | } | ||
1972 | |||
1973 | if (job->request_len < sizeof(struct fc_bsg_request) + | ||
1974 | sizeof(struct sli4_link_diag)) { | ||
1975 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
1976 | "3013 Received LINK DIAG TEST request " | ||
1977 | " size:%d below the minimum size:%d\n", | ||
1978 | job->request_len, | ||
1979 | (int)(sizeof(struct fc_bsg_request) + | ||
1980 | sizeof(struct sli4_link_diag))); | ||
1981 | rc = -EINVAL; | ||
1982 | goto job_error; | ||
1983 | } | ||
1984 | |||
1985 | rc = lpfc_bsg_diag_mode_enter(phba, job); | ||
1986 | if (rc) | ||
1987 | goto job_error; | ||
1988 | |||
1989 | link_diag_test_cmd = (struct sli4_link_diag *) | ||
1990 | job->request->rqst_data.h_vendor.vendor_cmd; | ||
1991 | timeout = link_diag_test_cmd->timeout * 100; | ||
1992 | |||
1993 | rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1); | ||
1994 | |||
1995 | if (rc) | ||
1996 | goto job_error; | ||
1997 | |||
1998 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
1999 | if (!pmboxq) { | ||
2000 | rc = -ENOMEM; | ||
2001 | goto link_diag_test_exit; | ||
2002 | } | ||
2003 | |||
2004 | req_len = (sizeof(struct lpfc_mbx_set_link_diag_state) - | ||
2005 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
2006 | alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | ||
2007 | LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE, | ||
2008 | req_len, LPFC_SLI4_MBX_EMBED); | ||
2009 | if (alloc_len != req_len) { | ||
2010 | rc = -ENOMEM; | ||
2011 | goto link_diag_test_exit; | ||
2012 | } | ||
2013 | run_link_diag_test = &pmboxq->u.mqe.un.link_diag_test; | ||
2014 | bf_set(lpfc_mbx_run_diag_test_link_num, &run_link_diag_test->u.req, | ||
2015 | phba->sli4_hba.link_state.number); | ||
2016 | bf_set(lpfc_mbx_run_diag_test_link_type, &run_link_diag_test->u.req, | ||
2017 | phba->sli4_hba.link_state.type); | ||
2018 | bf_set(lpfc_mbx_run_diag_test_test_id, &run_link_diag_test->u.req, | ||
2019 | link_diag_test_cmd->test_id); | ||
2020 | bf_set(lpfc_mbx_run_diag_test_loops, &run_link_diag_test->u.req, | ||
2021 | link_diag_test_cmd->loops); | ||
2022 | bf_set(lpfc_mbx_run_diag_test_test_ver, &run_link_diag_test->u.req, | ||
2023 | link_diag_test_cmd->test_version); | ||
2024 | bf_set(lpfc_mbx_run_diag_test_err_act, &run_link_diag_test->u.req, | ||
2025 | link_diag_test_cmd->error_action); | ||
2026 | |||
2027 | mbxstatus = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL); | ||
2028 | |||
2029 | shdr = (union lpfc_sli4_cfg_shdr *) | ||
2030 | &pmboxq->u.mqe.un.sli4_config.header.cfg_shdr; | ||
2031 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
2032 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); | ||
2033 | if (shdr_status || shdr_add_status || mbxstatus) { | ||
2034 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
2035 | "3010 Run link diag test mailbox failed with " | ||
2036 | "mbx_status x%x status x%x, add_status x%x\n", | ||
2037 | mbxstatus, shdr_status, shdr_add_status); | ||
2038 | } | ||
2039 | |||
2040 | diag_status_reply = (struct diag_status *) | ||
2041 | job->reply->reply_data.vendor_reply.vendor_rsp; | ||
2042 | |||
2043 | if (job->reply_len < | ||
2044 | sizeof(struct fc_bsg_request) + sizeof(struct diag_status)) { | ||
2045 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
2046 | "3012 Received Run link diag test reply " | ||
2047 | "below minimum size (%d): reply_len:%d\n", | ||
2048 | (int)(sizeof(struct fc_bsg_request) + | ||
2049 | sizeof(struct diag_status)), | ||
2050 | job->reply_len); | ||
2051 | rc = -EINVAL; | ||
2052 | goto job_error; | ||
2053 | } | ||
2054 | |||
2055 | diag_status_reply->mbox_status = mbxstatus; | ||
2056 | diag_status_reply->shdr_status = shdr_status; | ||
2057 | diag_status_reply->shdr_add_status = shdr_add_status; | ||
2058 | |||
2059 | link_diag_test_exit: | ||
2060 | rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0); | ||
2061 | |||
2062 | if (pmboxq) | ||
2063 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
2064 | |||
2065 | lpfc_bsg_diag_mode_exit(phba); | ||
2066 | |||
2067 | job_error: | ||
2068 | /* make error code available to userspace */ | ||
2069 | job->reply->result = rc; | ||
2070 | /* complete the job back to userspace if no error */ | ||
2071 | if (rc == 0) | ||
2072 | job->job_done(job); | ||
2073 | return rc; | ||
2074 | } | ||
2075 | |||
2076 | /** | ||
1625 | * lpfcdiag_loop_self_reg - obtains a remote port login id | 2077 | * lpfcdiag_loop_self_reg - obtains a remote port login id |
1626 | * @phba: Pointer to HBA context object | 2078 | * @phba: Pointer to HBA context object |
1627 | * @rpi: Pointer to a remote port login id | 2079 | * @rpi: Pointer to a remote port login id |
@@ -1851,6 +2303,86 @@ err_get_xri_exit: | |||
1851 | } | 2303 | } |
1852 | 2304 | ||
1853 | /** | 2305 | /** |
2306 | * lpfc_bsg_dma_page_alloc - allocate a bsg mbox page sized dma buffers | ||
2307 | * @phba: Pointer to HBA context object | ||
2308 | * | ||
2309 | * This function allocates BSG_MBOX_SIZE (4KB) page size dma buffer and. | ||
2310 | * retruns the pointer to the buffer. | ||
2311 | **/ | ||
2312 | static struct lpfc_dmabuf * | ||
2313 | lpfc_bsg_dma_page_alloc(struct lpfc_hba *phba) | ||
2314 | { | ||
2315 | struct lpfc_dmabuf *dmabuf; | ||
2316 | struct pci_dev *pcidev = phba->pcidev; | ||
2317 | |||
2318 | /* allocate dma buffer struct */ | ||
2319 | dmabuf = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | ||
2320 | if (!dmabuf) | ||
2321 | return NULL; | ||
2322 | |||
2323 | INIT_LIST_HEAD(&dmabuf->list); | ||
2324 | |||
2325 | /* now, allocate dma buffer */ | ||
2326 | dmabuf->virt = dma_alloc_coherent(&pcidev->dev, BSG_MBOX_SIZE, | ||
2327 | &(dmabuf->phys), GFP_KERNEL); | ||
2328 | |||
2329 | if (!dmabuf->virt) { | ||
2330 | kfree(dmabuf); | ||
2331 | return NULL; | ||
2332 | } | ||
2333 | memset((uint8_t *)dmabuf->virt, 0, BSG_MBOX_SIZE); | ||
2334 | |||
2335 | return dmabuf; | ||
2336 | } | ||
2337 | |||
2338 | /** | ||
2339 | * lpfc_bsg_dma_page_free - free a bsg mbox page sized dma buffer | ||
2340 | * @phba: Pointer to HBA context object. | ||
2341 | * @dmabuf: Pointer to the bsg mbox page sized dma buffer descriptor. | ||
2342 | * | ||
2343 | * This routine just simply frees a dma buffer and its associated buffer | ||
2344 | * descriptor referred by @dmabuf. | ||
2345 | **/ | ||
2346 | static void | ||
2347 | lpfc_bsg_dma_page_free(struct lpfc_hba *phba, struct lpfc_dmabuf *dmabuf) | ||
2348 | { | ||
2349 | struct pci_dev *pcidev = phba->pcidev; | ||
2350 | |||
2351 | if (!dmabuf) | ||
2352 | return; | ||
2353 | |||
2354 | if (dmabuf->virt) | ||
2355 | dma_free_coherent(&pcidev->dev, BSG_MBOX_SIZE, | ||
2356 | dmabuf->virt, dmabuf->phys); | ||
2357 | kfree(dmabuf); | ||
2358 | return; | ||
2359 | } | ||
2360 | |||
2361 | /** | ||
2362 | * lpfc_bsg_dma_page_list_free - free a list of bsg mbox page sized dma buffers | ||
2363 | * @phba: Pointer to HBA context object. | ||
2364 | * @dmabuf_list: Pointer to a list of bsg mbox page sized dma buffer descs. | ||
2365 | * | ||
2366 | * This routine just simply frees all dma buffers and their associated buffer | ||
2367 | * descriptors referred by @dmabuf_list. | ||
2368 | **/ | ||
2369 | static void | ||
2370 | lpfc_bsg_dma_page_list_free(struct lpfc_hba *phba, | ||
2371 | struct list_head *dmabuf_list) | ||
2372 | { | ||
2373 | struct lpfc_dmabuf *dmabuf, *next_dmabuf; | ||
2374 | |||
2375 | if (list_empty(dmabuf_list)) | ||
2376 | return; | ||
2377 | |||
2378 | list_for_each_entry_safe(dmabuf, next_dmabuf, dmabuf_list, list) { | ||
2379 | list_del_init(&dmabuf->list); | ||
2380 | lpfc_bsg_dma_page_free(phba, dmabuf); | ||
2381 | } | ||
2382 | return; | ||
2383 | } | ||
2384 | |||
2385 | /** | ||
1854 | * diag_cmd_data_alloc - fills in a bde struct with dma buffers | 2386 | * diag_cmd_data_alloc - fills in a bde struct with dma buffers |
1855 | * @phba: Pointer to HBA context object | 2387 | * @phba: Pointer to HBA context object |
1856 | * @bpl: Pointer to 64 bit bde structure | 2388 | * @bpl: Pointer to 64 bit bde structure |
@@ -2067,7 +2599,7 @@ err_post_rxbufs_exit: | |||
2067 | } | 2599 | } |
2068 | 2600 | ||
2069 | /** | 2601 | /** |
2070 | * lpfc_bsg_diag_test - with a port in loopback issues a Ct cmd to itself | 2602 | * lpfc_bsg_diag_loopback_run - run loopback on a port by issue ct cmd to itself |
2071 | * @job: LPFC_BSG_VENDOR_DIAG_TEST fc_bsg_job | 2603 | * @job: LPFC_BSG_VENDOR_DIAG_TEST fc_bsg_job |
2072 | * | 2604 | * |
2073 | * This function receives a user data buffer to be transmitted and received on | 2605 | * This function receives a user data buffer to be transmitted and received on |
@@ -2086,7 +2618,7 @@ err_post_rxbufs_exit: | |||
2086 | * of loopback mode. | 2618 | * of loopback mode. |
2087 | **/ | 2619 | **/ |
2088 | static int | 2620 | static int |
2089 | lpfc_bsg_diag_test(struct fc_bsg_job *job) | 2621 | lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) |
2090 | { | 2622 | { |
2091 | struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; | 2623 | struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; |
2092 | struct lpfc_hba *phba = vport->phba; | 2624 | struct lpfc_hba *phba = vport->phba; |
@@ -2411,7 +2943,7 @@ job_error: | |||
2411 | } | 2943 | } |
2412 | 2944 | ||
2413 | /** | 2945 | /** |
2414 | * lpfc_bsg_wake_mbox_wait - lpfc_bsg_issue_mbox mbox completion handler | 2946 | * lpfc_bsg_issue_mbox_cmpl - lpfc_bsg_issue_mbox mbox completion handler |
2415 | * @phba: Pointer to HBA context object. | 2947 | * @phba: Pointer to HBA context object. |
2416 | * @pmboxq: Pointer to mailbox command. | 2948 | * @pmboxq: Pointer to mailbox command. |
2417 | * | 2949 | * |
@@ -2422,15 +2954,13 @@ job_error: | |||
2422 | * of the mailbox. | 2954 | * of the mailbox. |
2423 | **/ | 2955 | **/ |
2424 | void | 2956 | void |
2425 | lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | 2957 | lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) |
2426 | { | 2958 | { |
2427 | struct bsg_job_data *dd_data; | 2959 | struct bsg_job_data *dd_data; |
2428 | struct fc_bsg_job *job; | 2960 | struct fc_bsg_job *job; |
2429 | struct lpfc_mbx_nembed_cmd *nembed_sge; | ||
2430 | uint32_t size; | 2961 | uint32_t size; |
2431 | unsigned long flags; | 2962 | unsigned long flags; |
2432 | uint8_t *to; | 2963 | uint8_t *pmb, *pmb_buf; |
2433 | uint8_t *from; | ||
2434 | 2964 | ||
2435 | spin_lock_irqsave(&phba->ct_ev_lock, flags); | 2965 | spin_lock_irqsave(&phba->ct_ev_lock, flags); |
2436 | dd_data = pmboxq->context1; | 2966 | dd_data = pmboxq->context1; |
@@ -2440,62 +2970,21 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | |||
2440 | return; | 2970 | return; |
2441 | } | 2971 | } |
2442 | 2972 | ||
2443 | /* build the outgoing buffer to do an sg copy | 2973 | /* |
2444 | * the format is the response mailbox followed by any extended | 2974 | * The outgoing buffer is readily referred from the dma buffer, |
2445 | * mailbox data | 2975 | * just need to get header part from mailboxq structure. |
2446 | */ | 2976 | */ |
2447 | from = (uint8_t *)&pmboxq->u.mb; | 2977 | pmb = (uint8_t *)&pmboxq->u.mb; |
2448 | to = (uint8_t *)dd_data->context_un.mbox.mb; | 2978 | pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb; |
2449 | memcpy(to, from, sizeof(MAILBOX_t)); | 2979 | memcpy(pmb_buf, pmb, sizeof(MAILBOX_t)); |
2450 | if (pmboxq->u.mb.mbxStatus == MBX_SUCCESS) { | ||
2451 | /* copy the extended data if any, count is in words */ | ||
2452 | if (dd_data->context_un.mbox.outExtWLen) { | ||
2453 | from = (uint8_t *)dd_data->context_un.mbox.ext; | ||
2454 | to += sizeof(MAILBOX_t); | ||
2455 | size = dd_data->context_un.mbox.outExtWLen * | ||
2456 | sizeof(uint32_t); | ||
2457 | memcpy(to, from, size); | ||
2458 | } else if (pmboxq->u.mb.mbxCommand == MBX_RUN_BIU_DIAG64) { | ||
2459 | from = (uint8_t *)dd_data->context_un.mbox. | ||
2460 | dmp->dma.virt; | ||
2461 | to += sizeof(MAILBOX_t); | ||
2462 | size = dd_data->context_un.mbox.dmp->size; | ||
2463 | memcpy(to, from, size); | ||
2464 | } else if ((phba->sli_rev == LPFC_SLI_REV4) && | ||
2465 | (pmboxq->u.mb.mbxCommand == MBX_DUMP_MEMORY)) { | ||
2466 | from = (uint8_t *)dd_data->context_un.mbox.dmp->dma. | ||
2467 | virt; | ||
2468 | to += sizeof(MAILBOX_t); | ||
2469 | size = pmboxq->u.mb.un.varWords[5]; | ||
2470 | memcpy(to, from, size); | ||
2471 | } else if ((phba->sli_rev == LPFC_SLI_REV4) && | ||
2472 | (pmboxq->u.mb.mbxCommand == MBX_SLI4_CONFIG)) { | ||
2473 | nembed_sge = (struct lpfc_mbx_nembed_cmd *) | ||
2474 | &pmboxq->u.mb.un.varWords[0]; | ||
2475 | |||
2476 | from = (uint8_t *)dd_data->context_un.mbox.dmp->dma. | ||
2477 | virt; | ||
2478 | to += sizeof(MAILBOX_t); | ||
2479 | size = nembed_sge->sge[0].length; | ||
2480 | memcpy(to, from, size); | ||
2481 | } else if (pmboxq->u.mb.mbxCommand == MBX_READ_EVENT_LOG) { | ||
2482 | from = (uint8_t *)dd_data->context_un. | ||
2483 | mbox.dmp->dma.virt; | ||
2484 | to += sizeof(MAILBOX_t); | ||
2485 | size = dd_data->context_un.mbox.dmp->size; | ||
2486 | memcpy(to, from, size); | ||
2487 | } | ||
2488 | } | ||
2489 | 2980 | ||
2490 | from = (uint8_t *)dd_data->context_un.mbox.mb; | ||
2491 | job = dd_data->context_un.mbox.set_job; | 2981 | job = dd_data->context_un.mbox.set_job; |
2492 | if (job) { | 2982 | if (job) { |
2493 | size = job->reply_payload.payload_len; | 2983 | size = job->reply_payload.payload_len; |
2494 | job->reply->reply_payload_rcv_len = | 2984 | job->reply->reply_payload_rcv_len = |
2495 | sg_copy_from_buffer(job->reply_payload.sg_list, | 2985 | sg_copy_from_buffer(job->reply_payload.sg_list, |
2496 | job->reply_payload.sg_cnt, | 2986 | job->reply_payload.sg_cnt, |
2497 | from, size); | 2987 | pmb_buf, size); |
2498 | job->reply->result = 0; | ||
2499 | /* need to hold the lock until we set job->dd_data to NULL | 2988 | /* need to hold the lock until we set job->dd_data to NULL |
2500 | * to hold off the timeout handler returning to the mid-layer | 2989 | * to hold off the timeout handler returning to the mid-layer |
2501 | * while we are still processing the job. | 2990 | * while we are still processing the job. |
@@ -2503,28 +2992,19 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | |||
2503 | job->dd_data = NULL; | 2992 | job->dd_data = NULL; |
2504 | dd_data->context_un.mbox.set_job = NULL; | 2993 | dd_data->context_un.mbox.set_job = NULL; |
2505 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 2994 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
2506 | job->job_done(job); | ||
2507 | } else { | 2995 | } else { |
2508 | dd_data->context_un.mbox.set_job = NULL; | 2996 | dd_data->context_un.mbox.set_job = NULL; |
2509 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 2997 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
2510 | } | 2998 | } |
2511 | 2999 | ||
2512 | kfree(dd_data->context_un.mbox.mb); | ||
2513 | mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool); | 3000 | mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool); |
2514 | kfree(dd_data->context_un.mbox.ext); | 3001 | lpfc_bsg_dma_page_free(phba, dd_data->context_un.mbox.dmabuffers); |
2515 | if (dd_data->context_un.mbox.dmp) { | ||
2516 | dma_free_coherent(&phba->pcidev->dev, | ||
2517 | dd_data->context_un.mbox.dmp->size, | ||
2518 | dd_data->context_un.mbox.dmp->dma.virt, | ||
2519 | dd_data->context_un.mbox.dmp->dma.phys); | ||
2520 | kfree(dd_data->context_un.mbox.dmp); | ||
2521 | } | ||
2522 | if (dd_data->context_un.mbox.rxbmp) { | ||
2523 | lpfc_mbuf_free(phba, dd_data->context_un.mbox.rxbmp->virt, | ||
2524 | dd_data->context_un.mbox.rxbmp->phys); | ||
2525 | kfree(dd_data->context_un.mbox.rxbmp); | ||
2526 | } | ||
2527 | kfree(dd_data); | 3002 | kfree(dd_data); |
3003 | |||
3004 | if (job) { | ||
3005 | job->reply->result = 0; | ||
3006 | job->job_done(job); | ||
3007 | } | ||
2528 | return; | 3008 | return; |
2529 | } | 3009 | } |
2530 | 3010 | ||
@@ -2619,6 +3099,1006 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba, | |||
2619 | } | 3099 | } |
2620 | 3100 | ||
2621 | /** | 3101 | /** |
3102 | * lpfc_bsg_mbox_ext_cleanup - clean up context of multi-buffer mbox session | ||
3103 | * @phba: Pointer to HBA context object. | ||
3104 | * | ||
3105 | * This is routine clean up and reset BSG handling of multi-buffer mbox | ||
3106 | * command session. | ||
3107 | **/ | ||
3108 | static void | ||
3109 | lpfc_bsg_mbox_ext_session_reset(struct lpfc_hba *phba) | ||
3110 | { | ||
3111 | if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_IDLE) | ||
3112 | return; | ||
3113 | |||
3114 | /* free all memory, including dma buffers */ | ||
3115 | lpfc_bsg_dma_page_list_free(phba, | ||
3116 | &phba->mbox_ext_buf_ctx.ext_dmabuf_list); | ||
3117 | lpfc_bsg_dma_page_free(phba, phba->mbox_ext_buf_ctx.mbx_dmabuf); | ||
3118 | /* multi-buffer write mailbox command pass-through complete */ | ||
3119 | memset((char *)&phba->mbox_ext_buf_ctx, 0, | ||
3120 | sizeof(struct lpfc_mbox_ext_buf_ctx)); | ||
3121 | INIT_LIST_HEAD(&phba->mbox_ext_buf_ctx.ext_dmabuf_list); | ||
3122 | |||
3123 | return; | ||
3124 | } | ||
3125 | |||
3126 | /** | ||
3127 | * lpfc_bsg_issue_mbox_ext_handle_job - job handler for multi-buffer mbox cmpl | ||
3128 | * @phba: Pointer to HBA context object. | ||
3129 | * @pmboxq: Pointer to mailbox command. | ||
3130 | * | ||
3131 | * This is routine handles BSG job for mailbox commands completions with | ||
3132 | * multiple external buffers. | ||
3133 | **/ | ||
3134 | static struct fc_bsg_job * | ||
3135 | lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | ||
3136 | { | ||
3137 | struct bsg_job_data *dd_data; | ||
3138 | struct fc_bsg_job *job; | ||
3139 | uint8_t *pmb, *pmb_buf; | ||
3140 | unsigned long flags; | ||
3141 | uint32_t size; | ||
3142 | int rc = 0; | ||
3143 | |||
3144 | spin_lock_irqsave(&phba->ct_ev_lock, flags); | ||
3145 | dd_data = pmboxq->context1; | ||
3146 | /* has the job already timed out? */ | ||
3147 | if (!dd_data) { | ||
3148 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
3149 | job = NULL; | ||
3150 | goto job_done_out; | ||
3151 | } | ||
3152 | |||
3153 | /* | ||
3154 | * The outgoing buffer is readily referred from the dma buffer, | ||
3155 | * just need to get header part from mailboxq structure. | ||
3156 | */ | ||
3157 | pmb = (uint8_t *)&pmboxq->u.mb; | ||
3158 | pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb; | ||
3159 | memcpy(pmb_buf, pmb, sizeof(MAILBOX_t)); | ||
3160 | |||
3161 | job = dd_data->context_un.mbox.set_job; | ||
3162 | if (job) { | ||
3163 | size = job->reply_payload.payload_len; | ||
3164 | job->reply->reply_payload_rcv_len = | ||
3165 | sg_copy_from_buffer(job->reply_payload.sg_list, | ||
3166 | job->reply_payload.sg_cnt, | ||
3167 | pmb_buf, size); | ||
3168 | /* result for successful */ | ||
3169 | job->reply->result = 0; | ||
3170 | job->dd_data = NULL; | ||
3171 | /* need to hold the lock util we set job->dd_data to NULL | ||
3172 | * to hold off the timeout handler from midlayer to take | ||
3173 | * any action. | ||
3174 | */ | ||
3175 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
3176 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3177 | "2937 SLI_CONFIG ext-buffer maibox command " | ||
3178 | "(x%x/x%x) complete bsg job done, bsize:%d\n", | ||
3179 | phba->mbox_ext_buf_ctx.nembType, | ||
3180 | phba->mbox_ext_buf_ctx.mboxType, size); | ||
3181 | } else | ||
3182 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
3183 | |||
3184 | job_done_out: | ||
3185 | if (!job) | ||
3186 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
3187 | "2938 SLI_CONFIG ext-buffer maibox " | ||
3188 | "command (x%x/x%x) failure, rc:x%x\n", | ||
3189 | phba->mbox_ext_buf_ctx.nembType, | ||
3190 | phba->mbox_ext_buf_ctx.mboxType, rc); | ||
3191 | /* state change */ | ||
3192 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_DONE; | ||
3193 | kfree(dd_data); | ||
3194 | |||
3195 | return job; | ||
3196 | } | ||
3197 | |||
3198 | /** | ||
3199 | * lpfc_bsg_issue_read_mbox_ext_cmpl - compl handler for multi-buffer read mbox | ||
3200 | * @phba: Pointer to HBA context object. | ||
3201 | * @pmboxq: Pointer to mailbox command. | ||
3202 | * | ||
3203 | * This is completion handler function for mailbox read commands with multiple | ||
3204 | * external buffers. | ||
3205 | **/ | ||
3206 | static void | ||
3207 | lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | ||
3208 | { | ||
3209 | struct fc_bsg_job *job; | ||
3210 | |||
3211 | /* handle the BSG job with mailbox command */ | ||
3212 | if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_ABTS) | ||
3213 | pmboxq->u.mb.mbxStatus = MBXERR_ERROR; | ||
3214 | |||
3215 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3216 | "2939 SLI_CONFIG ext-buffer rd maibox command " | ||
3217 | "complete, ctxState:x%x, mbxStatus:x%x\n", | ||
3218 | phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus); | ||
3219 | |||
3220 | job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq); | ||
3221 | |||
3222 | if (pmboxq->u.mb.mbxStatus || phba->mbox_ext_buf_ctx.numBuf == 1) | ||
3223 | lpfc_bsg_mbox_ext_session_reset(phba); | ||
3224 | |||
3225 | /* free base driver mailbox structure memory */ | ||
3226 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
3227 | |||
3228 | /* complete the bsg job if we have it */ | ||
3229 | if (job) | ||
3230 | job->job_done(job); | ||
3231 | |||
3232 | return; | ||
3233 | } | ||
3234 | |||
3235 | /** | ||
3236 | * lpfc_bsg_issue_write_mbox_ext_cmpl - cmpl handler for multi-buffer write mbox | ||
3237 | * @phba: Pointer to HBA context object. | ||
3238 | * @pmboxq: Pointer to mailbox command. | ||
3239 | * | ||
3240 | * This is completion handler function for mailbox write commands with multiple | ||
3241 | * external buffers. | ||
3242 | **/ | ||
3243 | static void | ||
3244 | lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | ||
3245 | { | ||
3246 | struct fc_bsg_job *job; | ||
3247 | |||
3248 | /* handle the BSG job with the mailbox command */ | ||
3249 | if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_ABTS) | ||
3250 | pmboxq->u.mb.mbxStatus = MBXERR_ERROR; | ||
3251 | |||
3252 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3253 | "2940 SLI_CONFIG ext-buffer wr maibox command " | ||
3254 | "complete, ctxState:x%x, mbxStatus:x%x\n", | ||
3255 | phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus); | ||
3256 | |||
3257 | job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq); | ||
3258 | |||
3259 | /* free all memory, including dma buffers */ | ||
3260 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
3261 | lpfc_bsg_mbox_ext_session_reset(phba); | ||
3262 | |||
3263 | /* complete the bsg job if we have it */ | ||
3264 | if (job) | ||
3265 | job->job_done(job); | ||
3266 | |||
3267 | return; | ||
3268 | } | ||
3269 | |||
3270 | static void | ||
3271 | lpfc_bsg_sli_cfg_dma_desc_setup(struct lpfc_hba *phba, enum nemb_type nemb_tp, | ||
3272 | uint32_t index, struct lpfc_dmabuf *mbx_dmabuf, | ||
3273 | struct lpfc_dmabuf *ext_dmabuf) | ||
3274 | { | ||
3275 | struct lpfc_sli_config_mbox *sli_cfg_mbx; | ||
3276 | |||
3277 | /* pointer to the start of mailbox command */ | ||
3278 | sli_cfg_mbx = (struct lpfc_sli_config_mbox *)mbx_dmabuf->virt; | ||
3279 | |||
3280 | if (nemb_tp == nemb_mse) { | ||
3281 | if (index == 0) { | ||
3282 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
3283 | mse[index].pa_hi = | ||
3284 | putPaddrHigh(mbx_dmabuf->phys + | ||
3285 | sizeof(MAILBOX_t)); | ||
3286 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
3287 | mse[index].pa_lo = | ||
3288 | putPaddrLow(mbx_dmabuf->phys + | ||
3289 | sizeof(MAILBOX_t)); | ||
3290 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3291 | "2943 SLI_CONFIG(mse)[%d], " | ||
3292 | "bufLen:%d, addrHi:x%x, addrLo:x%x\n", | ||
3293 | index, | ||
3294 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
3295 | mse[index].buf_len, | ||
3296 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
3297 | mse[index].pa_hi, | ||
3298 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
3299 | mse[index].pa_lo); | ||
3300 | } else { | ||
3301 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
3302 | mse[index].pa_hi = | ||
3303 | putPaddrHigh(ext_dmabuf->phys); | ||
3304 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
3305 | mse[index].pa_lo = | ||
3306 | putPaddrLow(ext_dmabuf->phys); | ||
3307 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3308 | "2944 SLI_CONFIG(mse)[%d], " | ||
3309 | "bufLen:%d, addrHi:x%x, addrLo:x%x\n", | ||
3310 | index, | ||
3311 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
3312 | mse[index].buf_len, | ||
3313 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
3314 | mse[index].pa_hi, | ||
3315 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
3316 | mse[index].pa_lo); | ||
3317 | } | ||
3318 | } else { | ||
3319 | if (index == 0) { | ||
3320 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
3321 | hbd[index].pa_hi = | ||
3322 | putPaddrHigh(mbx_dmabuf->phys + | ||
3323 | sizeof(MAILBOX_t)); | ||
3324 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
3325 | hbd[index].pa_lo = | ||
3326 | putPaddrLow(mbx_dmabuf->phys + | ||
3327 | sizeof(MAILBOX_t)); | ||
3328 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3329 | "3007 SLI_CONFIG(hbd)[%d], " | ||
3330 | "bufLen:%d, addrHi:x%x, addrLo:x%x\n", | ||
3331 | index, | ||
3332 | bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len, | ||
3333 | &sli_cfg_mbx->un. | ||
3334 | sli_config_emb1_subsys.hbd[index]), | ||
3335 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
3336 | hbd[index].pa_hi, | ||
3337 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
3338 | hbd[index].pa_lo); | ||
3339 | |||
3340 | } else { | ||
3341 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
3342 | hbd[index].pa_hi = | ||
3343 | putPaddrHigh(ext_dmabuf->phys); | ||
3344 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
3345 | hbd[index].pa_lo = | ||
3346 | putPaddrLow(ext_dmabuf->phys); | ||
3347 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3348 | "3008 SLI_CONFIG(hbd)[%d], " | ||
3349 | "bufLen:%d, addrHi:x%x, addrLo:x%x\n", | ||
3350 | index, | ||
3351 | bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len, | ||
3352 | &sli_cfg_mbx->un. | ||
3353 | sli_config_emb1_subsys.hbd[index]), | ||
3354 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
3355 | hbd[index].pa_hi, | ||
3356 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
3357 | hbd[index].pa_lo); | ||
3358 | } | ||
3359 | } | ||
3360 | return; | ||
3361 | } | ||
3362 | |||
3363 | /** | ||
3364 | * lpfc_bsg_sli_cfg_mse_read_cmd_ext - sli_config non-embedded mailbox cmd read | ||
3365 | * @phba: Pointer to HBA context object. | ||
3366 | * @mb: Pointer to a BSG mailbox object. | ||
3367 | * @nemb_tp: Enumerate of non-embedded mailbox command type. | ||
3368 | * @dmabuff: Pointer to a DMA buffer descriptor. | ||
3369 | * | ||
3370 | * This routine performs SLI_CONFIG (0x9B) read mailbox command operation with | ||
3371 | * non-embedded external bufffers. | ||
3372 | **/ | ||
3373 | static int | ||
3374 | lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, | ||
3375 | enum nemb_type nemb_tp, | ||
3376 | struct lpfc_dmabuf *dmabuf) | ||
3377 | { | ||
3378 | struct lpfc_sli_config_mbox *sli_cfg_mbx; | ||
3379 | struct dfc_mbox_req *mbox_req; | ||
3380 | struct lpfc_dmabuf *curr_dmabuf, *next_dmabuf; | ||
3381 | uint32_t ext_buf_cnt, ext_buf_index; | ||
3382 | struct lpfc_dmabuf *ext_dmabuf = NULL; | ||
3383 | struct bsg_job_data *dd_data = NULL; | ||
3384 | LPFC_MBOXQ_t *pmboxq = NULL; | ||
3385 | MAILBOX_t *pmb; | ||
3386 | uint8_t *pmbx; | ||
3387 | int rc, i; | ||
3388 | |||
3389 | mbox_req = | ||
3390 | (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd; | ||
3391 | |||
3392 | /* pointer to the start of mailbox command */ | ||
3393 | sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt; | ||
3394 | |||
3395 | if (nemb_tp == nemb_mse) { | ||
3396 | ext_buf_cnt = bsg_bf_get(lpfc_mbox_hdr_mse_cnt, | ||
3397 | &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr); | ||
3398 | if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE) { | ||
3399 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
3400 | "2945 Handled SLI_CONFIG(mse) rd, " | ||
3401 | "ext_buf_cnt(%d) out of range(%d)\n", | ||
3402 | ext_buf_cnt, | ||
3403 | LPFC_MBX_SLI_CONFIG_MAX_MSE); | ||
3404 | rc = -ERANGE; | ||
3405 | goto job_error; | ||
3406 | } | ||
3407 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3408 | "2941 Handled SLI_CONFIG(mse) rd, " | ||
3409 | "ext_buf_cnt:%d\n", ext_buf_cnt); | ||
3410 | } else { | ||
3411 | /* sanity check on interface type for support */ | ||
3412 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
3413 | LPFC_SLI_INTF_IF_TYPE_2) { | ||
3414 | rc = -ENODEV; | ||
3415 | goto job_error; | ||
3416 | } | ||
3417 | /* nemb_tp == nemb_hbd */ | ||
3418 | ext_buf_cnt = sli_cfg_mbx->un.sli_config_emb1_subsys.hbd_count; | ||
3419 | if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_HBD) { | ||
3420 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
3421 | "2946 Handled SLI_CONFIG(hbd) rd, " | ||
3422 | "ext_buf_cnt(%d) out of range(%d)\n", | ||
3423 | ext_buf_cnt, | ||
3424 | LPFC_MBX_SLI_CONFIG_MAX_HBD); | ||
3425 | rc = -ERANGE; | ||
3426 | goto job_error; | ||
3427 | } | ||
3428 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3429 | "2942 Handled SLI_CONFIG(hbd) rd, " | ||
3430 | "ext_buf_cnt:%d\n", ext_buf_cnt); | ||
3431 | } | ||
3432 | |||
3433 | /* reject non-embedded mailbox command with none external buffer */ | ||
3434 | if (ext_buf_cnt == 0) { | ||
3435 | rc = -EPERM; | ||
3436 | goto job_error; | ||
3437 | } else if (ext_buf_cnt > 1) { | ||
3438 | /* additional external read buffers */ | ||
3439 | for (i = 1; i < ext_buf_cnt; i++) { | ||
3440 | ext_dmabuf = lpfc_bsg_dma_page_alloc(phba); | ||
3441 | if (!ext_dmabuf) { | ||
3442 | rc = -ENOMEM; | ||
3443 | goto job_error; | ||
3444 | } | ||
3445 | list_add_tail(&ext_dmabuf->list, | ||
3446 | &phba->mbox_ext_buf_ctx.ext_dmabuf_list); | ||
3447 | } | ||
3448 | } | ||
3449 | |||
3450 | /* bsg tracking structure */ | ||
3451 | dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); | ||
3452 | if (!dd_data) { | ||
3453 | rc = -ENOMEM; | ||
3454 | goto job_error; | ||
3455 | } | ||
3456 | |||
3457 | /* mailbox command structure for base driver */ | ||
3458 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
3459 | if (!pmboxq) { | ||
3460 | rc = -ENOMEM; | ||
3461 | goto job_error; | ||
3462 | } | ||
3463 | memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); | ||
3464 | |||
3465 | /* for the first external buffer */ | ||
3466 | lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf); | ||
3467 | |||
3468 | /* for the rest of external buffer descriptors if any */ | ||
3469 | if (ext_buf_cnt > 1) { | ||
3470 | ext_buf_index = 1; | ||
3471 | list_for_each_entry_safe(curr_dmabuf, next_dmabuf, | ||
3472 | &phba->mbox_ext_buf_ctx.ext_dmabuf_list, list) { | ||
3473 | lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, | ||
3474 | ext_buf_index, dmabuf, | ||
3475 | curr_dmabuf); | ||
3476 | ext_buf_index++; | ||
3477 | } | ||
3478 | } | ||
3479 | |||
3480 | /* construct base driver mbox command */ | ||
3481 | pmb = &pmboxq->u.mb; | ||
3482 | pmbx = (uint8_t *)dmabuf->virt; | ||
3483 | memcpy(pmb, pmbx, sizeof(*pmb)); | ||
3484 | pmb->mbxOwner = OWN_HOST; | ||
3485 | pmboxq->vport = phba->pport; | ||
3486 | |||
3487 | /* multi-buffer handling context */ | ||
3488 | phba->mbox_ext_buf_ctx.nembType = nemb_tp; | ||
3489 | phba->mbox_ext_buf_ctx.mboxType = mbox_rd; | ||
3490 | phba->mbox_ext_buf_ctx.numBuf = ext_buf_cnt; | ||
3491 | phba->mbox_ext_buf_ctx.mbxTag = mbox_req->extMboxTag; | ||
3492 | phba->mbox_ext_buf_ctx.seqNum = mbox_req->extSeqNum; | ||
3493 | phba->mbox_ext_buf_ctx.mbx_dmabuf = dmabuf; | ||
3494 | |||
3495 | /* callback for multi-buffer read mailbox command */ | ||
3496 | pmboxq->mbox_cmpl = lpfc_bsg_issue_read_mbox_ext_cmpl; | ||
3497 | |||
3498 | /* context fields to callback function */ | ||
3499 | pmboxq->context1 = dd_data; | ||
3500 | dd_data->type = TYPE_MBOX; | ||
3501 | dd_data->context_un.mbox.pmboxq = pmboxq; | ||
3502 | dd_data->context_un.mbox.mb = (MAILBOX_t *)pmbx; | ||
3503 | dd_data->context_un.mbox.set_job = job; | ||
3504 | job->dd_data = dd_data; | ||
3505 | |||
3506 | /* state change */ | ||
3507 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT; | ||
3508 | |||
3509 | rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); | ||
3510 | if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) { | ||
3511 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3512 | "2947 Issued SLI_CONFIG ext-buffer " | ||
3513 | "maibox command, rc:x%x\n", rc); | ||
3514 | return 1; | ||
3515 | } | ||
3516 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
3517 | "2948 Failed to issue SLI_CONFIG ext-buffer " | ||
3518 | "maibox command, rc:x%x\n", rc); | ||
3519 | rc = -EPIPE; | ||
3520 | |||
3521 | job_error: | ||
3522 | if (pmboxq) | ||
3523 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
3524 | lpfc_bsg_dma_page_list_free(phba, | ||
3525 | &phba->mbox_ext_buf_ctx.ext_dmabuf_list); | ||
3526 | kfree(dd_data); | ||
3527 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_IDLE; | ||
3528 | return rc; | ||
3529 | } | ||
3530 | |||
3531 | /** | ||
3532 | * lpfc_bsg_sli_cfg_write_cmd_ext - sli_config non-embedded mailbox cmd write | ||
3533 | * @phba: Pointer to HBA context object. | ||
3534 | * @mb: Pointer to a BSG mailbox object. | ||
3535 | * @dmabuff: Pointer to a DMA buffer descriptor. | ||
3536 | * | ||
3537 | * This routine performs SLI_CONFIG (0x9B) write mailbox command operation with | ||
3538 | * non-embedded external bufffers. | ||
3539 | **/ | ||
3540 | static int | ||
3541 | lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, | ||
3542 | enum nemb_type nemb_tp, | ||
3543 | struct lpfc_dmabuf *dmabuf) | ||
3544 | { | ||
3545 | struct dfc_mbox_req *mbox_req; | ||
3546 | struct lpfc_sli_config_mbox *sli_cfg_mbx; | ||
3547 | uint32_t ext_buf_cnt; | ||
3548 | struct bsg_job_data *dd_data = NULL; | ||
3549 | LPFC_MBOXQ_t *pmboxq = NULL; | ||
3550 | MAILBOX_t *pmb; | ||
3551 | uint8_t *mbx; | ||
3552 | int rc = 0, i; | ||
3553 | |||
3554 | mbox_req = | ||
3555 | (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd; | ||
3556 | |||
3557 | /* pointer to the start of mailbox command */ | ||
3558 | sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt; | ||
3559 | |||
3560 | if (nemb_tp == nemb_mse) { | ||
3561 | ext_buf_cnt = bsg_bf_get(lpfc_mbox_hdr_mse_cnt, | ||
3562 | &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr); | ||
3563 | if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE) { | ||
3564 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
3565 | "2953 Handled SLI_CONFIG(mse) wr, " | ||
3566 | "ext_buf_cnt(%d) out of range(%d)\n", | ||
3567 | ext_buf_cnt, | ||
3568 | LPFC_MBX_SLI_CONFIG_MAX_MSE); | ||
3569 | return -ERANGE; | ||
3570 | } | ||
3571 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3572 | "2949 Handled SLI_CONFIG(mse) wr, " | ||
3573 | "ext_buf_cnt:%d\n", ext_buf_cnt); | ||
3574 | } else { | ||
3575 | /* sanity check on interface type for support */ | ||
3576 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
3577 | LPFC_SLI_INTF_IF_TYPE_2) | ||
3578 | return -ENODEV; | ||
3579 | /* nemb_tp == nemb_hbd */ | ||
3580 | ext_buf_cnt = sli_cfg_mbx->un.sli_config_emb1_subsys.hbd_count; | ||
3581 | if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_HBD) { | ||
3582 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
3583 | "2954 Handled SLI_CONFIG(hbd) wr, " | ||
3584 | "ext_buf_cnt(%d) out of range(%d)\n", | ||
3585 | ext_buf_cnt, | ||
3586 | LPFC_MBX_SLI_CONFIG_MAX_HBD); | ||
3587 | return -ERANGE; | ||
3588 | } | ||
3589 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3590 | "2950 Handled SLI_CONFIG(hbd) wr, " | ||
3591 | "ext_buf_cnt:%d\n", ext_buf_cnt); | ||
3592 | } | ||
3593 | |||
3594 | if (ext_buf_cnt == 0) | ||
3595 | return -EPERM; | ||
3596 | |||
3597 | /* for the first external buffer */ | ||
3598 | lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf); | ||
3599 | |||
3600 | /* log for looking forward */ | ||
3601 | for (i = 1; i < ext_buf_cnt; i++) { | ||
3602 | if (nemb_tp == nemb_mse) | ||
3603 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3604 | "2951 SLI_CONFIG(mse), buf[%d]-length:%d\n", | ||
3605 | i, sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
3606 | mse[i].buf_len); | ||
3607 | else | ||
3608 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3609 | "2952 SLI_CONFIG(hbd), buf[%d]-length:%d\n", | ||
3610 | i, bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len, | ||
3611 | &sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
3612 | hbd[i])); | ||
3613 | } | ||
3614 | |||
3615 | /* multi-buffer handling context */ | ||
3616 | phba->mbox_ext_buf_ctx.nembType = nemb_tp; | ||
3617 | phba->mbox_ext_buf_ctx.mboxType = mbox_wr; | ||
3618 | phba->mbox_ext_buf_ctx.numBuf = ext_buf_cnt; | ||
3619 | phba->mbox_ext_buf_ctx.mbxTag = mbox_req->extMboxTag; | ||
3620 | phba->mbox_ext_buf_ctx.seqNum = mbox_req->extSeqNum; | ||
3621 | phba->mbox_ext_buf_ctx.mbx_dmabuf = dmabuf; | ||
3622 | |||
3623 | if (ext_buf_cnt == 1) { | ||
3624 | /* bsg tracking structure */ | ||
3625 | dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); | ||
3626 | if (!dd_data) { | ||
3627 | rc = -ENOMEM; | ||
3628 | goto job_error; | ||
3629 | } | ||
3630 | |||
3631 | /* mailbox command structure for base driver */ | ||
3632 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
3633 | if (!pmboxq) { | ||
3634 | rc = -ENOMEM; | ||
3635 | goto job_error; | ||
3636 | } | ||
3637 | memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); | ||
3638 | pmb = &pmboxq->u.mb; | ||
3639 | mbx = (uint8_t *)dmabuf->virt; | ||
3640 | memcpy(pmb, mbx, sizeof(*pmb)); | ||
3641 | pmb->mbxOwner = OWN_HOST; | ||
3642 | pmboxq->vport = phba->pport; | ||
3643 | |||
3644 | /* callback for multi-buffer read mailbox command */ | ||
3645 | pmboxq->mbox_cmpl = lpfc_bsg_issue_write_mbox_ext_cmpl; | ||
3646 | |||
3647 | /* context fields to callback function */ | ||
3648 | pmboxq->context1 = dd_data; | ||
3649 | dd_data->type = TYPE_MBOX; | ||
3650 | dd_data->context_un.mbox.pmboxq = pmboxq; | ||
3651 | dd_data->context_un.mbox.mb = (MAILBOX_t *)mbx; | ||
3652 | dd_data->context_un.mbox.set_job = job; | ||
3653 | job->dd_data = dd_data; | ||
3654 | |||
3655 | /* state change */ | ||
3656 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT; | ||
3657 | |||
3658 | rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); | ||
3659 | if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) { | ||
3660 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3661 | "2955 Issued SLI_CONFIG ext-buffer " | ||
3662 | "maibox command, rc:x%x\n", rc); | ||
3663 | return 1; | ||
3664 | } | ||
3665 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
3666 | "2956 Failed to issue SLI_CONFIG ext-buffer " | ||
3667 | "maibox command, rc:x%x\n", rc); | ||
3668 | rc = -EPIPE; | ||
3669 | } | ||
3670 | |||
3671 | job_error: | ||
3672 | if (pmboxq) | ||
3673 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
3674 | kfree(dd_data); | ||
3675 | |||
3676 | return rc; | ||
3677 | } | ||
3678 | |||
3679 | /** | ||
3680 | * lpfc_bsg_handle_sli_cfg_mbox - handle sli-cfg mailbox cmd with ext buffer | ||
3681 | * @phba: Pointer to HBA context object. | ||
3682 | * @mb: Pointer to a BSG mailbox object. | ||
3683 | * @dmabuff: Pointer to a DMA buffer descriptor. | ||
3684 | * | ||
3685 | * This routine handles SLI_CONFIG (0x9B) mailbox command with non-embedded | ||
3686 | * external bufffers, including both 0x9B with non-embedded MSEs and 0x9B | ||
3687 | * with embedded sussystem 0x1 and opcodes with external HBDs. | ||
3688 | **/ | ||
3689 | static int | ||
3690 | lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | ||
3691 | struct lpfc_dmabuf *dmabuf) | ||
3692 | { | ||
3693 | struct lpfc_sli_config_mbox *sli_cfg_mbx; | ||
3694 | uint32_t subsys; | ||
3695 | uint32_t opcode; | ||
3696 | int rc = SLI_CONFIG_NOT_HANDLED; | ||
3697 | |||
3698 | /* state change */ | ||
3699 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_HOST; | ||
3700 | |||
3701 | sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt; | ||
3702 | |||
3703 | if (!bsg_bf_get(lpfc_mbox_hdr_emb, | ||
3704 | &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) { | ||
3705 | subsys = bsg_bf_get(lpfc_emb0_subcmnd_subsys, | ||
3706 | &sli_cfg_mbx->un.sli_config_emb0_subsys); | ||
3707 | opcode = bsg_bf_get(lpfc_emb0_subcmnd_opcode, | ||
3708 | &sli_cfg_mbx->un.sli_config_emb0_subsys); | ||
3709 | if (subsys == SLI_CONFIG_SUBSYS_FCOE) { | ||
3710 | switch (opcode) { | ||
3711 | case FCOE_OPCODE_READ_FCF: | ||
3712 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3713 | "2957 Handled SLI_CONFIG " | ||
3714 | "subsys_fcoe, opcode:x%x\n", | ||
3715 | opcode); | ||
3716 | rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job, | ||
3717 | nemb_mse, dmabuf); | ||
3718 | break; | ||
3719 | case FCOE_OPCODE_ADD_FCF: | ||
3720 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3721 | "2958 Handled SLI_CONFIG " | ||
3722 | "subsys_fcoe, opcode:x%x\n", | ||
3723 | opcode); | ||
3724 | rc = lpfc_bsg_sli_cfg_write_cmd_ext(phba, job, | ||
3725 | nemb_mse, dmabuf); | ||
3726 | break; | ||
3727 | default: | ||
3728 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3729 | "2959 Not handled SLI_CONFIG " | ||
3730 | "subsys_fcoe, opcode:x%x\n", | ||
3731 | opcode); | ||
3732 | rc = SLI_CONFIG_NOT_HANDLED; | ||
3733 | break; | ||
3734 | } | ||
3735 | } else { | ||
3736 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3737 | "2977 Handled SLI_CONFIG " | ||
3738 | "subsys:x%d, opcode:x%x\n", | ||
3739 | subsys, opcode); | ||
3740 | rc = SLI_CONFIG_NOT_HANDLED; | ||
3741 | } | ||
3742 | } else { | ||
3743 | subsys = bsg_bf_get(lpfc_emb1_subcmnd_subsys, | ||
3744 | &sli_cfg_mbx->un.sli_config_emb1_subsys); | ||
3745 | opcode = bsg_bf_get(lpfc_emb1_subcmnd_opcode, | ||
3746 | &sli_cfg_mbx->un.sli_config_emb1_subsys); | ||
3747 | if (subsys == SLI_CONFIG_SUBSYS_COMN) { | ||
3748 | switch (opcode) { | ||
3749 | case COMN_OPCODE_READ_OBJECT: | ||
3750 | case COMN_OPCODE_READ_OBJECT_LIST: | ||
3751 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3752 | "2960 Handled SLI_CONFIG " | ||
3753 | "subsys_comn, opcode:x%x\n", | ||
3754 | opcode); | ||
3755 | rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job, | ||
3756 | nemb_hbd, dmabuf); | ||
3757 | break; | ||
3758 | case COMN_OPCODE_WRITE_OBJECT: | ||
3759 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3760 | "2961 Handled SLI_CONFIG " | ||
3761 | "subsys_comn, opcode:x%x\n", | ||
3762 | opcode); | ||
3763 | rc = lpfc_bsg_sli_cfg_write_cmd_ext(phba, job, | ||
3764 | nemb_hbd, dmabuf); | ||
3765 | break; | ||
3766 | default: | ||
3767 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3768 | "2962 Not handled SLI_CONFIG " | ||
3769 | "subsys_comn, opcode:x%x\n", | ||
3770 | opcode); | ||
3771 | rc = SLI_CONFIG_NOT_HANDLED; | ||
3772 | break; | ||
3773 | } | ||
3774 | } else { | ||
3775 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3776 | "2978 Handled SLI_CONFIG " | ||
3777 | "subsys:x%d, opcode:x%x\n", | ||
3778 | subsys, opcode); | ||
3779 | rc = SLI_CONFIG_NOT_HANDLED; | ||
3780 | } | ||
3781 | } | ||
3782 | return rc; | ||
3783 | } | ||
3784 | |||
3785 | /** | ||
3786 | * lpfc_bsg_mbox_ext_abort_req - request to abort mbox command with ext buffers | ||
3787 | * @phba: Pointer to HBA context object. | ||
3788 | * | ||
3789 | * This routine is for requesting to abort a pass-through mailbox command with | ||
3790 | * multiple external buffers due to error condition. | ||
3791 | **/ | ||
3792 | static void | ||
3793 | lpfc_bsg_mbox_ext_abort(struct lpfc_hba *phba) | ||
3794 | { | ||
3795 | if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_PORT) | ||
3796 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS; | ||
3797 | else | ||
3798 | lpfc_bsg_mbox_ext_session_reset(phba); | ||
3799 | return; | ||
3800 | } | ||
3801 | |||
3802 | /** | ||
3803 | * lpfc_bsg_read_ebuf_get - get the next mailbox read external buffer | ||
3804 | * @phba: Pointer to HBA context object. | ||
3805 | * @dmabuf: Pointer to a DMA buffer descriptor. | ||
3806 | * | ||
3807 | * This routine extracts the next mailbox read external buffer back to | ||
3808 | * user space through BSG. | ||
3809 | **/ | ||
3810 | static int | ||
3811 | lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job) | ||
3812 | { | ||
3813 | struct lpfc_sli_config_mbox *sli_cfg_mbx; | ||
3814 | struct lpfc_dmabuf *dmabuf; | ||
3815 | uint8_t *pbuf; | ||
3816 | uint32_t size; | ||
3817 | uint32_t index; | ||
3818 | |||
3819 | index = phba->mbox_ext_buf_ctx.seqNum; | ||
3820 | phba->mbox_ext_buf_ctx.seqNum++; | ||
3821 | |||
3822 | sli_cfg_mbx = (struct lpfc_sli_config_mbox *) | ||
3823 | phba->mbox_ext_buf_ctx.mbx_dmabuf->virt; | ||
3824 | |||
3825 | if (phba->mbox_ext_buf_ctx.nembType == nemb_mse) { | ||
3826 | size = bsg_bf_get(lpfc_mbox_sli_config_mse_len, | ||
3827 | &sli_cfg_mbx->un.sli_config_emb0_subsys.mse[index]); | ||
3828 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3829 | "2963 SLI_CONFIG (mse) ext-buffer rd get " | ||
3830 | "buffer[%d], size:%d\n", index, size); | ||
3831 | } else { | ||
3832 | size = bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len, | ||
3833 | &sli_cfg_mbx->un.sli_config_emb1_subsys.hbd[index]); | ||
3834 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3835 | "2964 SLI_CONFIG (hbd) ext-buffer rd get " | ||
3836 | "buffer[%d], size:%d\n", index, size); | ||
3837 | } | ||
3838 | if (list_empty(&phba->mbox_ext_buf_ctx.ext_dmabuf_list)) | ||
3839 | return -EPIPE; | ||
3840 | dmabuf = list_first_entry(&phba->mbox_ext_buf_ctx.ext_dmabuf_list, | ||
3841 | struct lpfc_dmabuf, list); | ||
3842 | list_del_init(&dmabuf->list); | ||
3843 | pbuf = (uint8_t *)dmabuf->virt; | ||
3844 | job->reply->reply_payload_rcv_len = | ||
3845 | sg_copy_from_buffer(job->reply_payload.sg_list, | ||
3846 | job->reply_payload.sg_cnt, | ||
3847 | pbuf, size); | ||
3848 | |||
3849 | lpfc_bsg_dma_page_free(phba, dmabuf); | ||
3850 | |||
3851 | if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) { | ||
3852 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3853 | "2965 SLI_CONFIG (hbd) ext-buffer rd mbox " | ||
3854 | "command session done\n"); | ||
3855 | lpfc_bsg_mbox_ext_session_reset(phba); | ||
3856 | } | ||
3857 | |||
3858 | job->reply->result = 0; | ||
3859 | job->job_done(job); | ||
3860 | |||
3861 | return SLI_CONFIG_HANDLED; | ||
3862 | } | ||
3863 | |||
3864 | /** | ||
3865 | * lpfc_bsg_write_ebuf_set - set the next mailbox write external buffer | ||
3866 | * @phba: Pointer to HBA context object. | ||
3867 | * @dmabuf: Pointer to a DMA buffer descriptor. | ||
3868 | * | ||
3869 | * This routine sets up the next mailbox read external buffer obtained | ||
3870 | * from user space through BSG. | ||
3871 | **/ | ||
3872 | static int | ||
3873 | lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job, | ||
3874 | struct lpfc_dmabuf *dmabuf) | ||
3875 | { | ||
3876 | struct lpfc_sli_config_mbox *sli_cfg_mbx; | ||
3877 | struct bsg_job_data *dd_data = NULL; | ||
3878 | LPFC_MBOXQ_t *pmboxq = NULL; | ||
3879 | MAILBOX_t *pmb; | ||
3880 | enum nemb_type nemb_tp; | ||
3881 | uint8_t *pbuf; | ||
3882 | uint32_t size; | ||
3883 | uint32_t index; | ||
3884 | int rc; | ||
3885 | |||
3886 | index = phba->mbox_ext_buf_ctx.seqNum; | ||
3887 | phba->mbox_ext_buf_ctx.seqNum++; | ||
3888 | nemb_tp = phba->mbox_ext_buf_ctx.nembType; | ||
3889 | |||
3890 | sli_cfg_mbx = (struct lpfc_sli_config_mbox *) | ||
3891 | phba->mbox_ext_buf_ctx.mbx_dmabuf->virt; | ||
3892 | |||
3893 | dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); | ||
3894 | if (!dd_data) { | ||
3895 | rc = -ENOMEM; | ||
3896 | goto job_error; | ||
3897 | } | ||
3898 | |||
3899 | pbuf = (uint8_t *)dmabuf->virt; | ||
3900 | size = job->request_payload.payload_len; | ||
3901 | sg_copy_to_buffer(job->request_payload.sg_list, | ||
3902 | job->request_payload.sg_cnt, | ||
3903 | pbuf, size); | ||
3904 | |||
3905 | if (phba->mbox_ext_buf_ctx.nembType == nemb_mse) { | ||
3906 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3907 | "2966 SLI_CONFIG (mse) ext-buffer wr set " | ||
3908 | "buffer[%d], size:%d\n", | ||
3909 | phba->mbox_ext_buf_ctx.seqNum, size); | ||
3910 | |||
3911 | } else { | ||
3912 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3913 | "2967 SLI_CONFIG (hbd) ext-buffer wr set " | ||
3914 | "buffer[%d], size:%d\n", | ||
3915 | phba->mbox_ext_buf_ctx.seqNum, size); | ||
3916 | |||
3917 | } | ||
3918 | |||
3919 | /* set up external buffer descriptor and add to external buffer list */ | ||
3920 | lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, index, | ||
3921 | phba->mbox_ext_buf_ctx.mbx_dmabuf, | ||
3922 | dmabuf); | ||
3923 | list_add_tail(&dmabuf->list, &phba->mbox_ext_buf_ctx.ext_dmabuf_list); | ||
3924 | |||
3925 | if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) { | ||
3926 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3927 | "2968 SLI_CONFIG ext-buffer wr all %d " | ||
3928 | "ebuffers received\n", | ||
3929 | phba->mbox_ext_buf_ctx.numBuf); | ||
3930 | /* mailbox command structure for base driver */ | ||
3931 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
3932 | if (!pmboxq) { | ||
3933 | rc = -ENOMEM; | ||
3934 | goto job_error; | ||
3935 | } | ||
3936 | memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); | ||
3937 | pbuf = (uint8_t *)phba->mbox_ext_buf_ctx.mbx_dmabuf->virt; | ||
3938 | pmb = &pmboxq->u.mb; | ||
3939 | memcpy(pmb, pbuf, sizeof(*pmb)); | ||
3940 | pmb->mbxOwner = OWN_HOST; | ||
3941 | pmboxq->vport = phba->pport; | ||
3942 | |||
3943 | /* callback for multi-buffer write mailbox command */ | ||
3944 | pmboxq->mbox_cmpl = lpfc_bsg_issue_write_mbox_ext_cmpl; | ||
3945 | |||
3946 | /* context fields to callback function */ | ||
3947 | pmboxq->context1 = dd_data; | ||
3948 | dd_data->type = TYPE_MBOX; | ||
3949 | dd_data->context_un.mbox.pmboxq = pmboxq; | ||
3950 | dd_data->context_un.mbox.mb = (MAILBOX_t *)pbuf; | ||
3951 | dd_data->context_un.mbox.set_job = job; | ||
3952 | job->dd_data = dd_data; | ||
3953 | |||
3954 | /* state change */ | ||
3955 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT; | ||
3956 | |||
3957 | rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); | ||
3958 | if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) { | ||
3959 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3960 | "2969 Issued SLI_CONFIG ext-buffer " | ||
3961 | "maibox command, rc:x%x\n", rc); | ||
3962 | return 1; | ||
3963 | } | ||
3964 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
3965 | "2970 Failed to issue SLI_CONFIG ext-buffer " | ||
3966 | "maibox command, rc:x%x\n", rc); | ||
3967 | rc = -EPIPE; | ||
3968 | goto job_error; | ||
3969 | } | ||
3970 | |||
3971 | /* wait for additoinal external buffers */ | ||
3972 | job->reply->result = 0; | ||
3973 | job->job_done(job); | ||
3974 | return SLI_CONFIG_HANDLED; | ||
3975 | |||
3976 | job_error: | ||
3977 | lpfc_bsg_dma_page_free(phba, dmabuf); | ||
3978 | kfree(dd_data); | ||
3979 | |||
3980 | return rc; | ||
3981 | } | ||
3982 | |||
3983 | /** | ||
3984 | * lpfc_bsg_handle_sli_cfg_ebuf - handle ext buffer with sli-cfg mailbox cmd | ||
3985 | * @phba: Pointer to HBA context object. | ||
3986 | * @mb: Pointer to a BSG mailbox object. | ||
3987 | * @dmabuff: Pointer to a DMA buffer descriptor. | ||
3988 | * | ||
3989 | * This routine handles the external buffer with SLI_CONFIG (0x9B) mailbox | ||
3990 | * command with multiple non-embedded external buffers. | ||
3991 | **/ | ||
3992 | static int | ||
3993 | lpfc_bsg_handle_sli_cfg_ebuf(struct lpfc_hba *phba, struct fc_bsg_job *job, | ||
3994 | struct lpfc_dmabuf *dmabuf) | ||
3995 | { | ||
3996 | int rc; | ||
3997 | |||
3998 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
3999 | "2971 SLI_CONFIG buffer (type:x%x)\n", | ||
4000 | phba->mbox_ext_buf_ctx.mboxType); | ||
4001 | |||
4002 | if (phba->mbox_ext_buf_ctx.mboxType == mbox_rd) { | ||
4003 | if (phba->mbox_ext_buf_ctx.state != LPFC_BSG_MBOX_DONE) { | ||
4004 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
4005 | "2972 SLI_CONFIG rd buffer state " | ||
4006 | "mismatch:x%x\n", | ||
4007 | phba->mbox_ext_buf_ctx.state); | ||
4008 | lpfc_bsg_mbox_ext_abort(phba); | ||
4009 | return -EPIPE; | ||
4010 | } | ||
4011 | rc = lpfc_bsg_read_ebuf_get(phba, job); | ||
4012 | if (rc == SLI_CONFIG_HANDLED) | ||
4013 | lpfc_bsg_dma_page_free(phba, dmabuf); | ||
4014 | } else { /* phba->mbox_ext_buf_ctx.mboxType == mbox_wr */ | ||
4015 | if (phba->mbox_ext_buf_ctx.state != LPFC_BSG_MBOX_HOST) { | ||
4016 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
4017 | "2973 SLI_CONFIG wr buffer state " | ||
4018 | "mismatch:x%x\n", | ||
4019 | phba->mbox_ext_buf_ctx.state); | ||
4020 | lpfc_bsg_mbox_ext_abort(phba); | ||
4021 | return -EPIPE; | ||
4022 | } | ||
4023 | rc = lpfc_bsg_write_ebuf_set(phba, job, dmabuf); | ||
4024 | } | ||
4025 | return rc; | ||
4026 | } | ||
4027 | |||
4028 | /** | ||
4029 | * lpfc_bsg_handle_sli_cfg_ext - handle sli-cfg mailbox with external buffer | ||
4030 | * @phba: Pointer to HBA context object. | ||
4031 | * @mb: Pointer to a BSG mailbox object. | ||
4032 | * @dmabuff: Pointer to a DMA buffer descriptor. | ||
4033 | * | ||
4034 | * This routine checkes and handles non-embedded multi-buffer SLI_CONFIG | ||
4035 | * (0x9B) mailbox commands and external buffers. | ||
4036 | **/ | ||
4037 | static int | ||
4038 | lpfc_bsg_handle_sli_cfg_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, | ||
4039 | struct lpfc_dmabuf *dmabuf) | ||
4040 | { | ||
4041 | struct dfc_mbox_req *mbox_req; | ||
4042 | int rc; | ||
4043 | |||
4044 | mbox_req = | ||
4045 | (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd; | ||
4046 | |||
4047 | /* mbox command with/without single external buffer */ | ||
4048 | if (mbox_req->extMboxTag == 0 && mbox_req->extSeqNum == 0) | ||
4049 | return SLI_CONFIG_NOT_HANDLED; | ||
4050 | |||
4051 | /* mbox command and first external buffer */ | ||
4052 | if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_IDLE) { | ||
4053 | if (mbox_req->extSeqNum == 1) { | ||
4054 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
4055 | "2974 SLI_CONFIG mailbox: tag:%d, " | ||
4056 | "seq:%d\n", mbox_req->extMboxTag, | ||
4057 | mbox_req->extSeqNum); | ||
4058 | rc = lpfc_bsg_handle_sli_cfg_mbox(phba, job, dmabuf); | ||
4059 | return rc; | ||
4060 | } else | ||
4061 | goto sli_cfg_ext_error; | ||
4062 | } | ||
4063 | |||
4064 | /* | ||
4065 | * handle additional external buffers | ||
4066 | */ | ||
4067 | |||
4068 | /* check broken pipe conditions */ | ||
4069 | if (mbox_req->extMboxTag != phba->mbox_ext_buf_ctx.mbxTag) | ||
4070 | goto sli_cfg_ext_error; | ||
4071 | if (mbox_req->extSeqNum > phba->mbox_ext_buf_ctx.numBuf) | ||
4072 | goto sli_cfg_ext_error; | ||
4073 | if (mbox_req->extSeqNum != phba->mbox_ext_buf_ctx.seqNum + 1) | ||
4074 | goto sli_cfg_ext_error; | ||
4075 | |||
4076 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
4077 | "2975 SLI_CONFIG mailbox external buffer: " | ||
4078 | "extSta:x%x, tag:%d, seq:%d\n", | ||
4079 | phba->mbox_ext_buf_ctx.state, mbox_req->extMboxTag, | ||
4080 | mbox_req->extSeqNum); | ||
4081 | rc = lpfc_bsg_handle_sli_cfg_ebuf(phba, job, dmabuf); | ||
4082 | return rc; | ||
4083 | |||
4084 | sli_cfg_ext_error: | ||
4085 | /* all other cases, broken pipe */ | ||
4086 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
4087 | "2976 SLI_CONFIG mailbox broken pipe: " | ||
4088 | "ctxSta:x%x, ctxNumBuf:%d " | ||
4089 | "ctxTag:%d, ctxSeq:%d, tag:%d, seq:%d\n", | ||
4090 | phba->mbox_ext_buf_ctx.state, | ||
4091 | phba->mbox_ext_buf_ctx.numBuf, | ||
4092 | phba->mbox_ext_buf_ctx.mbxTag, | ||
4093 | phba->mbox_ext_buf_ctx.seqNum, | ||
4094 | mbox_req->extMboxTag, mbox_req->extSeqNum); | ||
4095 | |||
4096 | lpfc_bsg_mbox_ext_session_reset(phba); | ||
4097 | |||
4098 | return -EPIPE; | ||
4099 | } | ||
4100 | |||
4101 | /** | ||
2622 | * lpfc_bsg_issue_mbox - issues a mailbox command on behalf of an app | 4102 | * lpfc_bsg_issue_mbox - issues a mailbox command on behalf of an app |
2623 | * @phba: Pointer to HBA context object. | 4103 | * @phba: Pointer to HBA context object. |
2624 | * @mb: Pointer to a mailbox object. | 4104 | * @mb: Pointer to a mailbox object. |
@@ -2638,22 +4118,21 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2638 | LPFC_MBOXQ_t *pmboxq = NULL; /* internal mailbox queue */ | 4118 | LPFC_MBOXQ_t *pmboxq = NULL; /* internal mailbox queue */ |
2639 | MAILBOX_t *pmb; /* shortcut to the pmboxq mailbox */ | 4119 | MAILBOX_t *pmb; /* shortcut to the pmboxq mailbox */ |
2640 | /* a 4k buffer to hold the mb and extended data from/to the bsg */ | 4120 | /* a 4k buffer to hold the mb and extended data from/to the bsg */ |
2641 | MAILBOX_t *mb = NULL; | 4121 | uint8_t *pmbx = NULL; |
2642 | struct bsg_job_data *dd_data = NULL; /* bsg data tracking structure */ | 4122 | struct bsg_job_data *dd_data = NULL; /* bsg data tracking structure */ |
2643 | uint32_t size; | 4123 | struct lpfc_dmabuf *dmabuf = NULL; |
2644 | struct lpfc_dmabuf *rxbmp = NULL; /* for biu diag */ | 4124 | struct dfc_mbox_req *mbox_req; |
2645 | struct lpfc_dmabufext *dmp = NULL; /* for biu diag */ | ||
2646 | struct ulp_bde64 *rxbpl = NULL; | ||
2647 | struct dfc_mbox_req *mbox_req = (struct dfc_mbox_req *) | ||
2648 | job->request->rqst_data.h_vendor.vendor_cmd; | ||
2649 | struct READ_EVENT_LOG_VAR *rdEventLog; | 4125 | struct READ_EVENT_LOG_VAR *rdEventLog; |
2650 | uint32_t transmit_length, receive_length, mode; | 4126 | uint32_t transmit_length, receive_length, mode; |
4127 | struct lpfc_mbx_sli4_config *sli4_config; | ||
2651 | struct lpfc_mbx_nembed_cmd *nembed_sge; | 4128 | struct lpfc_mbx_nembed_cmd *nembed_sge; |
2652 | struct mbox_header *header; | 4129 | struct mbox_header *header; |
2653 | struct ulp_bde64 *bde; | 4130 | struct ulp_bde64 *bde; |
2654 | uint8_t *ext = NULL; | 4131 | uint8_t *ext = NULL; |
2655 | int rc = 0; | 4132 | int rc = 0; |
2656 | uint8_t *from; | 4133 | uint8_t *from; |
4134 | uint32_t size; | ||
4135 | |||
2657 | 4136 | ||
2658 | /* in case no data is transferred */ | 4137 | /* in case no data is transferred */ |
2659 | job->reply->reply_payload_rcv_len = 0; | 4138 | job->reply->reply_payload_rcv_len = 0; |
@@ -2665,6 +4144,18 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2665 | goto job_done; | 4144 | goto job_done; |
2666 | } | 4145 | } |
2667 | 4146 | ||
4147 | /* | ||
4148 | * Don't allow mailbox commands to be sent when blocked or when in | ||
4149 | * the middle of discovery | ||
4150 | */ | ||
4151 | if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) { | ||
4152 | rc = -EAGAIN; | ||
4153 | goto job_done; | ||
4154 | } | ||
4155 | |||
4156 | mbox_req = | ||
4157 | (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd; | ||
4158 | |||
2668 | /* check if requested extended data lengths are valid */ | 4159 | /* check if requested extended data lengths are valid */ |
2669 | if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) || | 4160 | if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) || |
2670 | (mbox_req->outExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t))) { | 4161 | (mbox_req->outExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t))) { |
@@ -2672,6 +4163,32 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2672 | goto job_done; | 4163 | goto job_done; |
2673 | } | 4164 | } |
2674 | 4165 | ||
4166 | dmabuf = lpfc_bsg_dma_page_alloc(phba); | ||
4167 | if (!dmabuf || !dmabuf->virt) { | ||
4168 | rc = -ENOMEM; | ||
4169 | goto job_done; | ||
4170 | } | ||
4171 | |||
4172 | /* Get the mailbox command or external buffer from BSG */ | ||
4173 | pmbx = (uint8_t *)dmabuf->virt; | ||
4174 | size = job->request_payload.payload_len; | ||
4175 | sg_copy_to_buffer(job->request_payload.sg_list, | ||
4176 | job->request_payload.sg_cnt, pmbx, size); | ||
4177 | |||
4178 | /* Handle possible SLI_CONFIG with non-embedded payloads */ | ||
4179 | if (phba->sli_rev == LPFC_SLI_REV4) { | ||
4180 | rc = lpfc_bsg_handle_sli_cfg_ext(phba, job, dmabuf); | ||
4181 | if (rc == SLI_CONFIG_HANDLED) | ||
4182 | goto job_cont; | ||
4183 | if (rc) | ||
4184 | goto job_done; | ||
4185 | /* SLI_CONFIG_NOT_HANDLED for other mailbox commands */ | ||
4186 | } | ||
4187 | |||
4188 | rc = lpfc_bsg_check_cmd_access(phba, (MAILBOX_t *)pmbx, vport); | ||
4189 | if (rc != 0) | ||
4190 | goto job_done; /* must be negative */ | ||
4191 | |||
2675 | /* allocate our bsg tracking structure */ | 4192 | /* allocate our bsg tracking structure */ |
2676 | dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); | 4193 | dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); |
2677 | if (!dd_data) { | 4194 | if (!dd_data) { |
@@ -2681,12 +4198,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2681 | goto job_done; | 4198 | goto job_done; |
2682 | } | 4199 | } |
2683 | 4200 | ||
2684 | mb = kzalloc(BSG_MBOX_SIZE, GFP_KERNEL); | ||
2685 | if (!mb) { | ||
2686 | rc = -ENOMEM; | ||
2687 | goto job_done; | ||
2688 | } | ||
2689 | |||
2690 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 4201 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
2691 | if (!pmboxq) { | 4202 | if (!pmboxq) { |
2692 | rc = -ENOMEM; | 4203 | rc = -ENOMEM; |
@@ -2694,17 +4205,8 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2694 | } | 4205 | } |
2695 | memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); | 4206 | memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); |
2696 | 4207 | ||
2697 | size = job->request_payload.payload_len; | ||
2698 | sg_copy_to_buffer(job->request_payload.sg_list, | ||
2699 | job->request_payload.sg_cnt, | ||
2700 | mb, size); | ||
2701 | |||
2702 | rc = lpfc_bsg_check_cmd_access(phba, mb, vport); | ||
2703 | if (rc != 0) | ||
2704 | goto job_done; /* must be negative */ | ||
2705 | |||
2706 | pmb = &pmboxq->u.mb; | 4208 | pmb = &pmboxq->u.mb; |
2707 | memcpy(pmb, mb, sizeof(*pmb)); | 4209 | memcpy(pmb, pmbx, sizeof(*pmb)); |
2708 | pmb->mbxOwner = OWN_HOST; | 4210 | pmb->mbxOwner = OWN_HOST; |
2709 | pmboxq->vport = vport; | 4211 | pmboxq->vport = vport; |
2710 | 4212 | ||
@@ -2721,30 +4223,13 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2721 | "0x%x while in stopped state.\n", | 4223 | "0x%x while in stopped state.\n", |
2722 | pmb->mbxCommand); | 4224 | pmb->mbxCommand); |
2723 | 4225 | ||
2724 | /* Don't allow mailbox commands to be sent when blocked | ||
2725 | * or when in the middle of discovery | ||
2726 | */ | ||
2727 | if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) { | ||
2728 | rc = -EAGAIN; | ||
2729 | goto job_done; | ||
2730 | } | ||
2731 | |||
2732 | /* extended mailbox commands will need an extended buffer */ | 4226 | /* extended mailbox commands will need an extended buffer */ |
2733 | if (mbox_req->inExtWLen || mbox_req->outExtWLen) { | 4227 | if (mbox_req->inExtWLen || mbox_req->outExtWLen) { |
2734 | ext = kzalloc(MAILBOX_EXT_SIZE, GFP_KERNEL); | ||
2735 | if (!ext) { | ||
2736 | rc = -ENOMEM; | ||
2737 | goto job_done; | ||
2738 | } | ||
2739 | |||
2740 | /* any data for the device? */ | 4228 | /* any data for the device? */ |
2741 | if (mbox_req->inExtWLen) { | 4229 | if (mbox_req->inExtWLen) { |
2742 | from = (uint8_t *)mb; | 4230 | from = pmbx; |
2743 | from += sizeof(MAILBOX_t); | 4231 | ext = from + sizeof(MAILBOX_t); |
2744 | memcpy((uint8_t *)ext, from, | ||
2745 | mbox_req->inExtWLen * sizeof(uint32_t)); | ||
2746 | } | 4232 | } |
2747 | |||
2748 | pmboxq->context2 = ext; | 4233 | pmboxq->context2 = ext; |
2749 | pmboxq->in_ext_byte_len = | 4234 | pmboxq->in_ext_byte_len = |
2750 | mbox_req->inExtWLen * sizeof(uint32_t); | 4235 | mbox_req->inExtWLen * sizeof(uint32_t); |
@@ -2768,46 +4253,17 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2768 | rc = -ERANGE; | 4253 | rc = -ERANGE; |
2769 | goto job_done; | 4254 | goto job_done; |
2770 | } | 4255 | } |
2771 | |||
2772 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | ||
2773 | if (!rxbmp) { | ||
2774 | rc = -ENOMEM; | ||
2775 | goto job_done; | ||
2776 | } | ||
2777 | |||
2778 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
2779 | if (!rxbmp->virt) { | ||
2780 | rc = -ENOMEM; | ||
2781 | goto job_done; | ||
2782 | } | ||
2783 | |||
2784 | INIT_LIST_HEAD(&rxbmp->list); | ||
2785 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | ||
2786 | dmp = diag_cmd_data_alloc(phba, rxbpl, transmit_length, 0); | ||
2787 | if (!dmp) { | ||
2788 | rc = -ENOMEM; | ||
2789 | goto job_done; | ||
2790 | } | ||
2791 | |||
2792 | INIT_LIST_HEAD(&dmp->dma.list); | ||
2793 | pmb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh = | 4256 | pmb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh = |
2794 | putPaddrHigh(dmp->dma.phys); | 4257 | putPaddrHigh(dmabuf->phys + sizeof(MAILBOX_t)); |
2795 | pmb->un.varBIUdiag.un.s2.xmit_bde64.addrLow = | 4258 | pmb->un.varBIUdiag.un.s2.xmit_bde64.addrLow = |
2796 | putPaddrLow(dmp->dma.phys); | 4259 | putPaddrLow(dmabuf->phys + sizeof(MAILBOX_t)); |
2797 | 4260 | ||
2798 | pmb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh = | 4261 | pmb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh = |
2799 | putPaddrHigh(dmp->dma.phys + | 4262 | putPaddrHigh(dmabuf->phys + sizeof(MAILBOX_t) |
2800 | pmb->un.varBIUdiag.un.s2. | 4263 | + pmb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize); |
2801 | xmit_bde64.tus.f.bdeSize); | ||
2802 | pmb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = | 4264 | pmb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = |
2803 | putPaddrLow(dmp->dma.phys + | 4265 | putPaddrLow(dmabuf->phys + sizeof(MAILBOX_t) |
2804 | pmb->un.varBIUdiag.un.s2. | 4266 | + pmb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize); |
2805 | xmit_bde64.tus.f.bdeSize); | ||
2806 | |||
2807 | /* copy the transmit data found in the mailbox extension area */ | ||
2808 | from = (uint8_t *)mb; | ||
2809 | from += sizeof(MAILBOX_t); | ||
2810 | memcpy((uint8_t *)dmp->dma.virt, from, transmit_length); | ||
2811 | } else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) { | 4267 | } else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) { |
2812 | rdEventLog = &pmb->un.varRdEventLog; | 4268 | rdEventLog = &pmb->un.varRdEventLog; |
2813 | receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize; | 4269 | receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize; |
@@ -2823,33 +4279,10 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2823 | 4279 | ||
2824 | /* mode zero uses a bde like biu diags command */ | 4280 | /* mode zero uses a bde like biu diags command */ |
2825 | if (mode == 0) { | 4281 | if (mode == 0) { |
2826 | 4282 | pmb->un.varWords[3] = putPaddrLow(dmabuf->phys | |
2827 | /* rebuild the command for sli4 using our own buffers | 4283 | + sizeof(MAILBOX_t)); |
2828 | * like we do for biu diags | 4284 | pmb->un.varWords[4] = putPaddrHigh(dmabuf->phys |
2829 | */ | 4285 | + sizeof(MAILBOX_t)); |
2830 | |||
2831 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | ||
2832 | if (!rxbmp) { | ||
2833 | rc = -ENOMEM; | ||
2834 | goto job_done; | ||
2835 | } | ||
2836 | |||
2837 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
2838 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | ||
2839 | if (rxbpl) { | ||
2840 | INIT_LIST_HEAD(&rxbmp->list); | ||
2841 | dmp = diag_cmd_data_alloc(phba, rxbpl, | ||
2842 | receive_length, 0); | ||
2843 | } | ||
2844 | |||
2845 | if (!dmp) { | ||
2846 | rc = -ENOMEM; | ||
2847 | goto job_done; | ||
2848 | } | ||
2849 | |||
2850 | INIT_LIST_HEAD(&dmp->dma.list); | ||
2851 | pmb->un.varWords[3] = putPaddrLow(dmp->dma.phys); | ||
2852 | pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys); | ||
2853 | } | 4286 | } |
2854 | } else if (phba->sli_rev == LPFC_SLI_REV4) { | 4287 | } else if (phba->sli_rev == LPFC_SLI_REV4) { |
2855 | if (pmb->mbxCommand == MBX_DUMP_MEMORY) { | 4288 | if (pmb->mbxCommand == MBX_DUMP_MEMORY) { |
@@ -2860,36 +4293,14 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2860 | /* receive length cannot be greater than mailbox | 4293 | /* receive length cannot be greater than mailbox |
2861 | * extension size | 4294 | * extension size |
2862 | */ | 4295 | */ |
2863 | if ((receive_length == 0) || | 4296 | if (receive_length == 0) { |
2864 | (receive_length > MAILBOX_EXT_SIZE)) { | ||
2865 | rc = -ERANGE; | 4297 | rc = -ERANGE; |
2866 | goto job_done; | 4298 | goto job_done; |
2867 | } | 4299 | } |
2868 | 4300 | pmb->un.varWords[3] = putPaddrLow(dmabuf->phys | |
2869 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 4301 | + sizeof(MAILBOX_t)); |
2870 | if (!rxbmp) { | 4302 | pmb->un.varWords[4] = putPaddrHigh(dmabuf->phys |
2871 | rc = -ENOMEM; | 4303 | + sizeof(MAILBOX_t)); |
2872 | goto job_done; | ||
2873 | } | ||
2874 | |||
2875 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
2876 | if (!rxbmp->virt) { | ||
2877 | rc = -ENOMEM; | ||
2878 | goto job_done; | ||
2879 | } | ||
2880 | |||
2881 | INIT_LIST_HEAD(&rxbmp->list); | ||
2882 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | ||
2883 | dmp = diag_cmd_data_alloc(phba, rxbpl, receive_length, | ||
2884 | 0); | ||
2885 | if (!dmp) { | ||
2886 | rc = -ENOMEM; | ||
2887 | goto job_done; | ||
2888 | } | ||
2889 | |||
2890 | INIT_LIST_HEAD(&dmp->dma.list); | ||
2891 | pmb->un.varWords[3] = putPaddrLow(dmp->dma.phys); | ||
2892 | pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys); | ||
2893 | } else if ((pmb->mbxCommand == MBX_UPDATE_CFG) && | 4304 | } else if ((pmb->mbxCommand == MBX_UPDATE_CFG) && |
2894 | pmb->un.varUpdateCfg.co) { | 4305 | pmb->un.varUpdateCfg.co) { |
2895 | bde = (struct ulp_bde64 *)&pmb->un.varWords[4]; | 4306 | bde = (struct ulp_bde64 *)&pmb->un.varWords[4]; |
@@ -2899,102 +4310,53 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2899 | rc = -ERANGE; | 4310 | rc = -ERANGE; |
2900 | goto job_done; | 4311 | goto job_done; |
2901 | } | 4312 | } |
2902 | 4313 | bde->addrHigh = putPaddrHigh(dmabuf->phys | |
2903 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 4314 | + sizeof(MAILBOX_t)); |
2904 | if (!rxbmp) { | 4315 | bde->addrLow = putPaddrLow(dmabuf->phys |
2905 | rc = -ENOMEM; | 4316 | + sizeof(MAILBOX_t)); |
2906 | goto job_done; | ||
2907 | } | ||
2908 | |||
2909 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
2910 | if (!rxbmp->virt) { | ||
2911 | rc = -ENOMEM; | ||
2912 | goto job_done; | ||
2913 | } | ||
2914 | |||
2915 | INIT_LIST_HEAD(&rxbmp->list); | ||
2916 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | ||
2917 | dmp = diag_cmd_data_alloc(phba, rxbpl, | ||
2918 | bde->tus.f.bdeSize, 0); | ||
2919 | if (!dmp) { | ||
2920 | rc = -ENOMEM; | ||
2921 | goto job_done; | ||
2922 | } | ||
2923 | |||
2924 | INIT_LIST_HEAD(&dmp->dma.list); | ||
2925 | bde->addrHigh = putPaddrHigh(dmp->dma.phys); | ||
2926 | bde->addrLow = putPaddrLow(dmp->dma.phys); | ||
2927 | |||
2928 | /* copy the transmit data found in the mailbox | ||
2929 | * extension area | ||
2930 | */ | ||
2931 | from = (uint8_t *)mb; | ||
2932 | from += sizeof(MAILBOX_t); | ||
2933 | memcpy((uint8_t *)dmp->dma.virt, from, | ||
2934 | bde->tus.f.bdeSize); | ||
2935 | } else if (pmb->mbxCommand == MBX_SLI4_CONFIG) { | 4317 | } else if (pmb->mbxCommand == MBX_SLI4_CONFIG) { |
2936 | /* rebuild the command for sli4 using our own buffers | 4318 | /* Handling non-embedded SLI_CONFIG mailbox command */ |
2937 | * like we do for biu diags | 4319 | sli4_config = &pmboxq->u.mqe.un.sli4_config; |
2938 | */ | 4320 | if (!bf_get(lpfc_mbox_hdr_emb, |
2939 | header = (struct mbox_header *)&pmb->un.varWords[0]; | 4321 | &sli4_config->header.cfg_mhdr)) { |
2940 | nembed_sge = (struct lpfc_mbx_nembed_cmd *) | 4322 | /* rebuild the command for sli4 using our |
2941 | &pmb->un.varWords[0]; | 4323 | * own buffers like we do for biu diags |
2942 | receive_length = nembed_sge->sge[0].length; | 4324 | */ |
2943 | 4325 | header = (struct mbox_header *) | |
2944 | /* receive length cannot be greater than mailbox | 4326 | &pmb->un.varWords[0]; |
2945 | * extension size | 4327 | nembed_sge = (struct lpfc_mbx_nembed_cmd *) |
2946 | */ | 4328 | &pmb->un.varWords[0]; |
2947 | if ((receive_length == 0) || | 4329 | receive_length = nembed_sge->sge[0].length; |
2948 | (receive_length > MAILBOX_EXT_SIZE)) { | 4330 | |
2949 | rc = -ERANGE; | 4331 | /* receive length cannot be greater than |
2950 | goto job_done; | 4332 | * mailbox extension size |
2951 | } | 4333 | */ |
2952 | 4334 | if ((receive_length == 0) || | |
2953 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 4335 | (receive_length > MAILBOX_EXT_SIZE)) { |
2954 | if (!rxbmp) { | 4336 | rc = -ERANGE; |
2955 | rc = -ENOMEM; | 4337 | goto job_done; |
2956 | goto job_done; | 4338 | } |
2957 | } | ||
2958 | |||
2959 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
2960 | if (!rxbmp->virt) { | ||
2961 | rc = -ENOMEM; | ||
2962 | goto job_done; | ||
2963 | } | ||
2964 | 4339 | ||
2965 | INIT_LIST_HEAD(&rxbmp->list); | 4340 | nembed_sge->sge[0].pa_hi = |
2966 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | 4341 | putPaddrHigh(dmabuf->phys |
2967 | dmp = diag_cmd_data_alloc(phba, rxbpl, receive_length, | 4342 | + sizeof(MAILBOX_t)); |
2968 | 0); | 4343 | nembed_sge->sge[0].pa_lo = |
2969 | if (!dmp) { | 4344 | putPaddrLow(dmabuf->phys |
2970 | rc = -ENOMEM; | 4345 | + sizeof(MAILBOX_t)); |
2971 | goto job_done; | ||
2972 | } | 4346 | } |
2973 | |||
2974 | INIT_LIST_HEAD(&dmp->dma.list); | ||
2975 | nembed_sge->sge[0].pa_hi = putPaddrHigh(dmp->dma.phys); | ||
2976 | nembed_sge->sge[0].pa_lo = putPaddrLow(dmp->dma.phys); | ||
2977 | /* copy the transmit data found in the mailbox | ||
2978 | * extension area | ||
2979 | */ | ||
2980 | from = (uint8_t *)mb; | ||
2981 | from += sizeof(MAILBOX_t); | ||
2982 | memcpy((uint8_t *)dmp->dma.virt, from, | ||
2983 | header->cfg_mhdr.payload_length); | ||
2984 | } | 4347 | } |
2985 | } | 4348 | } |
2986 | 4349 | ||
2987 | dd_data->context_un.mbox.rxbmp = rxbmp; | 4350 | dd_data->context_un.mbox.dmabuffers = dmabuf; |
2988 | dd_data->context_un.mbox.dmp = dmp; | ||
2989 | 4351 | ||
2990 | /* setup wake call as IOCB callback */ | 4352 | /* setup wake call as IOCB callback */ |
2991 | pmboxq->mbox_cmpl = lpfc_bsg_wake_mbox_wait; | 4353 | pmboxq->mbox_cmpl = lpfc_bsg_issue_mbox_cmpl; |
2992 | 4354 | ||
2993 | /* setup context field to pass wait_queue pointer to wake function */ | 4355 | /* setup context field to pass wait_queue pointer to wake function */ |
2994 | pmboxq->context1 = dd_data; | 4356 | pmboxq->context1 = dd_data; |
2995 | dd_data->type = TYPE_MBOX; | 4357 | dd_data->type = TYPE_MBOX; |
2996 | dd_data->context_un.mbox.pmboxq = pmboxq; | 4358 | dd_data->context_un.mbox.pmboxq = pmboxq; |
2997 | dd_data->context_un.mbox.mb = mb; | 4359 | dd_data->context_un.mbox.mb = (MAILBOX_t *)pmbx; |
2998 | dd_data->context_un.mbox.set_job = job; | 4360 | dd_data->context_un.mbox.set_job = job; |
2999 | dd_data->context_un.mbox.ext = ext; | 4361 | dd_data->context_un.mbox.ext = ext; |
3000 | dd_data->context_un.mbox.mbOffset = mbox_req->mbOffset; | 4362 | dd_data->context_un.mbox.mbOffset = mbox_req->mbOffset; |
@@ -3011,11 +4373,11 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
3011 | } | 4373 | } |
3012 | 4374 | ||
3013 | /* job finished, copy the data */ | 4375 | /* job finished, copy the data */ |
3014 | memcpy(mb, pmb, sizeof(*pmb)); | 4376 | memcpy(pmbx, pmb, sizeof(*pmb)); |
3015 | job->reply->reply_payload_rcv_len = | 4377 | job->reply->reply_payload_rcv_len = |
3016 | sg_copy_from_buffer(job->reply_payload.sg_list, | 4378 | sg_copy_from_buffer(job->reply_payload.sg_list, |
3017 | job->reply_payload.sg_cnt, | 4379 | job->reply_payload.sg_cnt, |
3018 | mb, size); | 4380 | pmbx, size); |
3019 | /* not waiting mbox already done */ | 4381 | /* not waiting mbox already done */ |
3020 | rc = 0; | 4382 | rc = 0; |
3021 | goto job_done; | 4383 | goto job_done; |
@@ -3027,22 +4389,12 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
3027 | 4389 | ||
3028 | job_done: | 4390 | job_done: |
3029 | /* common exit for error or job completed inline */ | 4391 | /* common exit for error or job completed inline */ |
3030 | kfree(mb); | ||
3031 | if (pmboxq) | 4392 | if (pmboxq) |
3032 | mempool_free(pmboxq, phba->mbox_mem_pool); | 4393 | mempool_free(pmboxq, phba->mbox_mem_pool); |
3033 | kfree(ext); | 4394 | lpfc_bsg_dma_page_free(phba, dmabuf); |
3034 | if (dmp) { | ||
3035 | dma_free_coherent(&phba->pcidev->dev, | ||
3036 | dmp->size, dmp->dma.virt, | ||
3037 | dmp->dma.phys); | ||
3038 | kfree(dmp); | ||
3039 | } | ||
3040 | if (rxbmp) { | ||
3041 | lpfc_mbuf_free(phba, rxbmp->virt, rxbmp->phys); | ||
3042 | kfree(rxbmp); | ||
3043 | } | ||
3044 | kfree(dd_data); | 4395 | kfree(dd_data); |
3045 | 4396 | ||
4397 | job_cont: | ||
3046 | return rc; | 4398 | return rc; |
3047 | } | 4399 | } |
3048 | 4400 | ||
@@ -3055,37 +4407,28 @@ lpfc_bsg_mbox_cmd(struct fc_bsg_job *job) | |||
3055 | { | 4407 | { |
3056 | struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; | 4408 | struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; |
3057 | struct lpfc_hba *phba = vport->phba; | 4409 | struct lpfc_hba *phba = vport->phba; |
4410 | struct dfc_mbox_req *mbox_req; | ||
3058 | int rc = 0; | 4411 | int rc = 0; |
3059 | 4412 | ||
3060 | /* in case no data is transferred */ | 4413 | /* mix-and-match backward compatibility */ |
3061 | job->reply->reply_payload_rcv_len = 0; | 4414 | job->reply->reply_payload_rcv_len = 0; |
3062 | if (job->request_len < | 4415 | if (job->request_len < |
3063 | sizeof(struct fc_bsg_request) + sizeof(struct dfc_mbox_req)) { | 4416 | sizeof(struct fc_bsg_request) + sizeof(struct dfc_mbox_req)) { |
3064 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | 4417 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, |
3065 | "2737 Received MBOX_REQ request below " | 4418 | "2737 Mix-and-match backward compability " |
3066 | "minimum size\n"); | 4419 | "between MBOX_REQ old size:%d and " |
3067 | rc = -EINVAL; | 4420 | "new request size:%d\n", |
3068 | goto job_error; | 4421 | (int)(job->request_len - |
3069 | } | 4422 | sizeof(struct fc_bsg_request)), |
3070 | 4423 | (int)sizeof(struct dfc_mbox_req)); | |
3071 | if (job->request_payload.payload_len != BSG_MBOX_SIZE) { | 4424 | mbox_req = (struct dfc_mbox_req *) |
3072 | rc = -EINVAL; | 4425 | job->request->rqst_data.h_vendor.vendor_cmd; |
3073 | goto job_error; | 4426 | mbox_req->extMboxTag = 0; |
3074 | } | 4427 | mbox_req->extSeqNum = 0; |
3075 | |||
3076 | if (job->reply_payload.payload_len != BSG_MBOX_SIZE) { | ||
3077 | rc = -EINVAL; | ||
3078 | goto job_error; | ||
3079 | } | ||
3080 | |||
3081 | if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) { | ||
3082 | rc = -EAGAIN; | ||
3083 | goto job_error; | ||
3084 | } | 4428 | } |
3085 | 4429 | ||
3086 | rc = lpfc_bsg_issue_mbox(phba, job, vport); | 4430 | rc = lpfc_bsg_issue_mbox(phba, job, vport); |
3087 | 4431 | ||
3088 | job_error: | ||
3089 | if (rc == 0) { | 4432 | if (rc == 0) { |
3090 | /* job done */ | 4433 | /* job done */ |
3091 | job->reply->result = 0; | 4434 | job->reply->result = 0; |
@@ -3416,10 +4759,16 @@ lpfc_bsg_hst_vendor(struct fc_bsg_job *job) | |||
3416 | rc = lpfc_bsg_send_mgmt_rsp(job); | 4759 | rc = lpfc_bsg_send_mgmt_rsp(job); |
3417 | break; | 4760 | break; |
3418 | case LPFC_BSG_VENDOR_DIAG_MODE: | 4761 | case LPFC_BSG_VENDOR_DIAG_MODE: |
3419 | rc = lpfc_bsg_diag_mode(job); | 4762 | rc = lpfc_bsg_diag_loopback_mode(job); |
4763 | break; | ||
4764 | case LPFC_BSG_VENDOR_DIAG_MODE_END: | ||
4765 | rc = lpfc_sli4_bsg_diag_mode_end(job); | ||
4766 | break; | ||
4767 | case LPFC_BSG_VENDOR_DIAG_RUN_LOOPBACK: | ||
4768 | rc = lpfc_bsg_diag_loopback_run(job); | ||
3420 | break; | 4769 | break; |
3421 | case LPFC_BSG_VENDOR_DIAG_TEST: | 4770 | case LPFC_BSG_VENDOR_LINK_DIAG_TEST: |
3422 | rc = lpfc_bsg_diag_test(job); | 4771 | rc = lpfc_sli4_bsg_link_diag_test(job); |
3423 | break; | 4772 | break; |
3424 | case LPFC_BSG_VENDOR_GET_MGMT_REV: | 4773 | case LPFC_BSG_VENDOR_GET_MGMT_REV: |
3425 | rc = lpfc_bsg_get_dfc_rev(job); | 4774 | rc = lpfc_bsg_get_dfc_rev(job); |
@@ -3538,6 +4887,8 @@ lpfc_bsg_timeout(struct fc_bsg_job *job) | |||
3538 | /* the mbox completion handler can now be run */ | 4887 | /* the mbox completion handler can now be run */ |
3539 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 4888 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
3540 | job->job_done(job); | 4889 | job->job_done(job); |
4890 | if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_PORT) | ||
4891 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS; | ||
3541 | break; | 4892 | break; |
3542 | case TYPE_MENLO: | 4893 | case TYPE_MENLO: |
3543 | menlo = &dd_data->context_un.menlo; | 4894 | menlo = &dd_data->context_un.menlo; |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h index b542aca6f5ae..c8c2b47ea886 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.h +++ b/drivers/scsi/lpfc/lpfc_bsg.h | |||
@@ -24,15 +24,17 @@ | |||
24 | * These are the vendor unique structures passed in using the bsg | 24 | * These are the vendor unique structures passed in using the bsg |
25 | * FC_BSG_HST_VENDOR message code type. | 25 | * FC_BSG_HST_VENDOR message code type. |
26 | */ | 26 | */ |
27 | #define LPFC_BSG_VENDOR_SET_CT_EVENT 1 | 27 | #define LPFC_BSG_VENDOR_SET_CT_EVENT 1 |
28 | #define LPFC_BSG_VENDOR_GET_CT_EVENT 2 | 28 | #define LPFC_BSG_VENDOR_GET_CT_EVENT 2 |
29 | #define LPFC_BSG_VENDOR_SEND_MGMT_RESP 3 | 29 | #define LPFC_BSG_VENDOR_SEND_MGMT_RESP 3 |
30 | #define LPFC_BSG_VENDOR_DIAG_MODE 4 | 30 | #define LPFC_BSG_VENDOR_DIAG_MODE 4 |
31 | #define LPFC_BSG_VENDOR_DIAG_TEST 5 | 31 | #define LPFC_BSG_VENDOR_DIAG_RUN_LOOPBACK 5 |
32 | #define LPFC_BSG_VENDOR_GET_MGMT_REV 6 | 32 | #define LPFC_BSG_VENDOR_GET_MGMT_REV 6 |
33 | #define LPFC_BSG_VENDOR_MBOX 7 | 33 | #define LPFC_BSG_VENDOR_MBOX 7 |
34 | #define LPFC_BSG_VENDOR_MENLO_CMD 8 | 34 | #define LPFC_BSG_VENDOR_MENLO_CMD 8 |
35 | #define LPFC_BSG_VENDOR_MENLO_DATA 9 | 35 | #define LPFC_BSG_VENDOR_MENLO_DATA 9 |
36 | #define LPFC_BSG_VENDOR_DIAG_MODE_END 10 | ||
37 | #define LPFC_BSG_VENDOR_LINK_DIAG_TEST 11 | ||
36 | 38 | ||
37 | struct set_ct_event { | 39 | struct set_ct_event { |
38 | uint32_t command; | 40 | uint32_t command; |
@@ -67,10 +69,25 @@ struct diag_mode_set { | |||
67 | uint32_t timeout; | 69 | uint32_t timeout; |
68 | }; | 70 | }; |
69 | 71 | ||
72 | struct sli4_link_diag { | ||
73 | uint32_t command; | ||
74 | uint32_t timeout; | ||
75 | uint32_t test_id; | ||
76 | uint32_t loops; | ||
77 | uint32_t test_version; | ||
78 | uint32_t error_action; | ||
79 | }; | ||
80 | |||
70 | struct diag_mode_test { | 81 | struct diag_mode_test { |
71 | uint32_t command; | 82 | uint32_t command; |
72 | }; | 83 | }; |
73 | 84 | ||
85 | struct diag_status { | ||
86 | uint32_t mbox_status; | ||
87 | uint32_t shdr_status; | ||
88 | uint32_t shdr_add_status; | ||
89 | }; | ||
90 | |||
74 | #define LPFC_WWNN_TYPE 0 | 91 | #define LPFC_WWNN_TYPE 0 |
75 | #define LPFC_WWPN_TYPE 1 | 92 | #define LPFC_WWPN_TYPE 1 |
76 | 93 | ||
@@ -92,11 +109,15 @@ struct get_mgmt_rev_reply { | |||
92 | }; | 109 | }; |
93 | 110 | ||
94 | #define BSG_MBOX_SIZE 4096 /* mailbox command plus extended data */ | 111 | #define BSG_MBOX_SIZE 4096 /* mailbox command plus extended data */ |
112 | |||
113 | /* BSG mailbox request header */ | ||
95 | struct dfc_mbox_req { | 114 | struct dfc_mbox_req { |
96 | uint32_t command; | 115 | uint32_t command; |
97 | uint32_t mbOffset; | 116 | uint32_t mbOffset; |
98 | uint32_t inExtWLen; | 117 | uint32_t inExtWLen; |
99 | uint32_t outExtWLen; | 118 | uint32_t outExtWLen; |
119 | uint32_t extMboxTag; | ||
120 | uint32_t extSeqNum; | ||
100 | }; | 121 | }; |
101 | 122 | ||
102 | /* Used for menlo command or menlo data. The xri is only used for menlo data */ | 123 | /* Used for menlo command or menlo data. The xri is only used for menlo data */ |
@@ -171,7 +192,7 @@ struct lpfc_sli_config_mse { | |||
171 | #define lpfc_mbox_sli_config_mse_len_WORD buf_len | 192 | #define lpfc_mbox_sli_config_mse_len_WORD buf_len |
172 | }; | 193 | }; |
173 | 194 | ||
174 | struct lpfc_sli_config_subcmd_hbd { | 195 | struct lpfc_sli_config_hbd { |
175 | uint32_t buf_len; | 196 | uint32_t buf_len; |
176 | #define lpfc_mbox_sli_config_ecmn_hbd_len_SHIFT 0 | 197 | #define lpfc_mbox_sli_config_ecmn_hbd_len_SHIFT 0 |
177 | #define lpfc_mbox_sli_config_ecmn_hbd_len_MASK 0xffffff | 198 | #define lpfc_mbox_sli_config_ecmn_hbd_len_MASK 0xffffff |
@@ -194,21 +215,39 @@ struct lpfc_sli_config_hdr { | |||
194 | uint32_t reserved5; | 215 | uint32_t reserved5; |
195 | }; | 216 | }; |
196 | 217 | ||
197 | struct lpfc_sli_config_generic { | 218 | struct lpfc_sli_config_emb0_subsys { |
198 | struct lpfc_sli_config_hdr sli_config_hdr; | 219 | struct lpfc_sli_config_hdr sli_config_hdr; |
199 | #define LPFC_MBX_SLI_CONFIG_MAX_MSE 19 | 220 | #define LPFC_MBX_SLI_CONFIG_MAX_MSE 19 |
200 | struct lpfc_sli_config_mse mse[LPFC_MBX_SLI_CONFIG_MAX_MSE]; | 221 | struct lpfc_sli_config_mse mse[LPFC_MBX_SLI_CONFIG_MAX_MSE]; |
222 | uint32_t padding; | ||
223 | uint32_t word64; | ||
224 | #define lpfc_emb0_subcmnd_opcode_SHIFT 0 | ||
225 | #define lpfc_emb0_subcmnd_opcode_MASK 0xff | ||
226 | #define lpfc_emb0_subcmnd_opcode_WORD word64 | ||
227 | #define lpfc_emb0_subcmnd_subsys_SHIFT 8 | ||
228 | #define lpfc_emb0_subcmnd_subsys_MASK 0xff | ||
229 | #define lpfc_emb0_subcmnd_subsys_WORD word64 | ||
230 | /* Subsystem FCOE (0x0C) OpCodes */ | ||
231 | #define SLI_CONFIG_SUBSYS_FCOE 0x0C | ||
232 | #define FCOE_OPCODE_READ_FCF 0x08 | ||
233 | #define FCOE_OPCODE_ADD_FCF 0x09 | ||
201 | }; | 234 | }; |
202 | 235 | ||
203 | struct lpfc_sli_config_subcmnd { | 236 | struct lpfc_sli_config_emb1_subsys { |
204 | struct lpfc_sli_config_hdr sli_config_hdr; | 237 | struct lpfc_sli_config_hdr sli_config_hdr; |
205 | uint32_t word6; | 238 | uint32_t word6; |
206 | #define lpfc_subcmnd_opcode_SHIFT 0 | 239 | #define lpfc_emb1_subcmnd_opcode_SHIFT 0 |
207 | #define lpfc_subcmnd_opcode_MASK 0xff | 240 | #define lpfc_emb1_subcmnd_opcode_MASK 0xff |
208 | #define lpfc_subcmnd_opcode_WORD word6 | 241 | #define lpfc_emb1_subcmnd_opcode_WORD word6 |
209 | #define lpfc_subcmnd_subsys_SHIFT 8 | 242 | #define lpfc_emb1_subcmnd_subsys_SHIFT 8 |
210 | #define lpfc_subcmnd_subsys_MASK 0xff | 243 | #define lpfc_emb1_subcmnd_subsys_MASK 0xff |
211 | #define lpfc_subcmnd_subsys_WORD word6 | 244 | #define lpfc_emb1_subcmnd_subsys_WORD word6 |
245 | /* Subsystem COMN (0x01) OpCodes */ | ||
246 | #define SLI_CONFIG_SUBSYS_COMN 0x01 | ||
247 | #define COMN_OPCODE_READ_OBJECT 0xAB | ||
248 | #define COMN_OPCODE_WRITE_OBJECT 0xAC | ||
249 | #define COMN_OPCODE_READ_OBJECT_LIST 0xAD | ||
250 | #define COMN_OPCODE_DELETE_OBJECT 0xAE | ||
212 | uint32_t timeout; | 251 | uint32_t timeout; |
213 | uint32_t request_length; | 252 | uint32_t request_length; |
214 | uint32_t word9; | 253 | uint32_t word9; |
@@ -222,8 +261,8 @@ struct lpfc_sli_config_subcmnd { | |||
222 | uint32_t rd_offset; | 261 | uint32_t rd_offset; |
223 | uint32_t obj_name[26]; | 262 | uint32_t obj_name[26]; |
224 | uint32_t hbd_count; | 263 | uint32_t hbd_count; |
225 | #define LPFC_MBX_SLI_CONFIG_MAX_HBD 10 | 264 | #define LPFC_MBX_SLI_CONFIG_MAX_HBD 8 |
226 | struct lpfc_sli_config_subcmd_hbd hbd[LPFC_MBX_SLI_CONFIG_MAX_HBD]; | 265 | struct lpfc_sli_config_hbd hbd[LPFC_MBX_SLI_CONFIG_MAX_HBD]; |
227 | }; | 266 | }; |
228 | 267 | ||
229 | struct lpfc_sli_config_mbox { | 268 | struct lpfc_sli_config_mbox { |
@@ -235,7 +274,11 @@ struct lpfc_sli_config_mbox { | |||
235 | #define lpfc_mqe_command_MASK 0x000000FF | 274 | #define lpfc_mqe_command_MASK 0x000000FF |
236 | #define lpfc_mqe_command_WORD word0 | 275 | #define lpfc_mqe_command_WORD word0 |
237 | union { | 276 | union { |
238 | struct lpfc_sli_config_generic sli_config_generic; | 277 | struct lpfc_sli_config_emb0_subsys sli_config_emb0_subsys; |
239 | struct lpfc_sli_config_subcmnd sli_config_subcmnd; | 278 | struct lpfc_sli_config_emb1_subsys sli_config_emb1_subsys; |
240 | } un; | 279 | } un; |
241 | }; | 280 | }; |
281 | |||
282 | /* driver only */ | ||
283 | #define SLI_CONFIG_NOT_HANDLED 0 | ||
284 | #define SLI_CONFIG_HANDLED 1 | ||
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index f0b332f4eedb..fc20c247f36b 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -55,6 +55,8 @@ void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *); | |||
55 | void lpfc_supported_pages(struct lpfcMboxq *); | 55 | void lpfc_supported_pages(struct lpfcMboxq *); |
56 | void lpfc_pc_sli4_params(struct lpfcMboxq *); | 56 | void lpfc_pc_sli4_params(struct lpfcMboxq *); |
57 | int lpfc_pc_sli4_params_get(struct lpfc_hba *, LPFC_MBOXQ_t *); | 57 | int lpfc_pc_sli4_params_get(struct lpfc_hba *, LPFC_MBOXQ_t *); |
58 | int lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *, struct lpfcMboxq *, | ||
59 | uint16_t, uint16_t, bool); | ||
58 | int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *); | 60 | int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *); |
59 | struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t); | 61 | struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t); |
60 | void lpfc_cleanup_rcv_buffers(struct lpfc_vport *); | 62 | void lpfc_cleanup_rcv_buffers(struct lpfc_vport *); |
@@ -171,6 +173,7 @@ void lpfc_delayed_disc_tmo(unsigned long); | |||
171 | void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *); | 173 | void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *); |
172 | 174 | ||
173 | int lpfc_config_port_prep(struct lpfc_hba *); | 175 | int lpfc_config_port_prep(struct lpfc_hba *); |
176 | void lpfc_update_vport_wwn(struct lpfc_vport *vport); | ||
174 | int lpfc_config_port_post(struct lpfc_hba *); | 177 | int lpfc_config_port_post(struct lpfc_hba *); |
175 | int lpfc_hba_down_prep(struct lpfc_hba *); | 178 | int lpfc_hba_down_prep(struct lpfc_hba *); |
176 | int lpfc_hba_down_post(struct lpfc_hba *); | 179 | int lpfc_hba_down_post(struct lpfc_hba *); |
@@ -365,6 +368,10 @@ extern void lpfc_debugfs_slow_ring_trc(struct lpfc_hba *, char *, uint32_t, | |||
365 | uint32_t, uint32_t); | 368 | uint32_t, uint32_t); |
366 | extern struct lpfc_hbq_init *lpfc_hbq_defs[]; | 369 | extern struct lpfc_hbq_init *lpfc_hbq_defs[]; |
367 | 370 | ||
371 | /* SLI4 if_type 2 externs. */ | ||
372 | int lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *); | ||
373 | int lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *); | ||
374 | |||
368 | /* externs BlockGuard */ | 375 | /* externs BlockGuard */ |
369 | extern char *_dump_buf_data; | 376 | extern char *_dump_buf_data; |
370 | extern unsigned long _dump_buf_data_order; | 377 | extern unsigned long _dump_buf_data_order; |
@@ -429,3 +436,6 @@ void lpfc_cleanup_wt_rrqs(struct lpfc_hba *); | |||
429 | void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *); | 436 | void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *); |
430 | struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, | 437 | struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, |
431 | uint32_t); | 438 | uint32_t); |
439 | int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *); | ||
440 | /* functions to support SR-IOV */ | ||
441 | int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int); | ||
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index d9edfd90d7ff..779b88e1469d 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -352,6 +352,8 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, | |||
352 | icmd->ulpLe = 1; | 352 | icmd->ulpLe = 1; |
353 | icmd->ulpClass = CLASS3; | 353 | icmd->ulpClass = CLASS3; |
354 | icmd->ulpContext = ndlp->nlp_rpi; | 354 | icmd->ulpContext = ndlp->nlp_rpi; |
355 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
356 | icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | ||
355 | 357 | ||
356 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { | 358 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { |
357 | /* For GEN_REQUEST64_CR, use the RPI */ | 359 | /* For GEN_REQUEST64_CR, use the RPI */ |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index c93fca058603..ffe82d169b40 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
@@ -1665,7 +1665,8 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, | |||
1665 | /* Get fast-path complete queue information */ | 1665 | /* Get fast-path complete queue information */ |
1666 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1666 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1667 | "Fast-path FCP CQ information:\n"); | 1667 | "Fast-path FCP CQ information:\n"); |
1668 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { | 1668 | fcp_qidx = 0; |
1669 | do { | ||
1669 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1670 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1670 | "Associated EQID[%02d]:\n", | 1671 | "Associated EQID[%02d]:\n", |
1671 | phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid); | 1672 | phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid); |
@@ -1678,7 +1679,7 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, | |||
1678 | phba->sli4_hba.fcp_cq[fcp_qidx]->entry_size, | 1679 | phba->sli4_hba.fcp_cq[fcp_qidx]->entry_size, |
1679 | phba->sli4_hba.fcp_cq[fcp_qidx]->host_index, | 1680 | phba->sli4_hba.fcp_cq[fcp_qidx]->host_index, |
1680 | phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index); | 1681 | phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index); |
1681 | } | 1682 | } while (++fcp_qidx < phba->cfg_fcp_eq_count); |
1682 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); | 1683 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); |
1683 | 1684 | ||
1684 | /* Get mailbox queue information */ | 1685 | /* Get mailbox queue information */ |
@@ -2012,7 +2013,8 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, | |||
2012 | goto pass_check; | 2013 | goto pass_check; |
2013 | } | 2014 | } |
2014 | /* FCP complete queue */ | 2015 | /* FCP complete queue */ |
2015 | for (qidx = 0; qidx < phba->cfg_fcp_eq_count; qidx++) { | 2016 | qidx = 0; |
2017 | do { | ||
2016 | if (phba->sli4_hba.fcp_cq[qidx]->queue_id == queid) { | 2018 | if (phba->sli4_hba.fcp_cq[qidx]->queue_id == queid) { |
2017 | /* Sanity check */ | 2019 | /* Sanity check */ |
2018 | rc = lpfc_idiag_que_param_check( | 2020 | rc = lpfc_idiag_que_param_check( |
@@ -2024,7 +2026,7 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, | |||
2024 | phba->sli4_hba.fcp_cq[qidx]; | 2026 | phba->sli4_hba.fcp_cq[qidx]; |
2025 | goto pass_check; | 2027 | goto pass_check; |
2026 | } | 2028 | } |
2027 | } | 2029 | } while (++qidx < phba->cfg_fcp_eq_count); |
2028 | goto error_out; | 2030 | goto error_out; |
2029 | break; | 2031 | break; |
2030 | case LPFC_IDIAG_MQ: | 2032 | case LPFC_IDIAG_MQ: |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index e2c452467c8b..32a084534f3e 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -250,7 +250,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
250 | icmd->un.elsreq64.myID = vport->fc_myDID; | 250 | icmd->un.elsreq64.myID = vport->fc_myDID; |
251 | 251 | ||
252 | /* For ELS_REQUEST64_CR, use the VPI by default */ | 252 | /* For ELS_REQUEST64_CR, use the VPI by default */ |
253 | icmd->ulpContext = vport->vpi + phba->vpi_base; | 253 | icmd->ulpContext = phba->vpi_ids[vport->vpi]; |
254 | icmd->ulpCt_h = 0; | 254 | icmd->ulpCt_h = 0; |
255 | /* The CT field must be 0=INVALID_RPI for the ECHO cmd */ | 255 | /* The CT field must be 0=INVALID_RPI for the ECHO cmd */ |
256 | if (elscmd == ELS_CMD_ECHO) | 256 | if (elscmd == ELS_CMD_ECHO) |
@@ -454,6 +454,7 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport) | |||
454 | rc = -ENOMEM; | 454 | rc = -ENOMEM; |
455 | goto fail_free_dmabuf; | 455 | goto fail_free_dmabuf; |
456 | } | 456 | } |
457 | |||
457 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 458 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
458 | if (!mboxq) { | 459 | if (!mboxq) { |
459 | rc = -ENOMEM; | 460 | rc = -ENOMEM; |
@@ -6585,6 +6586,26 @@ lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) | |||
6585 | { | 6586 | { |
6586 | struct lpfc_vport *vport; | 6587 | struct lpfc_vport *vport; |
6587 | unsigned long flags; | 6588 | unsigned long flags; |
6589 | int i; | ||
6590 | |||
6591 | /* The physical ports are always vpi 0 - translate is unnecessary. */ | ||
6592 | if (vpi > 0) { | ||
6593 | /* | ||
6594 | * Translate the physical vpi to the logical vpi. The | ||
6595 | * vport stores the logical vpi. | ||
6596 | */ | ||
6597 | for (i = 0; i < phba->max_vpi; i++) { | ||
6598 | if (vpi == phba->vpi_ids[i]) | ||
6599 | break; | ||
6600 | } | ||
6601 | |||
6602 | if (i >= phba->max_vpi) { | ||
6603 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
6604 | "2936 Could not find Vport mapped " | ||
6605 | "to vpi %d\n", vpi); | ||
6606 | return NULL; | ||
6607 | } | ||
6608 | } | ||
6588 | 6609 | ||
6589 | spin_lock_irqsave(&phba->hbalock, flags); | 6610 | spin_lock_irqsave(&phba->hbalock, flags); |
6590 | list_for_each_entry(vport, &phba->port_list, listentry) { | 6611 | list_for_each_entry(vport, &phba->port_list, listentry) { |
@@ -6641,8 +6662,9 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
6641 | vport = phba->pport; | 6662 | vport = phba->pport; |
6642 | else | 6663 | else |
6643 | vport = lpfc_find_vport_by_vpid(phba, | 6664 | vport = lpfc_find_vport_by_vpid(phba, |
6644 | icmd->unsli3.rcvsli3.vpi - phba->vpi_base); | 6665 | icmd->unsli3.rcvsli3.vpi); |
6645 | } | 6666 | } |
6667 | |||
6646 | /* If there are no BDEs associated | 6668 | /* If there are no BDEs associated |
6647 | * with this IOCB, there is nothing to do. | 6669 | * with this IOCB, there is nothing to do. |
6648 | */ | 6670 | */ |
@@ -7222,7 +7244,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
7222 | elsiocb->iocb.ulpCt_h = (SLI4_CT_VPI >> 1) & 1; | 7244 | elsiocb->iocb.ulpCt_h = (SLI4_CT_VPI >> 1) & 1; |
7223 | elsiocb->iocb.ulpCt_l = SLI4_CT_VPI & 1 ; | 7245 | elsiocb->iocb.ulpCt_l = SLI4_CT_VPI & 1 ; |
7224 | /* Set the ulpContext to the vpi */ | 7246 | /* Set the ulpContext to the vpi */ |
7225 | elsiocb->iocb.ulpContext = vport->vpi + phba->vpi_base; | 7247 | elsiocb->iocb.ulpContext = phba->vpi_ids[vport->vpi]; |
7226 | } else { | 7248 | } else { |
7227 | /* For FDISC, Let FDISC rsp set the NPortID for this VPI */ | 7249 | /* For FDISC, Let FDISC rsp set the NPortID for this VPI */ |
7228 | icmd->ulpCt_h = 1; | 7250 | icmd->ulpCt_h = 1; |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 7a35df5e2038..18d0dbfda2bc 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -881,7 +881,7 @@ lpfc_linkdown(struct lpfc_hba *phba) | |||
881 | /* Clean up any firmware default rpi's */ | 881 | /* Clean up any firmware default rpi's */ |
882 | mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 882 | mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
883 | if (mb) { | 883 | if (mb) { |
884 | lpfc_unreg_did(phba, 0xffff, 0xffffffff, mb); | 884 | lpfc_unreg_did(phba, 0xffff, LPFC_UNREG_ALL_DFLT_RPIS, mb); |
885 | mb->vport = vport; | 885 | mb->vport = vport; |
886 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 886 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
887 | if (lpfc_sli_issue_mbox(phba, mb, MBX_NOWAIT) | 887 | if (lpfc_sli_issue_mbox(phba, mb, MBX_NOWAIT) |
@@ -2690,16 +2690,7 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2690 | 2690 | ||
2691 | memcpy((uint8_t *) &vport->fc_sparam, (uint8_t *) mp->virt, | 2691 | memcpy((uint8_t *) &vport->fc_sparam, (uint8_t *) mp->virt, |
2692 | sizeof (struct serv_parm)); | 2692 | sizeof (struct serv_parm)); |
2693 | if (phba->cfg_soft_wwnn) | 2693 | lpfc_update_vport_wwn(vport); |
2694 | u64_to_wwn(phba->cfg_soft_wwnn, | ||
2695 | vport->fc_sparam.nodeName.u.wwn); | ||
2696 | if (phba->cfg_soft_wwpn) | ||
2697 | u64_to_wwn(phba->cfg_soft_wwpn, | ||
2698 | vport->fc_sparam.portName.u.wwn); | ||
2699 | memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName, | ||
2700 | sizeof(vport->fc_nodename)); | ||
2701 | memcpy(&vport->fc_portname, &vport->fc_sparam.portName, | ||
2702 | sizeof(vport->fc_portname)); | ||
2703 | if (vport->port_type == LPFC_PHYSICAL_PORT) { | 2694 | if (vport->port_type == LPFC_PHYSICAL_PORT) { |
2704 | memcpy(&phba->wwnn, &vport->fc_nodename, sizeof(phba->wwnn)); | 2695 | memcpy(&phba->wwnn, &vport->fc_nodename, sizeof(phba->wwnn)); |
2705 | memcpy(&phba->wwpn, &vport->fc_portname, sizeof(phba->wwnn)); | 2696 | memcpy(&phba->wwpn, &vport->fc_portname, sizeof(phba->wwnn)); |
@@ -3430,7 +3421,8 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
3430 | return; | 3421 | return; |
3431 | } | 3422 | } |
3432 | 3423 | ||
3433 | ndlp->nlp_rpi = mb->un.varWords[0]; | 3424 | if (phba->sli_rev < LPFC_SLI_REV4) |
3425 | ndlp->nlp_rpi = mb->un.varWords[0]; | ||
3434 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 3426 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
3435 | ndlp->nlp_type |= NLP_FABRIC; | 3427 | ndlp->nlp_type |= NLP_FABRIC; |
3436 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 3428 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
@@ -3504,7 +3496,8 @@ out: | |||
3504 | return; | 3496 | return; |
3505 | } | 3497 | } |
3506 | 3498 | ||
3507 | ndlp->nlp_rpi = mb->un.varWords[0]; | 3499 | if (phba->sli_rev < LPFC_SLI_REV4) |
3500 | ndlp->nlp_rpi = mb->un.varWords[0]; | ||
3508 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 3501 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
3509 | ndlp->nlp_type |= NLP_FABRIC; | 3502 | ndlp->nlp_type |= NLP_FABRIC; |
3510 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 3503 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
@@ -3591,7 +3584,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
3591 | if (ndlp->nlp_type & NLP_FCP_INITIATOR) | 3584 | if (ndlp->nlp_type & NLP_FCP_INITIATOR) |
3592 | rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; | 3585 | rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; |
3593 | 3586 | ||
3594 | |||
3595 | if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN) | 3587 | if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN) |
3596 | fc_remote_port_rolechg(rport, rport_ids.roles); | 3588 | fc_remote_port_rolechg(rport, rport_ids.roles); |
3597 | 3589 | ||
@@ -4106,11 +4098,16 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
4106 | struct lpfc_hba *phba = vport->phba; | 4098 | struct lpfc_hba *phba = vport->phba; |
4107 | LPFC_MBOXQ_t *mbox; | 4099 | LPFC_MBOXQ_t *mbox; |
4108 | int rc; | 4100 | int rc; |
4101 | uint16_t rpi; | ||
4109 | 4102 | ||
4110 | if (ndlp->nlp_flag & NLP_RPI_REGISTERED) { | 4103 | if (ndlp->nlp_flag & NLP_RPI_REGISTERED) { |
4111 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 4104 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
4112 | if (mbox) { | 4105 | if (mbox) { |
4113 | lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox); | 4106 | /* SLI4 ports require the physical rpi value. */ |
4107 | rpi = ndlp->nlp_rpi; | ||
4108 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
4109 | rpi = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | ||
4110 | lpfc_unreg_login(phba, vport->vpi, rpi, mbox); | ||
4114 | mbox->vport = vport; | 4111 | mbox->vport = vport; |
4115 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 4112 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
4116 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); | 4113 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); |
@@ -4179,7 +4176,8 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport) | |||
4179 | 4176 | ||
4180 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 4177 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
4181 | if (mbox) { | 4178 | if (mbox) { |
4182 | lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox); | 4179 | lpfc_unreg_login(phba, vport->vpi, LPFC_UNREG_ALL_RPIS_VPORT, |
4180 | mbox); | ||
4183 | mbox->vport = vport; | 4181 | mbox->vport = vport; |
4184 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 4182 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
4185 | mbox->context1 = NULL; | 4183 | mbox->context1 = NULL; |
@@ -4203,7 +4201,8 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport) | |||
4203 | 4201 | ||
4204 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 4202 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
4205 | if (mbox) { | 4203 | if (mbox) { |
4206 | lpfc_unreg_did(phba, vport->vpi, 0xffffffff, mbox); | 4204 | lpfc_unreg_did(phba, vport->vpi, LPFC_UNREG_ALL_DFLT_RPIS, |
4205 | mbox); | ||
4207 | mbox->vport = vport; | 4206 | mbox->vport = vport; |
4208 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 4207 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
4209 | mbox->context1 = NULL; | 4208 | mbox->context1 = NULL; |
@@ -4653,10 +4652,7 @@ lpfc_disc_start(struct lpfc_vport *vport) | |||
4653 | if (num_sent) | 4652 | if (num_sent) |
4654 | return; | 4653 | return; |
4655 | 4654 | ||
4656 | /* | 4655 | /* Register the VPI for SLI3, NON-NPIV only. */ |
4657 | * For SLI3, cmpl_reg_vpi will set port_state to READY, and | ||
4658 | * continue discovery. | ||
4659 | */ | ||
4660 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && | 4656 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && |
4661 | !(vport->fc_flag & FC_PT2PT) && | 4657 | !(vport->fc_flag & FC_PT2PT) && |
4662 | !(vport->fc_flag & FC_RSCN_MODE) && | 4658 | !(vport->fc_flag & FC_RSCN_MODE) && |
@@ -4943,7 +4939,7 @@ restart_disc: | |||
4943 | if (phba->sli_rev < LPFC_SLI_REV4) { | 4939 | if (phba->sli_rev < LPFC_SLI_REV4) { |
4944 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) | 4940 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) |
4945 | lpfc_issue_reg_vpi(phba, vport); | 4941 | lpfc_issue_reg_vpi(phba, vport); |
4946 | else { /* NPIV Not enabled */ | 4942 | else { |
4947 | lpfc_issue_clear_la(phba, vport); | 4943 | lpfc_issue_clear_la(phba, vport); |
4948 | vport->port_state = LPFC_VPORT_READY; | 4944 | vport->port_state = LPFC_VPORT_READY; |
4949 | } | 4945 | } |
@@ -5069,7 +5065,8 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
5069 | pmb->context1 = NULL; | 5065 | pmb->context1 = NULL; |
5070 | pmb->context2 = NULL; | 5066 | pmb->context2 = NULL; |
5071 | 5067 | ||
5072 | ndlp->nlp_rpi = mb->un.varWords[0]; | 5068 | if (phba->sli_rev < LPFC_SLI_REV4) |
5069 | ndlp->nlp_rpi = mb->un.varWords[0]; | ||
5073 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 5070 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
5074 | ndlp->nlp_type |= NLP_FABRIC; | 5071 | ndlp->nlp_type |= NLP_FABRIC; |
5075 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 5072 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
@@ -5354,6 +5351,17 @@ lpfc_fcf_inuse(struct lpfc_hba *phba) | |||
5354 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { | 5351 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { |
5355 | shost = lpfc_shost_from_vport(vports[i]); | 5352 | shost = lpfc_shost_from_vport(vports[i]); |
5356 | spin_lock_irq(shost->host_lock); | 5353 | spin_lock_irq(shost->host_lock); |
5354 | /* | ||
5355 | * IF the CVL_RCVD bit is not set then we have sent the | ||
5356 | * flogi. | ||
5357 | * If dev_loss fires while we are waiting we do not want to | ||
5358 | * unreg the fcf. | ||
5359 | */ | ||
5360 | if (!(vports[i]->fc_flag & FC_VPORT_CVL_RCVD)) { | ||
5361 | spin_unlock_irq(shost->host_lock); | ||
5362 | ret = 1; | ||
5363 | goto out; | ||
5364 | } | ||
5357 | list_for_each_entry(ndlp, &vports[i]->fc_nodes, nlp_listp) { | 5365 | list_for_each_entry(ndlp, &vports[i]->fc_nodes, nlp_listp) { |
5358 | if (NLP_CHK_NODE_ACT(ndlp) && ndlp->rport && | 5366 | if (NLP_CHK_NODE_ACT(ndlp) && ndlp->rport && |
5359 | (ndlp->rport->roles & FC_RPORT_ROLE_FCP_TARGET)) { | 5367 | (ndlp->rport->roles & FC_RPORT_ROLE_FCP_TARGET)) { |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 86b6f7e6686a..9059524cf225 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -64,6 +64,8 @@ | |||
64 | #define SLI3_IOCB_CMD_SIZE 128 | 64 | #define SLI3_IOCB_CMD_SIZE 128 |
65 | #define SLI3_IOCB_RSP_SIZE 64 | 65 | #define SLI3_IOCB_RSP_SIZE 64 |
66 | 66 | ||
67 | #define LPFC_UNREG_ALL_RPIS_VPORT 0xffff | ||
68 | #define LPFC_UNREG_ALL_DFLT_RPIS 0xffffffff | ||
67 | 69 | ||
68 | /* vendor ID used in SCSI netlink calls */ | 70 | /* vendor ID used in SCSI netlink calls */ |
69 | #define LPFC_NL_VENDOR_ID (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX) | 71 | #define LPFC_NL_VENDOR_ID (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX) |
@@ -903,6 +905,8 @@ struct RRQ { /* Structure is in Big Endian format */ | |||
903 | #define rrq_rxid_WORD rrq_exchg | 905 | #define rrq_rxid_WORD rrq_exchg |
904 | }; | 906 | }; |
905 | 907 | ||
908 | #define LPFC_MAX_VFN_PER_PFN 255 /* Maximum VFs allowed per ARI */ | ||
909 | #define LPFC_DEF_VFN_PER_PFN 0 /* Default VFs due to platform limitation*/ | ||
906 | 910 | ||
907 | struct RTV_RSP { /* Structure is in Big Endian format */ | 911 | struct RTV_RSP { /* Structure is in Big Endian format */ |
908 | uint32_t ratov; | 912 | uint32_t ratov; |
@@ -1199,7 +1203,9 @@ typedef struct { | |||
1199 | #define PCI_DEVICE_ID_BALIUS 0xe131 | 1203 | #define PCI_DEVICE_ID_BALIUS 0xe131 |
1200 | #define PCI_DEVICE_ID_PROTEUS_PF 0xe180 | 1204 | #define PCI_DEVICE_ID_PROTEUS_PF 0xe180 |
1201 | #define PCI_DEVICE_ID_LANCER_FC 0xe200 | 1205 | #define PCI_DEVICE_ID_LANCER_FC 0xe200 |
1206 | #define PCI_DEVICE_ID_LANCER_FC_VF 0xe208 | ||
1202 | #define PCI_DEVICE_ID_LANCER_FCOE 0xe260 | 1207 | #define PCI_DEVICE_ID_LANCER_FCOE 0xe260 |
1208 | #define PCI_DEVICE_ID_LANCER_FCOE_VF 0xe268 | ||
1203 | #define PCI_DEVICE_ID_SAT_SMB 0xf011 | 1209 | #define PCI_DEVICE_ID_SAT_SMB 0xf011 |
1204 | #define PCI_DEVICE_ID_SAT_MID 0xf015 | 1210 | #define PCI_DEVICE_ID_SAT_MID 0xf015 |
1205 | #define PCI_DEVICE_ID_RFLY 0xf095 | 1211 | #define PCI_DEVICE_ID_RFLY 0xf095 |
@@ -3021,7 +3027,7 @@ typedef struct { | |||
3021 | #define MAILBOX_EXT_SIZE (MAILBOX_EXT_WSIZE * sizeof(uint32_t)) | 3027 | #define MAILBOX_EXT_SIZE (MAILBOX_EXT_WSIZE * sizeof(uint32_t)) |
3022 | #define MAILBOX_HBA_EXT_OFFSET 0x100 | 3028 | #define MAILBOX_HBA_EXT_OFFSET 0x100 |
3023 | /* max mbox xmit size is a page size for sysfs IO operations */ | 3029 | /* max mbox xmit size is a page size for sysfs IO operations */ |
3024 | #define MAILBOX_MAX_XMIT_SIZE PAGE_SIZE | 3030 | #define MAILBOX_SYSFS_MAX 4096 |
3025 | 3031 | ||
3026 | typedef union { | 3032 | typedef union { |
3027 | uint32_t varWords[MAILBOX_CMD_WSIZE - 1]; /* first word is type/ | 3033 | uint32_t varWords[MAILBOX_CMD_WSIZE - 1]; /* first word is type/ |
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 4dff668ebdad..11e26a26b5d1 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
@@ -170,6 +170,25 @@ struct lpfc_sli_intf { | |||
170 | #define LPFC_PCI_FUNC3 3 | 170 | #define LPFC_PCI_FUNC3 3 |
171 | #define LPFC_PCI_FUNC4 4 | 171 | #define LPFC_PCI_FUNC4 4 |
172 | 172 | ||
173 | /* SLI4 interface type-2 control register offsets */ | ||
174 | #define LPFC_CTL_PORT_SEM_OFFSET 0x400 | ||
175 | #define LPFC_CTL_PORT_STA_OFFSET 0x404 | ||
176 | #define LPFC_CTL_PORT_CTL_OFFSET 0x408 | ||
177 | #define LPFC_CTL_PORT_ER1_OFFSET 0x40C | ||
178 | #define LPFC_CTL_PORT_ER2_OFFSET 0x410 | ||
179 | #define LPFC_CTL_PDEV_CTL_OFFSET 0x414 | ||
180 | |||
181 | /* Some SLI4 interface type-2 PDEV_CTL register bits */ | ||
182 | #define LPFC_CTL_PDEV_CTL_DRST 0x00000001 | ||
183 | #define LPFC_CTL_PDEV_CTL_FRST 0x00000002 | ||
184 | #define LPFC_CTL_PDEV_CTL_DD 0x00000004 | ||
185 | #define LPFC_CTL_PDEV_CTL_LC 0x00000008 | ||
186 | #define LPFC_CTL_PDEV_CTL_FRL_ALL 0x00 | ||
187 | #define LPFC_CTL_PDEV_CTL_FRL_FC_FCOE 0x10 | ||
188 | #define LPFC_CTL_PDEV_CTL_FRL_NIC 0x20 | ||
189 | |||
190 | #define LPFC_FW_DUMP_REQUEST (LPFC_CTL_PDEV_CTL_DD | LPFC_CTL_PDEV_CTL_FRST) | ||
191 | |||
173 | /* Active interrupt test count */ | 192 | /* Active interrupt test count */ |
174 | #define LPFC_ACT_INTR_CNT 4 | 193 | #define LPFC_ACT_INTR_CNT 4 |
175 | 194 | ||
@@ -210,9 +229,26 @@ struct ulp_bde64 { | |||
210 | 229 | ||
211 | struct lpfc_sli4_flags { | 230 | struct lpfc_sli4_flags { |
212 | uint32_t word0; | 231 | uint32_t word0; |
213 | #define lpfc_fip_flag_SHIFT 0 | 232 | #define lpfc_idx_rsrc_rdy_SHIFT 0 |
214 | #define lpfc_fip_flag_MASK 0x00000001 | 233 | #define lpfc_idx_rsrc_rdy_MASK 0x00000001 |
215 | #define lpfc_fip_flag_WORD word0 | 234 | #define lpfc_idx_rsrc_rdy_WORD word0 |
235 | #define LPFC_IDX_RSRC_RDY 1 | ||
236 | #define lpfc_xri_rsrc_rdy_SHIFT 1 | ||
237 | #define lpfc_xri_rsrc_rdy_MASK 0x00000001 | ||
238 | #define lpfc_xri_rsrc_rdy_WORD word0 | ||
239 | #define LPFC_XRI_RSRC_RDY 1 | ||
240 | #define lpfc_rpi_rsrc_rdy_SHIFT 2 | ||
241 | #define lpfc_rpi_rsrc_rdy_MASK 0x00000001 | ||
242 | #define lpfc_rpi_rsrc_rdy_WORD word0 | ||
243 | #define LPFC_RPI_RSRC_RDY 1 | ||
244 | #define lpfc_vpi_rsrc_rdy_SHIFT 3 | ||
245 | #define lpfc_vpi_rsrc_rdy_MASK 0x00000001 | ||
246 | #define lpfc_vpi_rsrc_rdy_WORD word0 | ||
247 | #define LPFC_VPI_RSRC_RDY 1 | ||
248 | #define lpfc_vfi_rsrc_rdy_SHIFT 4 | ||
249 | #define lpfc_vfi_rsrc_rdy_MASK 0x00000001 | ||
250 | #define lpfc_vfi_rsrc_rdy_WORD word0 | ||
251 | #define LPFC_VFI_RSRC_RDY 1 | ||
216 | }; | 252 | }; |
217 | 253 | ||
218 | struct sli4_bls_rsp { | 254 | struct sli4_bls_rsp { |
@@ -739,6 +775,12 @@ union lpfc_sli4_cfg_shdr { | |||
739 | #define lpfc_mbox_hdr_version_SHIFT 0 | 775 | #define lpfc_mbox_hdr_version_SHIFT 0 |
740 | #define lpfc_mbox_hdr_version_MASK 0x000000FF | 776 | #define lpfc_mbox_hdr_version_MASK 0x000000FF |
741 | #define lpfc_mbox_hdr_version_WORD word9 | 777 | #define lpfc_mbox_hdr_version_WORD word9 |
778 | #define lpfc_mbox_hdr_pf_num_SHIFT 16 | ||
779 | #define lpfc_mbox_hdr_pf_num_MASK 0x000000FF | ||
780 | #define lpfc_mbox_hdr_pf_num_WORD word9 | ||
781 | #define lpfc_mbox_hdr_vh_num_SHIFT 24 | ||
782 | #define lpfc_mbox_hdr_vh_num_MASK 0x000000FF | ||
783 | #define lpfc_mbox_hdr_vh_num_WORD word9 | ||
742 | #define LPFC_Q_CREATE_VERSION_2 2 | 784 | #define LPFC_Q_CREATE_VERSION_2 2 |
743 | #define LPFC_Q_CREATE_VERSION_1 1 | 785 | #define LPFC_Q_CREATE_VERSION_1 1 |
744 | #define LPFC_Q_CREATE_VERSION_0 0 | 786 | #define LPFC_Q_CREATE_VERSION_0 0 |
@@ -766,12 +808,22 @@ union lpfc_sli4_cfg_shdr { | |||
766 | } response; | 808 | } response; |
767 | }; | 809 | }; |
768 | 810 | ||
769 | /* Mailbox structures */ | 811 | /* Mailbox Header structures. |
812 | * struct mbox_header is defined for first generation SLI4_CFG mailbox | ||
813 | * calls deployed for BE-based ports. | ||
814 | * | ||
815 | * struct sli4_mbox_header is defined for second generation SLI4 | ||
816 | * ports that don't deploy the SLI4_CFG mechanism. | ||
817 | */ | ||
770 | struct mbox_header { | 818 | struct mbox_header { |
771 | struct lpfc_sli4_cfg_mhdr cfg_mhdr; | 819 | struct lpfc_sli4_cfg_mhdr cfg_mhdr; |
772 | union lpfc_sli4_cfg_shdr cfg_shdr; | 820 | union lpfc_sli4_cfg_shdr cfg_shdr; |
773 | }; | 821 | }; |
774 | 822 | ||
823 | #define LPFC_EXTENT_LOCAL 0 | ||
824 | #define LPFC_TIMEOUT_DEFAULT 0 | ||
825 | #define LPFC_EXTENT_VERSION_DEFAULT 0 | ||
826 | |||
775 | /* Subsystem Definitions */ | 827 | /* Subsystem Definitions */ |
776 | #define LPFC_MBOX_SUBSYSTEM_COMMON 0x1 | 828 | #define LPFC_MBOX_SUBSYSTEM_COMMON 0x1 |
777 | #define LPFC_MBOX_SUBSYSTEM_FCOE 0xC | 829 | #define LPFC_MBOX_SUBSYSTEM_FCOE 0xC |
@@ -794,6 +846,13 @@ struct mbox_header { | |||
794 | #define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A | 846 | #define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A |
795 | #define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D | 847 | #define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D |
796 | #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A | 848 | #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A |
849 | #define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO 0x9A | ||
850 | #define LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT 0x9B | ||
851 | #define LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT 0x9C | ||
852 | #define LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT 0x9D | ||
853 | #define LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG 0xA0 | ||
854 | #define LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG 0xA4 | ||
855 | #define LPFC_MBOX_OPCODE_WRITE_OBJECT 0xAC | ||
797 | #define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5 | 856 | #define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5 |
798 | 857 | ||
799 | /* FCoE Opcodes */ | 858 | /* FCoE Opcodes */ |
@@ -808,6 +867,8 @@ struct mbox_header { | |||
808 | #define LPFC_MBOX_OPCODE_FCOE_DELETE_FCF 0x0A | 867 | #define LPFC_MBOX_OPCODE_FCOE_DELETE_FCF 0x0A |
809 | #define LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE 0x0B | 868 | #define LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE 0x0B |
810 | #define LPFC_MBOX_OPCODE_FCOE_REDISCOVER_FCF 0x10 | 869 | #define LPFC_MBOX_OPCODE_FCOE_REDISCOVER_FCF 0x10 |
870 | #define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE 0x22 | ||
871 | #define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK 0x23 | ||
811 | 872 | ||
812 | /* Mailbox command structures */ | 873 | /* Mailbox command structures */ |
813 | struct eq_context { | 874 | struct eq_context { |
@@ -1210,6 +1271,187 @@ struct lpfc_mbx_mq_destroy { | |||
1210 | } u; | 1271 | } u; |
1211 | }; | 1272 | }; |
1212 | 1273 | ||
1274 | /* Start Gen 2 SLI4 Mailbox definitions: */ | ||
1275 | |||
1276 | /* Define allocate-ready Gen 2 SLI4 FCoE Resource Extent Types. */ | ||
1277 | #define LPFC_RSC_TYPE_FCOE_VFI 0x20 | ||
1278 | #define LPFC_RSC_TYPE_FCOE_VPI 0x21 | ||
1279 | #define LPFC_RSC_TYPE_FCOE_RPI 0x22 | ||
1280 | #define LPFC_RSC_TYPE_FCOE_XRI 0x23 | ||
1281 | |||
1282 | struct lpfc_mbx_get_rsrc_extent_info { | ||
1283 | struct mbox_header header; | ||
1284 | union { | ||
1285 | struct { | ||
1286 | uint32_t word4; | ||
1287 | #define lpfc_mbx_get_rsrc_extent_info_type_SHIFT 0 | ||
1288 | #define lpfc_mbx_get_rsrc_extent_info_type_MASK 0x0000FFFF | ||
1289 | #define lpfc_mbx_get_rsrc_extent_info_type_WORD word4 | ||
1290 | } req; | ||
1291 | struct { | ||
1292 | uint32_t word4; | ||
1293 | #define lpfc_mbx_get_rsrc_extent_info_cnt_SHIFT 0 | ||
1294 | #define lpfc_mbx_get_rsrc_extent_info_cnt_MASK 0x0000FFFF | ||
1295 | #define lpfc_mbx_get_rsrc_extent_info_cnt_WORD word4 | ||
1296 | #define lpfc_mbx_get_rsrc_extent_info_size_SHIFT 16 | ||
1297 | #define lpfc_mbx_get_rsrc_extent_info_size_MASK 0x0000FFFF | ||
1298 | #define lpfc_mbx_get_rsrc_extent_info_size_WORD word4 | ||
1299 | } rsp; | ||
1300 | } u; | ||
1301 | }; | ||
1302 | |||
1303 | struct lpfc_id_range { | ||
1304 | uint32_t word5; | ||
1305 | #define lpfc_mbx_rsrc_id_word4_0_SHIFT 0 | ||
1306 | #define lpfc_mbx_rsrc_id_word4_0_MASK 0x0000FFFF | ||
1307 | #define lpfc_mbx_rsrc_id_word4_0_WORD word5 | ||
1308 | #define lpfc_mbx_rsrc_id_word4_1_SHIFT 16 | ||
1309 | #define lpfc_mbx_rsrc_id_word4_1_MASK 0x0000FFFF | ||
1310 | #define lpfc_mbx_rsrc_id_word4_1_WORD word5 | ||
1311 | }; | ||
1312 | |||
1313 | struct lpfc_mbx_set_link_diag_state { | ||
1314 | struct mbox_header header; | ||
1315 | union { | ||
1316 | struct { | ||
1317 | uint32_t word0; | ||
1318 | #define lpfc_mbx_set_diag_state_diag_SHIFT 0 | ||
1319 | #define lpfc_mbx_set_diag_state_diag_MASK 0x00000001 | ||
1320 | #define lpfc_mbx_set_diag_state_diag_WORD word0 | ||
1321 | #define lpfc_mbx_set_diag_state_link_num_SHIFT 16 | ||
1322 | #define lpfc_mbx_set_diag_state_link_num_MASK 0x0000003F | ||
1323 | #define lpfc_mbx_set_diag_state_link_num_WORD word0 | ||
1324 | #define lpfc_mbx_set_diag_state_link_type_SHIFT 22 | ||
1325 | #define lpfc_mbx_set_diag_state_link_type_MASK 0x00000003 | ||
1326 | #define lpfc_mbx_set_diag_state_link_type_WORD word0 | ||
1327 | } req; | ||
1328 | struct { | ||
1329 | uint32_t word0; | ||
1330 | } rsp; | ||
1331 | } u; | ||
1332 | }; | ||
1333 | |||
1334 | struct lpfc_mbx_set_link_diag_loopback { | ||
1335 | struct mbox_header header; | ||
1336 | union { | ||
1337 | struct { | ||
1338 | uint32_t word0; | ||
1339 | #define lpfc_mbx_set_diag_lpbk_type_SHIFT 0 | ||
1340 | #define lpfc_mbx_set_diag_lpbk_type_MASK 0x00000001 | ||
1341 | #define lpfc_mbx_set_diag_lpbk_type_WORD word0 | ||
1342 | #define LPFC_DIAG_LOOPBACK_TYPE_DISABLE 0x0 | ||
1343 | #define LPFC_DIAG_LOOPBACK_TYPE_INTERNAL 0x1 | ||
1344 | #define LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL 0x2 | ||
1345 | #define lpfc_mbx_set_diag_lpbk_link_num_SHIFT 16 | ||
1346 | #define lpfc_mbx_set_diag_lpbk_link_num_MASK 0x0000003F | ||
1347 | #define lpfc_mbx_set_diag_lpbk_link_num_WORD word0 | ||
1348 | #define lpfc_mbx_set_diag_lpbk_link_type_SHIFT 22 | ||
1349 | #define lpfc_mbx_set_diag_lpbk_link_type_MASK 0x00000003 | ||
1350 | #define lpfc_mbx_set_diag_lpbk_link_type_WORD word0 | ||
1351 | } req; | ||
1352 | struct { | ||
1353 | uint32_t word0; | ||
1354 | } rsp; | ||
1355 | } u; | ||
1356 | }; | ||
1357 | |||
1358 | struct lpfc_mbx_run_link_diag_test { | ||
1359 | struct mbox_header header; | ||
1360 | union { | ||
1361 | struct { | ||
1362 | uint32_t word0; | ||
1363 | #define lpfc_mbx_run_diag_test_link_num_SHIFT 16 | ||
1364 | #define lpfc_mbx_run_diag_test_link_num_MASK 0x0000003F | ||
1365 | #define lpfc_mbx_run_diag_test_link_num_WORD word0 | ||
1366 | #define lpfc_mbx_run_diag_test_link_type_SHIFT 22 | ||
1367 | #define lpfc_mbx_run_diag_test_link_type_MASK 0x00000003 | ||
1368 | #define lpfc_mbx_run_diag_test_link_type_WORD word0 | ||
1369 | uint32_t word1; | ||
1370 | #define lpfc_mbx_run_diag_test_test_id_SHIFT 0 | ||
1371 | #define lpfc_mbx_run_diag_test_test_id_MASK 0x0000FFFF | ||
1372 | #define lpfc_mbx_run_diag_test_test_id_WORD word1 | ||
1373 | #define lpfc_mbx_run_diag_test_loops_SHIFT 16 | ||
1374 | #define lpfc_mbx_run_diag_test_loops_MASK 0x0000FFFF | ||
1375 | #define lpfc_mbx_run_diag_test_loops_WORD word1 | ||
1376 | uint32_t word2; | ||
1377 | #define lpfc_mbx_run_diag_test_test_ver_SHIFT 0 | ||
1378 | #define lpfc_mbx_run_diag_test_test_ver_MASK 0x0000FFFF | ||
1379 | #define lpfc_mbx_run_diag_test_test_ver_WORD word2 | ||
1380 | #define lpfc_mbx_run_diag_test_err_act_SHIFT 16 | ||
1381 | #define lpfc_mbx_run_diag_test_err_act_MASK 0x000000FF | ||
1382 | #define lpfc_mbx_run_diag_test_err_act_WORD word2 | ||
1383 | } req; | ||
1384 | struct { | ||
1385 | uint32_t word0; | ||
1386 | } rsp; | ||
1387 | } u; | ||
1388 | }; | ||
1389 | |||
1390 | /* | ||
1391 | * struct lpfc_mbx_alloc_rsrc_extents: | ||
1392 | * A mbox is generically 256 bytes long. An SLI4_CONFIG mailbox requires | ||
1393 | * 6 words of header + 4 words of shared subcommand header + | ||
1394 | * 1 words of Extent-Opcode-specific header = 11 words or 44 bytes total. | ||
1395 | * | ||
1396 | * An embedded version of SLI4_CONFIG therefore has 256 - 44 = 212 bytes | ||
1397 | * for extents payload. | ||
1398 | * | ||
1399 | * 212/2 (bytes per extent) = 106 extents. | ||
1400 | * 106/2 (extents per word) = 53 words. | ||
1401 | * lpfc_id_range id is statically size to 53. | ||
1402 | * | ||
1403 | * This mailbox definition is used for ALLOC or GET_ALLOCATED | ||
1404 | * extent ranges. For ALLOC, the type and cnt are required. | ||
1405 | * For GET_ALLOCATED, only the type is required. | ||
1406 | */ | ||
1407 | struct lpfc_mbx_alloc_rsrc_extents { | ||
1408 | struct mbox_header header; | ||
1409 | union { | ||
1410 | struct { | ||
1411 | uint32_t word4; | ||
1412 | #define lpfc_mbx_alloc_rsrc_extents_type_SHIFT 0 | ||
1413 | #define lpfc_mbx_alloc_rsrc_extents_type_MASK 0x0000FFFF | ||
1414 | #define lpfc_mbx_alloc_rsrc_extents_type_WORD word4 | ||
1415 | #define lpfc_mbx_alloc_rsrc_extents_cnt_SHIFT 16 | ||
1416 | #define lpfc_mbx_alloc_rsrc_extents_cnt_MASK 0x0000FFFF | ||
1417 | #define lpfc_mbx_alloc_rsrc_extents_cnt_WORD word4 | ||
1418 | } req; | ||
1419 | struct { | ||
1420 | uint32_t word4; | ||
1421 | #define lpfc_mbx_rsrc_cnt_SHIFT 0 | ||
1422 | #define lpfc_mbx_rsrc_cnt_MASK 0x0000FFFF | ||
1423 | #define lpfc_mbx_rsrc_cnt_WORD word4 | ||
1424 | struct lpfc_id_range id[53]; | ||
1425 | } rsp; | ||
1426 | } u; | ||
1427 | }; | ||
1428 | |||
1429 | /* | ||
1430 | * This is the non-embedded version of ALLOC or GET RSRC_EXTENTS. Word4 in this | ||
1431 | * structure shares the same SHIFT/MASK/WORD defines provided in the | ||
1432 | * mbx_alloc_rsrc_extents and mbx_get_alloc_rsrc_extents, word4, provided in | ||
1433 | * the structures defined above. This non-embedded structure provides for the | ||
1434 | * maximum number of extents supported by the port. | ||
1435 | */ | ||
1436 | struct lpfc_mbx_nembed_rsrc_extent { | ||
1437 | union lpfc_sli4_cfg_shdr cfg_shdr; | ||
1438 | uint32_t word4; | ||
1439 | struct lpfc_id_range id; | ||
1440 | }; | ||
1441 | |||
1442 | struct lpfc_mbx_dealloc_rsrc_extents { | ||
1443 | struct mbox_header header; | ||
1444 | struct { | ||
1445 | uint32_t word4; | ||
1446 | #define lpfc_mbx_dealloc_rsrc_extents_type_SHIFT 0 | ||
1447 | #define lpfc_mbx_dealloc_rsrc_extents_type_MASK 0x0000FFFF | ||
1448 | #define lpfc_mbx_dealloc_rsrc_extents_type_WORD word4 | ||
1449 | } req; | ||
1450 | |||
1451 | }; | ||
1452 | |||
1453 | /* Start SLI4 FCoE specific mbox structures. */ | ||
1454 | |||
1213 | struct lpfc_mbx_post_hdr_tmpl { | 1455 | struct lpfc_mbx_post_hdr_tmpl { |
1214 | struct mbox_header header; | 1456 | struct mbox_header header; |
1215 | uint32_t word10; | 1457 | uint32_t word10; |
@@ -1229,7 +1471,7 @@ struct sli4_sge { /* SLI-4 */ | |||
1229 | 1471 | ||
1230 | uint32_t word2; | 1472 | uint32_t word2; |
1231 | #define lpfc_sli4_sge_offset_SHIFT 0 /* Offset of buffer - Not used*/ | 1473 | #define lpfc_sli4_sge_offset_SHIFT 0 /* Offset of buffer - Not used*/ |
1232 | #define lpfc_sli4_sge_offset_MASK 0x00FFFFFF | 1474 | #define lpfc_sli4_sge_offset_MASK 0x1FFFFFFF |
1233 | #define lpfc_sli4_sge_offset_WORD word2 | 1475 | #define lpfc_sli4_sge_offset_WORD word2 |
1234 | #define lpfc_sli4_sge_last_SHIFT 31 /* Last SEG in the SGL sets | 1476 | #define lpfc_sli4_sge_last_SHIFT 31 /* Last SEG in the SGL sets |
1235 | this flag !! */ | 1477 | this flag !! */ |
@@ -1773,61 +2015,31 @@ struct lpfc_mbx_read_rev { | |||
1773 | 2015 | ||
1774 | struct lpfc_mbx_read_config { | 2016 | struct lpfc_mbx_read_config { |
1775 | uint32_t word1; | 2017 | uint32_t word1; |
1776 | #define lpfc_mbx_rd_conf_max_bbc_SHIFT 0 | 2018 | #define lpfc_mbx_rd_conf_extnts_inuse_SHIFT 31 |
1777 | #define lpfc_mbx_rd_conf_max_bbc_MASK 0x000000FF | 2019 | #define lpfc_mbx_rd_conf_extnts_inuse_MASK 0x00000001 |
1778 | #define lpfc_mbx_rd_conf_max_bbc_WORD word1 | 2020 | #define lpfc_mbx_rd_conf_extnts_inuse_WORD word1 |
1779 | #define lpfc_mbx_rd_conf_init_bbc_SHIFT 8 | ||
1780 | #define lpfc_mbx_rd_conf_init_bbc_MASK 0x000000FF | ||
1781 | #define lpfc_mbx_rd_conf_init_bbc_WORD word1 | ||
1782 | uint32_t word2; | 2021 | uint32_t word2; |
1783 | #define lpfc_mbx_rd_conf_nport_did_SHIFT 0 | ||
1784 | #define lpfc_mbx_rd_conf_nport_did_MASK 0x00FFFFFF | ||
1785 | #define lpfc_mbx_rd_conf_nport_did_WORD word2 | ||
1786 | #define lpfc_mbx_rd_conf_topology_SHIFT 24 | 2022 | #define lpfc_mbx_rd_conf_topology_SHIFT 24 |
1787 | #define lpfc_mbx_rd_conf_topology_MASK 0x000000FF | 2023 | #define lpfc_mbx_rd_conf_topology_MASK 0x000000FF |
1788 | #define lpfc_mbx_rd_conf_topology_WORD word2 | 2024 | #define lpfc_mbx_rd_conf_topology_WORD word2 |
1789 | uint32_t word3; | 2025 | uint32_t rsvd_3; |
1790 | #define lpfc_mbx_rd_conf_ao_SHIFT 0 | ||
1791 | #define lpfc_mbx_rd_conf_ao_MASK 0x00000001 | ||
1792 | #define lpfc_mbx_rd_conf_ao_WORD word3 | ||
1793 | #define lpfc_mbx_rd_conf_bb_scn_SHIFT 8 | ||
1794 | #define lpfc_mbx_rd_conf_bb_scn_MASK 0x0000000F | ||
1795 | #define lpfc_mbx_rd_conf_bb_scn_WORD word3 | ||
1796 | #define lpfc_mbx_rd_conf_cbb_scn_SHIFT 12 | ||
1797 | #define lpfc_mbx_rd_conf_cbb_scn_MASK 0x0000000F | ||
1798 | #define lpfc_mbx_rd_conf_cbb_scn_WORD word3 | ||
1799 | #define lpfc_mbx_rd_conf_mc_SHIFT 29 | ||
1800 | #define lpfc_mbx_rd_conf_mc_MASK 0x00000001 | ||
1801 | #define lpfc_mbx_rd_conf_mc_WORD word3 | ||
1802 | uint32_t word4; | 2026 | uint32_t word4; |
1803 | #define lpfc_mbx_rd_conf_e_d_tov_SHIFT 0 | 2027 | #define lpfc_mbx_rd_conf_e_d_tov_SHIFT 0 |
1804 | #define lpfc_mbx_rd_conf_e_d_tov_MASK 0x0000FFFF | 2028 | #define lpfc_mbx_rd_conf_e_d_tov_MASK 0x0000FFFF |
1805 | #define lpfc_mbx_rd_conf_e_d_tov_WORD word4 | 2029 | #define lpfc_mbx_rd_conf_e_d_tov_WORD word4 |
1806 | uint32_t word5; | 2030 | uint32_t rsvd_5; |
1807 | #define lpfc_mbx_rd_conf_lp_tov_SHIFT 0 | ||
1808 | #define lpfc_mbx_rd_conf_lp_tov_MASK 0x0000FFFF | ||
1809 | #define lpfc_mbx_rd_conf_lp_tov_WORD word5 | ||
1810 | uint32_t word6; | 2031 | uint32_t word6; |
1811 | #define lpfc_mbx_rd_conf_r_a_tov_SHIFT 0 | 2032 | #define lpfc_mbx_rd_conf_r_a_tov_SHIFT 0 |
1812 | #define lpfc_mbx_rd_conf_r_a_tov_MASK 0x0000FFFF | 2033 | #define lpfc_mbx_rd_conf_r_a_tov_MASK 0x0000FFFF |
1813 | #define lpfc_mbx_rd_conf_r_a_tov_WORD word6 | 2034 | #define lpfc_mbx_rd_conf_r_a_tov_WORD word6 |
1814 | uint32_t word7; | 2035 | uint32_t rsvd_7; |
1815 | #define lpfc_mbx_rd_conf_r_t_tov_SHIFT 0 | 2036 | uint32_t rsvd_8; |
1816 | #define lpfc_mbx_rd_conf_r_t_tov_MASK 0x000000FF | ||
1817 | #define lpfc_mbx_rd_conf_r_t_tov_WORD word7 | ||
1818 | uint32_t word8; | ||
1819 | #define lpfc_mbx_rd_conf_al_tov_SHIFT 0 | ||
1820 | #define lpfc_mbx_rd_conf_al_tov_MASK 0x0000000F | ||
1821 | #define lpfc_mbx_rd_conf_al_tov_WORD word8 | ||
1822 | uint32_t word9; | 2037 | uint32_t word9; |
1823 | #define lpfc_mbx_rd_conf_lmt_SHIFT 0 | 2038 | #define lpfc_mbx_rd_conf_lmt_SHIFT 0 |
1824 | #define lpfc_mbx_rd_conf_lmt_MASK 0x0000FFFF | 2039 | #define lpfc_mbx_rd_conf_lmt_MASK 0x0000FFFF |
1825 | #define lpfc_mbx_rd_conf_lmt_WORD word9 | 2040 | #define lpfc_mbx_rd_conf_lmt_WORD word9 |
1826 | uint32_t word10; | 2041 | uint32_t rsvd_10; |
1827 | #define lpfc_mbx_rd_conf_max_alpa_SHIFT 0 | 2042 | uint32_t rsvd_11; |
1828 | #define lpfc_mbx_rd_conf_max_alpa_MASK 0x000000FF | ||
1829 | #define lpfc_mbx_rd_conf_max_alpa_WORD word10 | ||
1830 | uint32_t word11_rsvd; | ||
1831 | uint32_t word12; | 2043 | uint32_t word12; |
1832 | #define lpfc_mbx_rd_conf_xri_base_SHIFT 0 | 2044 | #define lpfc_mbx_rd_conf_xri_base_SHIFT 0 |
1833 | #define lpfc_mbx_rd_conf_xri_base_MASK 0x0000FFFF | 2045 | #define lpfc_mbx_rd_conf_xri_base_MASK 0x0000FFFF |
@@ -1857,9 +2069,6 @@ struct lpfc_mbx_read_config { | |||
1857 | #define lpfc_mbx_rd_conf_vfi_count_MASK 0x0000FFFF | 2069 | #define lpfc_mbx_rd_conf_vfi_count_MASK 0x0000FFFF |
1858 | #define lpfc_mbx_rd_conf_vfi_count_WORD word15 | 2070 | #define lpfc_mbx_rd_conf_vfi_count_WORD word15 |
1859 | uint32_t word16; | 2071 | uint32_t word16; |
1860 | #define lpfc_mbx_rd_conf_fcfi_base_SHIFT 0 | ||
1861 | #define lpfc_mbx_rd_conf_fcfi_base_MASK 0x0000FFFF | ||
1862 | #define lpfc_mbx_rd_conf_fcfi_base_WORD word16 | ||
1863 | #define lpfc_mbx_rd_conf_fcfi_count_SHIFT 16 | 2072 | #define lpfc_mbx_rd_conf_fcfi_count_SHIFT 16 |
1864 | #define lpfc_mbx_rd_conf_fcfi_count_MASK 0x0000FFFF | 2073 | #define lpfc_mbx_rd_conf_fcfi_count_MASK 0x0000FFFF |
1865 | #define lpfc_mbx_rd_conf_fcfi_count_WORD word16 | 2074 | #define lpfc_mbx_rd_conf_fcfi_count_WORD word16 |
@@ -2169,6 +2378,12 @@ struct lpfc_sli4_parameters { | |||
2169 | #define cfg_fcoe_SHIFT 0 | 2378 | #define cfg_fcoe_SHIFT 0 |
2170 | #define cfg_fcoe_MASK 0x00000001 | 2379 | #define cfg_fcoe_MASK 0x00000001 |
2171 | #define cfg_fcoe_WORD word12 | 2380 | #define cfg_fcoe_WORD word12 |
2381 | #define cfg_ext_SHIFT 1 | ||
2382 | #define cfg_ext_MASK 0x00000001 | ||
2383 | #define cfg_ext_WORD word12 | ||
2384 | #define cfg_hdrr_SHIFT 2 | ||
2385 | #define cfg_hdrr_MASK 0x00000001 | ||
2386 | #define cfg_hdrr_WORD word12 | ||
2172 | #define cfg_phwq_SHIFT 15 | 2387 | #define cfg_phwq_SHIFT 15 |
2173 | #define cfg_phwq_MASK 0x00000001 | 2388 | #define cfg_phwq_MASK 0x00000001 |
2174 | #define cfg_phwq_WORD word12 | 2389 | #define cfg_phwq_WORD word12 |
@@ -2198,6 +2413,145 @@ struct lpfc_mbx_get_sli4_parameters { | |||
2198 | struct lpfc_sli4_parameters sli4_parameters; | 2413 | struct lpfc_sli4_parameters sli4_parameters; |
2199 | }; | 2414 | }; |
2200 | 2415 | ||
2416 | struct lpfc_rscr_desc_generic { | ||
2417 | #define LPFC_RSRC_DESC_WSIZE 18 | ||
2418 | uint32_t desc[LPFC_RSRC_DESC_WSIZE]; | ||
2419 | }; | ||
2420 | |||
2421 | struct lpfc_rsrc_desc_pcie { | ||
2422 | uint32_t word0; | ||
2423 | #define lpfc_rsrc_desc_pcie_type_SHIFT 0 | ||
2424 | #define lpfc_rsrc_desc_pcie_type_MASK 0x000000ff | ||
2425 | #define lpfc_rsrc_desc_pcie_type_WORD word0 | ||
2426 | #define LPFC_RSRC_DESC_TYPE_PCIE 0x40 | ||
2427 | uint32_t word1; | ||
2428 | #define lpfc_rsrc_desc_pcie_pfnum_SHIFT 0 | ||
2429 | #define lpfc_rsrc_desc_pcie_pfnum_MASK 0x000000ff | ||
2430 | #define lpfc_rsrc_desc_pcie_pfnum_WORD word1 | ||
2431 | uint32_t reserved; | ||
2432 | uint32_t word3; | ||
2433 | #define lpfc_rsrc_desc_pcie_sriov_sta_SHIFT 0 | ||
2434 | #define lpfc_rsrc_desc_pcie_sriov_sta_MASK 0x000000ff | ||
2435 | #define lpfc_rsrc_desc_pcie_sriov_sta_WORD word3 | ||
2436 | #define lpfc_rsrc_desc_pcie_pf_sta_SHIFT 8 | ||
2437 | #define lpfc_rsrc_desc_pcie_pf_sta_MASK 0x000000ff | ||
2438 | #define lpfc_rsrc_desc_pcie_pf_sta_WORD word3 | ||
2439 | #define lpfc_rsrc_desc_pcie_pf_type_SHIFT 16 | ||
2440 | #define lpfc_rsrc_desc_pcie_pf_type_MASK 0x000000ff | ||
2441 | #define lpfc_rsrc_desc_pcie_pf_type_WORD word3 | ||
2442 | uint32_t word4; | ||
2443 | #define lpfc_rsrc_desc_pcie_nr_virtfn_SHIFT 0 | ||
2444 | #define lpfc_rsrc_desc_pcie_nr_virtfn_MASK 0x0000ffff | ||
2445 | #define lpfc_rsrc_desc_pcie_nr_virtfn_WORD word4 | ||
2446 | }; | ||
2447 | |||
2448 | struct lpfc_rsrc_desc_fcfcoe { | ||
2449 | uint32_t word0; | ||
2450 | #define lpfc_rsrc_desc_fcfcoe_type_SHIFT 0 | ||
2451 | #define lpfc_rsrc_desc_fcfcoe_type_MASK 0x000000ff | ||
2452 | #define lpfc_rsrc_desc_fcfcoe_type_WORD word0 | ||
2453 | #define LPFC_RSRC_DESC_TYPE_FCFCOE 0x43 | ||
2454 | uint32_t word1; | ||
2455 | #define lpfc_rsrc_desc_fcfcoe_vfnum_SHIFT 0 | ||
2456 | #define lpfc_rsrc_desc_fcfcoe_vfnum_MASK 0x000000ff | ||
2457 | #define lpfc_rsrc_desc_fcfcoe_vfnum_WORD word1 | ||
2458 | #define lpfc_rsrc_desc_fcfcoe_pfnum_SHIFT 16 | ||
2459 | #define lpfc_rsrc_desc_fcfcoe_pfnum_MASK 0x000007ff | ||
2460 | #define lpfc_rsrc_desc_fcfcoe_pfnum_WORD word1 | ||
2461 | uint32_t word2; | ||
2462 | #define lpfc_rsrc_desc_fcfcoe_rpi_cnt_SHIFT 0 | ||
2463 | #define lpfc_rsrc_desc_fcfcoe_rpi_cnt_MASK 0x0000ffff | ||
2464 | #define lpfc_rsrc_desc_fcfcoe_rpi_cnt_WORD word2 | ||
2465 | #define lpfc_rsrc_desc_fcfcoe_xri_cnt_SHIFT 16 | ||
2466 | #define lpfc_rsrc_desc_fcfcoe_xri_cnt_MASK 0x0000ffff | ||
2467 | #define lpfc_rsrc_desc_fcfcoe_xri_cnt_WORD word2 | ||
2468 | uint32_t word3; | ||
2469 | #define lpfc_rsrc_desc_fcfcoe_wq_cnt_SHIFT 0 | ||
2470 | #define lpfc_rsrc_desc_fcfcoe_wq_cnt_MASK 0x0000ffff | ||
2471 | #define lpfc_rsrc_desc_fcfcoe_wq_cnt_WORD word3 | ||
2472 | #define lpfc_rsrc_desc_fcfcoe_rq_cnt_SHIFT 16 | ||
2473 | #define lpfc_rsrc_desc_fcfcoe_rq_cnt_MASK 0x0000ffff | ||
2474 | #define lpfc_rsrc_desc_fcfcoe_rq_cnt_WORD word3 | ||
2475 | uint32_t word4; | ||
2476 | #define lpfc_rsrc_desc_fcfcoe_cq_cnt_SHIFT 0 | ||
2477 | #define lpfc_rsrc_desc_fcfcoe_cq_cnt_MASK 0x0000ffff | ||
2478 | #define lpfc_rsrc_desc_fcfcoe_cq_cnt_WORD word4 | ||
2479 | #define lpfc_rsrc_desc_fcfcoe_vpi_cnt_SHIFT 16 | ||
2480 | #define lpfc_rsrc_desc_fcfcoe_vpi_cnt_MASK 0x0000ffff | ||
2481 | #define lpfc_rsrc_desc_fcfcoe_vpi_cnt_WORD word4 | ||
2482 | uint32_t word5; | ||
2483 | #define lpfc_rsrc_desc_fcfcoe_fcfi_cnt_SHIFT 0 | ||
2484 | #define lpfc_rsrc_desc_fcfcoe_fcfi_cnt_MASK 0x0000ffff | ||
2485 | #define lpfc_rsrc_desc_fcfcoe_fcfi_cnt_WORD word5 | ||
2486 | #define lpfc_rsrc_desc_fcfcoe_vfi_cnt_SHIFT 16 | ||
2487 | #define lpfc_rsrc_desc_fcfcoe_vfi_cnt_MASK 0x0000ffff | ||
2488 | #define lpfc_rsrc_desc_fcfcoe_vfi_cnt_WORD word5 | ||
2489 | uint32_t word6; | ||
2490 | uint32_t word7; | ||
2491 | uint32_t word8; | ||
2492 | uint32_t word9; | ||
2493 | uint32_t word10; | ||
2494 | uint32_t word11; | ||
2495 | uint32_t word12; | ||
2496 | uint32_t word13; | ||
2497 | #define lpfc_rsrc_desc_fcfcoe_lnk_nr_SHIFT 0 | ||
2498 | #define lpfc_rsrc_desc_fcfcoe_lnk_nr_MASK 0x0000003f | ||
2499 | #define lpfc_rsrc_desc_fcfcoe_lnk_nr_WORD word13 | ||
2500 | #define lpfc_rsrc_desc_fcfcoe_lnk_tp_SHIFT 6 | ||
2501 | #define lpfc_rsrc_desc_fcfcoe_lnk_tp_MASK 0x00000003 | ||
2502 | #define lpfc_rsrc_desc_fcfcoe_lnk_tp_WORD word13 | ||
2503 | #define lpfc_rsrc_desc_fcfcoe_lmc_SHIFT 8 | ||
2504 | #define lpfc_rsrc_desc_fcfcoe_lmc_MASK 0x00000001 | ||
2505 | #define lpfc_rsrc_desc_fcfcoe_lmc_WORD word13 | ||
2506 | #define lpfc_rsrc_desc_fcfcoe_lld_SHIFT 9 | ||
2507 | #define lpfc_rsrc_desc_fcfcoe_lld_MASK 0x00000001 | ||
2508 | #define lpfc_rsrc_desc_fcfcoe_lld_WORD word13 | ||
2509 | #define lpfc_rsrc_desc_fcfcoe_eq_cnt_SHIFT 16 | ||
2510 | #define lpfc_rsrc_desc_fcfcoe_eq_cnt_MASK 0x0000ffff | ||
2511 | #define lpfc_rsrc_desc_fcfcoe_eq_cnt_WORD word13 | ||
2512 | }; | ||
2513 | |||
2514 | struct lpfc_func_cfg { | ||
2515 | #define LPFC_RSRC_DESC_MAX_NUM 2 | ||
2516 | uint32_t rsrc_desc_count; | ||
2517 | struct lpfc_rscr_desc_generic desc[LPFC_RSRC_DESC_MAX_NUM]; | ||
2518 | }; | ||
2519 | |||
2520 | struct lpfc_mbx_get_func_cfg { | ||
2521 | struct mbox_header header; | ||
2522 | #define LPFC_CFG_TYPE_PERSISTENT_OVERRIDE 0x0 | ||
2523 | #define LPFC_CFG_TYPE_FACTURY_DEFAULT 0x1 | ||
2524 | #define LPFC_CFG_TYPE_CURRENT_ACTIVE 0x2 | ||
2525 | struct lpfc_func_cfg func_cfg; | ||
2526 | }; | ||
2527 | |||
2528 | struct lpfc_prof_cfg { | ||
2529 | #define LPFC_RSRC_DESC_MAX_NUM 2 | ||
2530 | uint32_t rsrc_desc_count; | ||
2531 | struct lpfc_rscr_desc_generic desc[LPFC_RSRC_DESC_MAX_NUM]; | ||
2532 | }; | ||
2533 | |||
2534 | struct lpfc_mbx_get_prof_cfg { | ||
2535 | struct mbox_header header; | ||
2536 | #define LPFC_CFG_TYPE_PERSISTENT_OVERRIDE 0x0 | ||
2537 | #define LPFC_CFG_TYPE_FACTURY_DEFAULT 0x1 | ||
2538 | #define LPFC_CFG_TYPE_CURRENT_ACTIVE 0x2 | ||
2539 | union { | ||
2540 | struct { | ||
2541 | uint32_t word10; | ||
2542 | #define lpfc_mbx_get_prof_cfg_prof_id_SHIFT 0 | ||
2543 | #define lpfc_mbx_get_prof_cfg_prof_id_MASK 0x000000ff | ||
2544 | #define lpfc_mbx_get_prof_cfg_prof_id_WORD word10 | ||
2545 | #define lpfc_mbx_get_prof_cfg_prof_tp_SHIFT 8 | ||
2546 | #define lpfc_mbx_get_prof_cfg_prof_tp_MASK 0x00000003 | ||
2547 | #define lpfc_mbx_get_prof_cfg_prof_tp_WORD word10 | ||
2548 | } request; | ||
2549 | struct { | ||
2550 | struct lpfc_prof_cfg prof_cfg; | ||
2551 | } response; | ||
2552 | } u; | ||
2553 | }; | ||
2554 | |||
2201 | /* Mailbox Completion Queue Error Messages */ | 2555 | /* Mailbox Completion Queue Error Messages */ |
2202 | #define MB_CQE_STATUS_SUCCESS 0x0 | 2556 | #define MB_CQE_STATUS_SUCCESS 0x0 |
2203 | #define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES 0x1 | 2557 | #define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES 0x1 |
@@ -2206,6 +2560,29 @@ struct lpfc_mbx_get_sli4_parameters { | |||
2206 | #define MB_CEQ_STATUS_QUEUE_FLUSHING 0x4 | 2560 | #define MB_CEQ_STATUS_QUEUE_FLUSHING 0x4 |
2207 | #define MB_CQE_STATUS_DMA_FAILED 0x5 | 2561 | #define MB_CQE_STATUS_DMA_FAILED 0x5 |
2208 | 2562 | ||
2563 | #define LPFC_MBX_WR_CONFIG_MAX_BDE 8 | ||
2564 | struct lpfc_mbx_wr_object { | ||
2565 | struct mbox_header header; | ||
2566 | union { | ||
2567 | struct { | ||
2568 | uint32_t word4; | ||
2569 | #define lpfc_wr_object_eof_SHIFT 31 | ||
2570 | #define lpfc_wr_object_eof_MASK 0x00000001 | ||
2571 | #define lpfc_wr_object_eof_WORD word4 | ||
2572 | #define lpfc_wr_object_write_length_SHIFT 0 | ||
2573 | #define lpfc_wr_object_write_length_MASK 0x00FFFFFF | ||
2574 | #define lpfc_wr_object_write_length_WORD word4 | ||
2575 | uint32_t write_offset; | ||
2576 | uint32_t object_name[26]; | ||
2577 | uint32_t bde_count; | ||
2578 | struct ulp_bde64 bde[LPFC_MBX_WR_CONFIG_MAX_BDE]; | ||
2579 | } request; | ||
2580 | struct { | ||
2581 | uint32_t actual_write_length; | ||
2582 | } response; | ||
2583 | } u; | ||
2584 | }; | ||
2585 | |||
2209 | /* mailbox queue entry structure */ | 2586 | /* mailbox queue entry structure */ |
2210 | struct lpfc_mqe { | 2587 | struct lpfc_mqe { |
2211 | uint32_t word0; | 2588 | uint32_t word0; |
@@ -2241,6 +2618,9 @@ struct lpfc_mqe { | |||
2241 | struct lpfc_mbx_cq_destroy cq_destroy; | 2618 | struct lpfc_mbx_cq_destroy cq_destroy; |
2242 | struct lpfc_mbx_wq_destroy wq_destroy; | 2619 | struct lpfc_mbx_wq_destroy wq_destroy; |
2243 | struct lpfc_mbx_rq_destroy rq_destroy; | 2620 | struct lpfc_mbx_rq_destroy rq_destroy; |
2621 | struct lpfc_mbx_get_rsrc_extent_info rsrc_extent_info; | ||
2622 | struct lpfc_mbx_alloc_rsrc_extents alloc_rsrc_extents; | ||
2623 | struct lpfc_mbx_dealloc_rsrc_extents dealloc_rsrc_extents; | ||
2244 | struct lpfc_mbx_post_sgl_pages post_sgl_pages; | 2624 | struct lpfc_mbx_post_sgl_pages post_sgl_pages; |
2245 | struct lpfc_mbx_nembed_cmd nembed_cmd; | 2625 | struct lpfc_mbx_nembed_cmd nembed_cmd; |
2246 | struct lpfc_mbx_read_rev read_rev; | 2626 | struct lpfc_mbx_read_rev read_rev; |
@@ -2252,7 +2632,13 @@ struct lpfc_mqe { | |||
2252 | struct lpfc_mbx_supp_pages supp_pages; | 2632 | struct lpfc_mbx_supp_pages supp_pages; |
2253 | struct lpfc_mbx_pc_sli4_params sli4_params; | 2633 | struct lpfc_mbx_pc_sli4_params sli4_params; |
2254 | struct lpfc_mbx_get_sli4_parameters get_sli4_parameters; | 2634 | struct lpfc_mbx_get_sli4_parameters get_sli4_parameters; |
2635 | struct lpfc_mbx_set_link_diag_state link_diag_state; | ||
2636 | struct lpfc_mbx_set_link_diag_loopback link_diag_loopback; | ||
2637 | struct lpfc_mbx_run_link_diag_test link_diag_test; | ||
2638 | struct lpfc_mbx_get_func_cfg get_func_cfg; | ||
2639 | struct lpfc_mbx_get_prof_cfg get_prof_cfg; | ||
2255 | struct lpfc_mbx_nop nop; | 2640 | struct lpfc_mbx_nop nop; |
2641 | struct lpfc_mbx_wr_object wr_object; | ||
2256 | } un; | 2642 | } un; |
2257 | }; | 2643 | }; |
2258 | 2644 | ||
@@ -2458,7 +2844,7 @@ struct lpfc_bmbx_create { | |||
2458 | #define SGL_ALIGN_SZ 64 | 2844 | #define SGL_ALIGN_SZ 64 |
2459 | #define SGL_PAGE_SIZE 4096 | 2845 | #define SGL_PAGE_SIZE 4096 |
2460 | /* align SGL addr on a size boundary - adjust address up */ | 2846 | /* align SGL addr on a size boundary - adjust address up */ |
2461 | #define NO_XRI ((uint16_t)-1) | 2847 | #define NO_XRI 0xffff |
2462 | 2848 | ||
2463 | struct wqe_common { | 2849 | struct wqe_common { |
2464 | uint32_t word6; | 2850 | uint32_t word6; |
@@ -2798,9 +3184,28 @@ union lpfc_wqe { | |||
2798 | struct gen_req64_wqe gen_req; | 3184 | struct gen_req64_wqe gen_req; |
2799 | }; | 3185 | }; |
2800 | 3186 | ||
3187 | #define LPFC_GROUP_OJECT_MAGIC_NUM 0xfeaa0001 | ||
3188 | #define LPFC_FILE_TYPE_GROUP 0xf7 | ||
3189 | #define LPFC_FILE_ID_GROUP 0xa2 | ||
3190 | struct lpfc_grp_hdr { | ||
3191 | uint32_t size; | ||
3192 | uint32_t magic_number; | ||
3193 | uint32_t word2; | ||
3194 | #define lpfc_grp_hdr_file_type_SHIFT 24 | ||
3195 | #define lpfc_grp_hdr_file_type_MASK 0x000000FF | ||
3196 | #define lpfc_grp_hdr_file_type_WORD word2 | ||
3197 | #define lpfc_grp_hdr_id_SHIFT 16 | ||
3198 | #define lpfc_grp_hdr_id_MASK 0x000000FF | ||
3199 | #define lpfc_grp_hdr_id_WORD word2 | ||
3200 | uint8_t rev_name[128]; | ||
3201 | }; | ||
3202 | |||
2801 | #define FCP_COMMAND 0x0 | 3203 | #define FCP_COMMAND 0x0 |
2802 | #define FCP_COMMAND_DATA_OUT 0x1 | 3204 | #define FCP_COMMAND_DATA_OUT 0x1 |
2803 | #define ELS_COMMAND_NON_FIP 0xC | 3205 | #define ELS_COMMAND_NON_FIP 0xC |
2804 | #define ELS_COMMAND_FIP 0xD | 3206 | #define ELS_COMMAND_FIP 0xD |
2805 | #define OTHER_COMMAND 0x8 | 3207 | #define OTHER_COMMAND 0x8 |
2806 | 3208 | ||
3209 | #define LPFC_FW_DUMP 1 | ||
3210 | #define LPFC_FW_RESET 2 | ||
3211 | #define LPFC_DV_RESET 3 | ||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 7dda036a1af3..148b98ddbb1d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/ctype.h> | 30 | #include <linux/ctype.h> |
31 | #include <linux/aer.h> | 31 | #include <linux/aer.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/firmware.h> | ||
33 | 34 | ||
34 | #include <scsi/scsi.h> | 35 | #include <scsi/scsi.h> |
35 | #include <scsi/scsi_device.h> | 36 | #include <scsi/scsi_device.h> |
@@ -211,7 +212,6 @@ lpfc_config_port_prep(struct lpfc_hba *phba) | |||
211 | lpfc_vpd_data = kmalloc(DMP_VPD_SIZE, GFP_KERNEL); | 212 | lpfc_vpd_data = kmalloc(DMP_VPD_SIZE, GFP_KERNEL); |
212 | if (!lpfc_vpd_data) | 213 | if (!lpfc_vpd_data) |
213 | goto out_free_mbox; | 214 | goto out_free_mbox; |
214 | |||
215 | do { | 215 | do { |
216 | lpfc_dump_mem(phba, pmb, offset, DMP_REGION_VPD); | 216 | lpfc_dump_mem(phba, pmb, offset, DMP_REGION_VPD); |
217 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); | 217 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); |
@@ -309,6 +309,45 @@ lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | |||
309 | } | 309 | } |
310 | 310 | ||
311 | /** | 311 | /** |
312 | * lpfc_update_vport_wwn - Updates the fc_nodename, fc_portname, | ||
313 | * cfg_soft_wwnn, cfg_soft_wwpn | ||
314 | * @vport: pointer to lpfc vport data structure. | ||
315 | * | ||
316 | * | ||
317 | * Return codes | ||
318 | * None. | ||
319 | **/ | ||
320 | void | ||
321 | lpfc_update_vport_wwn(struct lpfc_vport *vport) | ||
322 | { | ||
323 | /* If the soft name exists then update it using the service params */ | ||
324 | if (vport->phba->cfg_soft_wwnn) | ||
325 | u64_to_wwn(vport->phba->cfg_soft_wwnn, | ||
326 | vport->fc_sparam.nodeName.u.wwn); | ||
327 | if (vport->phba->cfg_soft_wwpn) | ||
328 | u64_to_wwn(vport->phba->cfg_soft_wwpn, | ||
329 | vport->fc_sparam.portName.u.wwn); | ||
330 | |||
331 | /* | ||
332 | * If the name is empty or there exists a soft name | ||
333 | * then copy the service params name, otherwise use the fc name | ||
334 | */ | ||
335 | if (vport->fc_nodename.u.wwn[0] == 0 || vport->phba->cfg_soft_wwnn) | ||
336 | memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName, | ||
337 | sizeof(struct lpfc_name)); | ||
338 | else | ||
339 | memcpy(&vport->fc_sparam.nodeName, &vport->fc_nodename, | ||
340 | sizeof(struct lpfc_name)); | ||
341 | |||
342 | if (vport->fc_portname.u.wwn[0] == 0 || vport->phba->cfg_soft_wwpn) | ||
343 | memcpy(&vport->fc_portname, &vport->fc_sparam.portName, | ||
344 | sizeof(struct lpfc_name)); | ||
345 | else | ||
346 | memcpy(&vport->fc_sparam.portName, &vport->fc_portname, | ||
347 | sizeof(struct lpfc_name)); | ||
348 | } | ||
349 | |||
350 | /** | ||
312 | * lpfc_config_port_post - Perform lpfc initialization after config port | 351 | * lpfc_config_port_post - Perform lpfc initialization after config port |
313 | * @phba: pointer to lpfc hba data structure. | 352 | * @phba: pointer to lpfc hba data structure. |
314 | * | 353 | * |
@@ -377,17 +416,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
377 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 416 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
378 | kfree(mp); | 417 | kfree(mp); |
379 | pmb->context1 = NULL; | 418 | pmb->context1 = NULL; |
380 | 419 | lpfc_update_vport_wwn(vport); | |
381 | if (phba->cfg_soft_wwnn) | ||
382 | u64_to_wwn(phba->cfg_soft_wwnn, | ||
383 | vport->fc_sparam.nodeName.u.wwn); | ||
384 | if (phba->cfg_soft_wwpn) | ||
385 | u64_to_wwn(phba->cfg_soft_wwpn, | ||
386 | vport->fc_sparam.portName.u.wwn); | ||
387 | memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName, | ||
388 | sizeof (struct lpfc_name)); | ||
389 | memcpy(&vport->fc_portname, &vport->fc_sparam.portName, | ||
390 | sizeof (struct lpfc_name)); | ||
391 | 420 | ||
392 | /* Update the fc_host data structures with new wwn. */ | 421 | /* Update the fc_host data structures with new wwn. */ |
393 | fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn); | 422 | fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn); |
@@ -573,7 +602,6 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
573 | /* Clear all pending interrupts */ | 602 | /* Clear all pending interrupts */ |
574 | writel(0xffffffff, phba->HAregaddr); | 603 | writel(0xffffffff, phba->HAregaddr); |
575 | readl(phba->HAregaddr); /* flush */ | 604 | readl(phba->HAregaddr); /* flush */ |
576 | |||
577 | phba->link_state = LPFC_HBA_ERROR; | 605 | phba->link_state = LPFC_HBA_ERROR; |
578 | if (rc != MBX_BUSY) | 606 | if (rc != MBX_BUSY) |
579 | mempool_free(pmb, phba->mbox_mem_pool); | 607 | mempool_free(pmb, phba->mbox_mem_pool); |
@@ -1755,7 +1783,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) | |||
1755 | && descp && descp[0] != '\0') | 1783 | && descp && descp[0] != '\0') |
1756 | return; | 1784 | return; |
1757 | 1785 | ||
1758 | if (phba->lmt & LMT_10Gb) | 1786 | if (phba->lmt & LMT_16Gb) |
1787 | max_speed = 16; | ||
1788 | else if (phba->lmt & LMT_10Gb) | ||
1759 | max_speed = 10; | 1789 | max_speed = 10; |
1760 | else if (phba->lmt & LMT_8Gb) | 1790 | else if (phba->lmt & LMT_8Gb) |
1761 | max_speed = 8; | 1791 | max_speed = 8; |
@@ -1922,12 +1952,13 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) | |||
1922 | "Fibre Channel Adapter"}; | 1952 | "Fibre Channel Adapter"}; |
1923 | break; | 1953 | break; |
1924 | case PCI_DEVICE_ID_LANCER_FC: | 1954 | case PCI_DEVICE_ID_LANCER_FC: |
1925 | oneConnect = 1; | 1955 | case PCI_DEVICE_ID_LANCER_FC_VF: |
1926 | m = (typeof(m)){"Undefined", "PCIe", "Fibre Channel Adapter"}; | 1956 | m = (typeof(m)){"LPe16000", "PCIe", "Fibre Channel Adapter"}; |
1927 | break; | 1957 | break; |
1928 | case PCI_DEVICE_ID_LANCER_FCOE: | 1958 | case PCI_DEVICE_ID_LANCER_FCOE: |
1959 | case PCI_DEVICE_ID_LANCER_FCOE_VF: | ||
1929 | oneConnect = 1; | 1960 | oneConnect = 1; |
1930 | m = (typeof(m)){"Undefined", "PCIe", "FCoE"}; | 1961 | m = (typeof(m)){"OCe50100", "PCIe", "FCoE"}; |
1931 | break; | 1962 | break; |
1932 | default: | 1963 | default: |
1933 | m = (typeof(m)){"Unknown", "", ""}; | 1964 | m = (typeof(m)){"Unknown", "", ""}; |
@@ -1936,7 +1967,8 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) | |||
1936 | 1967 | ||
1937 | if (mdp && mdp[0] == '\0') | 1968 | if (mdp && mdp[0] == '\0') |
1938 | snprintf(mdp, 79,"%s", m.name); | 1969 | snprintf(mdp, 79,"%s", m.name); |
1939 | /* oneConnect hba requires special processing, they are all initiators | 1970 | /* |
1971 | * oneConnect hba requires special processing, they are all initiators | ||
1940 | * and we put the port number on the end | 1972 | * and we put the port number on the end |
1941 | */ | 1973 | */ |
1942 | if (descp && descp[0] == '\0') { | 1974 | if (descp && descp[0] == '\0') { |
@@ -2656,6 +2688,7 @@ lpfc_scsi_free(struct lpfc_hba *phba) | |||
2656 | kfree(io); | 2688 | kfree(io); |
2657 | phba->total_iocbq_bufs--; | 2689 | phba->total_iocbq_bufs--; |
2658 | } | 2690 | } |
2691 | |||
2659 | spin_unlock_irq(&phba->hbalock); | 2692 | spin_unlock_irq(&phba->hbalock); |
2660 | return 0; | 2693 | return 0; |
2661 | } | 2694 | } |
@@ -3612,6 +3645,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, | |||
3612 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, | 3645 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, |
3613 | "2718 Clear Virtual Link Received for VPI 0x%x" | 3646 | "2718 Clear Virtual Link Received for VPI 0x%x" |
3614 | " tag 0x%x\n", acqe_fip->index, acqe_fip->event_tag); | 3647 | " tag 0x%x\n", acqe_fip->index, acqe_fip->event_tag); |
3648 | |||
3615 | vport = lpfc_find_vport_by_vpid(phba, | 3649 | vport = lpfc_find_vport_by_vpid(phba, |
3616 | acqe_fip->index - phba->vpi_base); | 3650 | acqe_fip->index - phba->vpi_base); |
3617 | ndlp = lpfc_sli4_perform_vport_cvl(vport); | 3651 | ndlp = lpfc_sli4_perform_vport_cvl(vport); |
@@ -3935,6 +3969,10 @@ lpfc_enable_pci_dev(struct lpfc_hba *phba) | |||
3935 | pci_try_set_mwi(pdev); | 3969 | pci_try_set_mwi(pdev); |
3936 | pci_save_state(pdev); | 3970 | pci_save_state(pdev); |
3937 | 3971 | ||
3972 | /* PCIe EEH recovery on powerpc platforms needs fundamental reset */ | ||
3973 | if (pci_find_capability(pdev, PCI_CAP_ID_EXP)) | ||
3974 | pdev->needs_freset = 1; | ||
3975 | |||
3938 | return 0; | 3976 | return 0; |
3939 | 3977 | ||
3940 | out_disable_device: | 3978 | out_disable_device: |
@@ -3997,6 +4035,36 @@ lpfc_reset_hba(struct lpfc_hba *phba) | |||
3997 | } | 4035 | } |
3998 | 4036 | ||
3999 | /** | 4037 | /** |
4038 | * lpfc_sli_probe_sriov_nr_virtfn - Enable a number of sr-iov virtual functions | ||
4039 | * @phba: pointer to lpfc hba data structure. | ||
4040 | * @nr_vfn: number of virtual functions to be enabled. | ||
4041 | * | ||
4042 | * This function enables the PCI SR-IOV virtual functions to a physical | ||
4043 | * function. It invokes the PCI SR-IOV api with the @nr_vfn provided to | ||
4044 | * enable the number of virtual functions to the physical function. As | ||
4045 | * not all devices support SR-IOV, the return code from the pci_enable_sriov() | ||
4046 | * API call does not considered as an error condition for most of the device. | ||
4047 | **/ | ||
4048 | int | ||
4049 | lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *phba, int nr_vfn) | ||
4050 | { | ||
4051 | struct pci_dev *pdev = phba->pcidev; | ||
4052 | int rc; | ||
4053 | |||
4054 | rc = pci_enable_sriov(pdev, nr_vfn); | ||
4055 | if (rc) { | ||
4056 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
4057 | "2806 Failed to enable sriov on this device " | ||
4058 | "with vfn number nr_vf:%d, rc:%d\n", | ||
4059 | nr_vfn, rc); | ||
4060 | } else | ||
4061 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
4062 | "2807 Successful enable sriov on this device " | ||
4063 | "with vfn number nr_vf:%d\n", nr_vfn); | ||
4064 | return rc; | ||
4065 | } | ||
4066 | |||
4067 | /** | ||
4000 | * lpfc_sli_driver_resource_setup - Setup driver internal resources for SLI3 dev. | 4068 | * lpfc_sli_driver_resource_setup - Setup driver internal resources for SLI3 dev. |
4001 | * @phba: pointer to lpfc hba data structure. | 4069 | * @phba: pointer to lpfc hba data structure. |
4002 | * | 4070 | * |
@@ -4011,6 +4079,7 @@ static int | |||
4011 | lpfc_sli_driver_resource_setup(struct lpfc_hba *phba) | 4079 | lpfc_sli_driver_resource_setup(struct lpfc_hba *phba) |
4012 | { | 4080 | { |
4013 | struct lpfc_sli *psli; | 4081 | struct lpfc_sli *psli; |
4082 | int rc; | ||
4014 | 4083 | ||
4015 | /* | 4084 | /* |
4016 | * Initialize timers used by driver | 4085 | * Initialize timers used by driver |
@@ -4085,6 +4154,23 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba) | |||
4085 | if (lpfc_mem_alloc(phba, BPL_ALIGN_SZ)) | 4154 | if (lpfc_mem_alloc(phba, BPL_ALIGN_SZ)) |
4086 | return -ENOMEM; | 4155 | return -ENOMEM; |
4087 | 4156 | ||
4157 | /* | ||
4158 | * Enable sr-iov virtual functions if supported and configured | ||
4159 | * through the module parameter. | ||
4160 | */ | ||
4161 | if (phba->cfg_sriov_nr_virtfn > 0) { | ||
4162 | rc = lpfc_sli_probe_sriov_nr_virtfn(phba, | ||
4163 | phba->cfg_sriov_nr_virtfn); | ||
4164 | if (rc) { | ||
4165 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
4166 | "2808 Requested number of SR-IOV " | ||
4167 | "virtual functions (%d) is not " | ||
4168 | "supported\n", | ||
4169 | phba->cfg_sriov_nr_virtfn); | ||
4170 | phba->cfg_sriov_nr_virtfn = 0; | ||
4171 | } | ||
4172 | } | ||
4173 | |||
4088 | return 0; | 4174 | return 0; |
4089 | } | 4175 | } |
4090 | 4176 | ||
@@ -4161,6 +4247,14 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
4161 | phba->fcf.redisc_wait.data = (unsigned long)phba; | 4247 | phba->fcf.redisc_wait.data = (unsigned long)phba; |
4162 | 4248 | ||
4163 | /* | 4249 | /* |
4250 | * Control structure for handling external multi-buffer mailbox | ||
4251 | * command pass-through. | ||
4252 | */ | ||
4253 | memset((uint8_t *)&phba->mbox_ext_buf_ctx, 0, | ||
4254 | sizeof(struct lpfc_mbox_ext_buf_ctx)); | ||
4255 | INIT_LIST_HEAD(&phba->mbox_ext_buf_ctx.ext_dmabuf_list); | ||
4256 | |||
4257 | /* | ||
4164 | * We need to do a READ_CONFIG mailbox command here before | 4258 | * We need to do a READ_CONFIG mailbox command here before |
4165 | * calling lpfc_get_cfgparam. For VFs this will report the | 4259 | * calling lpfc_get_cfgparam. For VFs this will report the |
4166 | * MAX_XRI, MAX_VPI, MAX_RPI, MAX_IOCB, and MAX_VFI settings. | 4260 | * MAX_XRI, MAX_VPI, MAX_RPI, MAX_IOCB, and MAX_VFI settings. |
@@ -4233,7 +4327,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
4233 | spin_lock_init(&phba->sli4_hba.abts_sgl_list_lock); | 4327 | spin_lock_init(&phba->sli4_hba.abts_sgl_list_lock); |
4234 | 4328 | ||
4235 | /* | 4329 | /* |
4236 | * Initialize dirver internal slow-path work queues | 4330 | * Initialize driver internal slow-path work queues |
4237 | */ | 4331 | */ |
4238 | 4332 | ||
4239 | /* Driver internel slow-path CQ Event pool */ | 4333 | /* Driver internel slow-path CQ Event pool */ |
@@ -4249,6 +4343,12 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
4249 | /* Receive queue CQ Event work queue list */ | 4343 | /* Receive queue CQ Event work queue list */ |
4250 | INIT_LIST_HEAD(&phba->sli4_hba.sp_unsol_work_queue); | 4344 | INIT_LIST_HEAD(&phba->sli4_hba.sp_unsol_work_queue); |
4251 | 4345 | ||
4346 | /* Initialize extent block lists. */ | ||
4347 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_rpi_blk_list); | ||
4348 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_xri_blk_list); | ||
4349 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_vfi_blk_list); | ||
4350 | INIT_LIST_HEAD(&phba->lpfc_vpi_blk_list); | ||
4351 | |||
4252 | /* Initialize the driver internal SLI layer lists. */ | 4352 | /* Initialize the driver internal SLI layer lists. */ |
4253 | lpfc_sli_setup(phba); | 4353 | lpfc_sli_setup(phba); |
4254 | lpfc_sli_queue_setup(phba); | 4354 | lpfc_sli_queue_setup(phba); |
@@ -4323,9 +4423,19 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
4323 | } | 4423 | } |
4324 | /* | 4424 | /* |
4325 | * Get sli4 parameters that override parameters from Port capabilities. | 4425 | * Get sli4 parameters that override parameters from Port capabilities. |
4326 | * If this call fails it is not a critical error so continue loading. | 4426 | * If this call fails, it isn't critical unless the SLI4 parameters come |
4427 | * back in conflict. | ||
4327 | */ | 4428 | */ |
4328 | lpfc_get_sli4_parameters(phba, mboxq); | 4429 | rc = lpfc_get_sli4_parameters(phba, mboxq); |
4430 | if (rc) { | ||
4431 | if (phba->sli4_hba.extents_in_use && | ||
4432 | phba->sli4_hba.rpi_hdrs_in_use) { | ||
4433 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
4434 | "2999 Unsupported SLI4 Parameters " | ||
4435 | "Extents and RPI headers enabled.\n"); | ||
4436 | goto out_free_bsmbx; | ||
4437 | } | ||
4438 | } | ||
4329 | mempool_free(mboxq, phba->mbox_mem_pool); | 4439 | mempool_free(mboxq, phba->mbox_mem_pool); |
4330 | /* Create all the SLI4 queues */ | 4440 | /* Create all the SLI4 queues */ |
4331 | rc = lpfc_sli4_queue_create(phba); | 4441 | rc = lpfc_sli4_queue_create(phba); |
@@ -4350,7 +4460,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
4350 | "1430 Failed to initialize sgl list.\n"); | 4460 | "1430 Failed to initialize sgl list.\n"); |
4351 | goto out_free_sgl_list; | 4461 | goto out_free_sgl_list; |
4352 | } | 4462 | } |
4353 | |||
4354 | rc = lpfc_sli4_init_rpi_hdrs(phba); | 4463 | rc = lpfc_sli4_init_rpi_hdrs(phba); |
4355 | if (rc) { | 4464 | if (rc) { |
4356 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 4465 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
@@ -4366,6 +4475,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
4366 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 4475 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
4367 | "2759 Failed allocate memory for FCF round " | 4476 | "2759 Failed allocate memory for FCF round " |
4368 | "robin failover bmask\n"); | 4477 | "robin failover bmask\n"); |
4478 | rc = -ENOMEM; | ||
4369 | goto out_remove_rpi_hdrs; | 4479 | goto out_remove_rpi_hdrs; |
4370 | } | 4480 | } |
4371 | 4481 | ||
@@ -4375,6 +4485,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
4375 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 4485 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
4376 | "2572 Failed allocate memory for fast-path " | 4486 | "2572 Failed allocate memory for fast-path " |
4377 | "per-EQ handle array\n"); | 4487 | "per-EQ handle array\n"); |
4488 | rc = -ENOMEM; | ||
4378 | goto out_free_fcf_rr_bmask; | 4489 | goto out_free_fcf_rr_bmask; |
4379 | } | 4490 | } |
4380 | 4491 | ||
@@ -4384,9 +4495,27 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
4384 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 4495 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
4385 | "2573 Failed allocate memory for msi-x " | 4496 | "2573 Failed allocate memory for msi-x " |
4386 | "interrupt vector entries\n"); | 4497 | "interrupt vector entries\n"); |
4498 | rc = -ENOMEM; | ||
4387 | goto out_free_fcp_eq_hdl; | 4499 | goto out_free_fcp_eq_hdl; |
4388 | } | 4500 | } |
4389 | 4501 | ||
4502 | /* | ||
4503 | * Enable sr-iov virtual functions if supported and configured | ||
4504 | * through the module parameter. | ||
4505 | */ | ||
4506 | if (phba->cfg_sriov_nr_virtfn > 0) { | ||
4507 | rc = lpfc_sli_probe_sriov_nr_virtfn(phba, | ||
4508 | phba->cfg_sriov_nr_virtfn); | ||
4509 | if (rc) { | ||
4510 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
4511 | "3020 Requested number of SR-IOV " | ||
4512 | "virtual functions (%d) is not " | ||
4513 | "supported\n", | ||
4514 | phba->cfg_sriov_nr_virtfn); | ||
4515 | phba->cfg_sriov_nr_virtfn = 0; | ||
4516 | } | ||
4517 | } | ||
4518 | |||
4390 | return rc; | 4519 | return rc; |
4391 | 4520 | ||
4392 | out_free_fcp_eq_hdl: | 4521 | out_free_fcp_eq_hdl: |
@@ -4449,6 +4578,9 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba) | |||
4449 | lpfc_sli4_cq_event_release_all(phba); | 4578 | lpfc_sli4_cq_event_release_all(phba); |
4450 | lpfc_sli4_cq_event_pool_destroy(phba); | 4579 | lpfc_sli4_cq_event_pool_destroy(phba); |
4451 | 4580 | ||
4581 | /* Release resource identifiers. */ | ||
4582 | lpfc_sli4_dealloc_resource_identifiers(phba); | ||
4583 | |||
4452 | /* Free the bsmbx region. */ | 4584 | /* Free the bsmbx region. */ |
4453 | lpfc_destroy_bootstrap_mbox(phba); | 4585 | lpfc_destroy_bootstrap_mbox(phba); |
4454 | 4586 | ||
@@ -4649,6 +4781,7 @@ lpfc_init_iocb_list(struct lpfc_hba *phba, int iocb_count) | |||
4649 | "Unloading driver.\n", __func__); | 4781 | "Unloading driver.\n", __func__); |
4650 | goto out_free_iocbq; | 4782 | goto out_free_iocbq; |
4651 | } | 4783 | } |
4784 | iocbq_entry->sli4_lxritag = NO_XRI; | ||
4652 | iocbq_entry->sli4_xritag = NO_XRI; | 4785 | iocbq_entry->sli4_xritag = NO_XRI; |
4653 | 4786 | ||
4654 | spin_lock_irq(&phba->hbalock); | 4787 | spin_lock_irq(&phba->hbalock); |
@@ -4746,7 +4879,7 @@ lpfc_init_sgl_list(struct lpfc_hba *phba) | |||
4746 | 4879 | ||
4747 | els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba); | 4880 | els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba); |
4748 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | 4881 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, |
4749 | "2400 lpfc_init_sgl_list els %d.\n", | 4882 | "2400 ELS XRI count %d.\n", |
4750 | els_xri_cnt); | 4883 | els_xri_cnt); |
4751 | /* Initialize and populate the sglq list per host/VF. */ | 4884 | /* Initialize and populate the sglq list per host/VF. */ |
4752 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_sgl_list); | 4885 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_sgl_list); |
@@ -4779,7 +4912,6 @@ lpfc_init_sgl_list(struct lpfc_hba *phba) | |||
4779 | phba->sli4_hba.scsi_xri_max = | 4912 | phba->sli4_hba.scsi_xri_max = |
4780 | phba->sli4_hba.max_cfg_param.max_xri - els_xri_cnt; | 4913 | phba->sli4_hba.max_cfg_param.max_xri - els_xri_cnt; |
4781 | phba->sli4_hba.scsi_xri_cnt = 0; | 4914 | phba->sli4_hba.scsi_xri_cnt = 0; |
4782 | |||
4783 | phba->sli4_hba.lpfc_scsi_psb_array = | 4915 | phba->sli4_hba.lpfc_scsi_psb_array = |
4784 | kzalloc((sizeof(struct lpfc_scsi_buf *) * | 4916 | kzalloc((sizeof(struct lpfc_scsi_buf *) * |
4785 | phba->sli4_hba.scsi_xri_max), GFP_KERNEL); | 4917 | phba->sli4_hba.scsi_xri_max), GFP_KERNEL); |
@@ -4802,13 +4934,6 @@ lpfc_init_sgl_list(struct lpfc_hba *phba) | |||
4802 | goto out_free_mem; | 4934 | goto out_free_mem; |
4803 | } | 4935 | } |
4804 | 4936 | ||
4805 | sglq_entry->sli4_xritag = lpfc_sli4_next_xritag(phba); | ||
4806 | if (sglq_entry->sli4_xritag == NO_XRI) { | ||
4807 | kfree(sglq_entry); | ||
4808 | printk(KERN_ERR "%s: failed to allocate XRI.\n" | ||
4809 | "Unloading driver.\n", __func__); | ||
4810 | goto out_free_mem; | ||
4811 | } | ||
4812 | sglq_entry->buff_type = GEN_BUFF_TYPE; | 4937 | sglq_entry->buff_type = GEN_BUFF_TYPE; |
4813 | sglq_entry->virt = lpfc_mbuf_alloc(phba, 0, &sglq_entry->phys); | 4938 | sglq_entry->virt = lpfc_mbuf_alloc(phba, 0, &sglq_entry->phys); |
4814 | if (sglq_entry->virt == NULL) { | 4939 | if (sglq_entry->virt == NULL) { |
@@ -4857,24 +4982,20 @@ int | |||
4857 | lpfc_sli4_init_rpi_hdrs(struct lpfc_hba *phba) | 4982 | lpfc_sli4_init_rpi_hdrs(struct lpfc_hba *phba) |
4858 | { | 4983 | { |
4859 | int rc = 0; | 4984 | int rc = 0; |
4860 | int longs; | ||
4861 | uint16_t rpi_count; | ||
4862 | struct lpfc_rpi_hdr *rpi_hdr; | 4985 | struct lpfc_rpi_hdr *rpi_hdr; |
4863 | 4986 | ||
4864 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_rpi_hdr_list); | 4987 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_rpi_hdr_list); |
4865 | |||
4866 | /* | 4988 | /* |
4867 | * Provision an rpi bitmask range for discovery. The total count | 4989 | * If the SLI4 port supports extents, posting the rpi header isn't |
4868 | * is the difference between max and base + 1. | 4990 | * required. Set the expected maximum count and let the actual value |
4991 | * get set when extents are fully allocated. | ||
4869 | */ | 4992 | */ |
4870 | rpi_count = phba->sli4_hba.max_cfg_param.rpi_base + | 4993 | if (!phba->sli4_hba.rpi_hdrs_in_use) { |
4871 | phba->sli4_hba.max_cfg_param.max_rpi - 1; | 4994 | phba->sli4_hba.next_rpi = phba->sli4_hba.max_cfg_param.max_rpi; |
4872 | 4995 | return rc; | |
4873 | longs = ((rpi_count) + BITS_PER_LONG - 1) / BITS_PER_LONG; | 4996 | } |
4874 | phba->sli4_hba.rpi_bmask = kzalloc(longs * sizeof(unsigned long), | 4997 | if (phba->sli4_hba.extents_in_use) |
4875 | GFP_KERNEL); | 4998 | return -EIO; |
4876 | if (!phba->sli4_hba.rpi_bmask) | ||
4877 | return -ENOMEM; | ||
4878 | 4999 | ||
4879 | rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); | 5000 | rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); |
4880 | if (!rpi_hdr) { | 5001 | if (!rpi_hdr) { |
@@ -4908,11 +5029,28 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
4908 | struct lpfc_rpi_hdr *rpi_hdr; | 5029 | struct lpfc_rpi_hdr *rpi_hdr; |
4909 | uint32_t rpi_count; | 5030 | uint32_t rpi_count; |
4910 | 5031 | ||
5032 | /* | ||
5033 | * If the SLI4 port supports extents, posting the rpi header isn't | ||
5034 | * required. Set the expected maximum count and let the actual value | ||
5035 | * get set when extents are fully allocated. | ||
5036 | */ | ||
5037 | if (!phba->sli4_hba.rpi_hdrs_in_use) | ||
5038 | return NULL; | ||
5039 | if (phba->sli4_hba.extents_in_use) | ||
5040 | return NULL; | ||
5041 | |||
5042 | /* The limit on the logical index is just the max_rpi count. */ | ||
4911 | rpi_limit = phba->sli4_hba.max_cfg_param.rpi_base + | 5043 | rpi_limit = phba->sli4_hba.max_cfg_param.rpi_base + |
4912 | phba->sli4_hba.max_cfg_param.max_rpi - 1; | 5044 | phba->sli4_hba.max_cfg_param.max_rpi - 1; |
4913 | 5045 | ||
4914 | spin_lock_irq(&phba->hbalock); | 5046 | spin_lock_irq(&phba->hbalock); |
4915 | curr_rpi_range = phba->sli4_hba.next_rpi; | 5047 | /* |
5048 | * Establish the starting RPI in this header block. The starting | ||
5049 | * rpi is normalized to a zero base because the physical rpi is | ||
5050 | * port based. | ||
5051 | */ | ||
5052 | curr_rpi_range = phba->sli4_hba.next_rpi - | ||
5053 | phba->sli4_hba.max_cfg_param.rpi_base; | ||
4916 | spin_unlock_irq(&phba->hbalock); | 5054 | spin_unlock_irq(&phba->hbalock); |
4917 | 5055 | ||
4918 | /* | 5056 | /* |
@@ -4925,6 +5063,8 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
4925 | else | 5063 | else |
4926 | rpi_count = LPFC_RPI_HDR_COUNT; | 5064 | rpi_count = LPFC_RPI_HDR_COUNT; |
4927 | 5065 | ||
5066 | if (!rpi_count) | ||
5067 | return NULL; | ||
4928 | /* | 5068 | /* |
4929 | * First allocate the protocol header region for the port. The | 5069 | * First allocate the protocol header region for the port. The |
4930 | * port expects a 4KB DMA-mapped memory region that is 4K aligned. | 5070 | * port expects a 4KB DMA-mapped memory region that is 4K aligned. |
@@ -4957,12 +5097,14 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
4957 | rpi_hdr->len = LPFC_HDR_TEMPLATE_SIZE; | 5097 | rpi_hdr->len = LPFC_HDR_TEMPLATE_SIZE; |
4958 | rpi_hdr->page_count = 1; | 5098 | rpi_hdr->page_count = 1; |
4959 | spin_lock_irq(&phba->hbalock); | 5099 | spin_lock_irq(&phba->hbalock); |
4960 | rpi_hdr->start_rpi = phba->sli4_hba.next_rpi; | 5100 | |
5101 | /* The rpi_hdr stores the logical index only. */ | ||
5102 | rpi_hdr->start_rpi = curr_rpi_range; | ||
4961 | list_add_tail(&rpi_hdr->list, &phba->sli4_hba.lpfc_rpi_hdr_list); | 5103 | list_add_tail(&rpi_hdr->list, &phba->sli4_hba.lpfc_rpi_hdr_list); |
4962 | 5104 | ||
4963 | /* | 5105 | /* |
4964 | * The next_rpi stores the next module-64 rpi value to post | 5106 | * The next_rpi stores the next logical module-64 rpi value used |
4965 | * in any subsequent rpi memory region postings. | 5107 | * to post physical rpis in subsequent rpi postings. |
4966 | */ | 5108 | */ |
4967 | phba->sli4_hba.next_rpi += rpi_count; | 5109 | phba->sli4_hba.next_rpi += rpi_count; |
4968 | spin_unlock_irq(&phba->hbalock); | 5110 | spin_unlock_irq(&phba->hbalock); |
@@ -4981,15 +5123,18 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
4981 | * @phba: pointer to lpfc hba data structure. | 5123 | * @phba: pointer to lpfc hba data structure. |
4982 | * | 5124 | * |
4983 | * This routine is invoked to remove all memory resources allocated | 5125 | * This routine is invoked to remove all memory resources allocated |
4984 | * to support rpis. This routine presumes the caller has released all | 5126 | * to support rpis for SLI4 ports not supporting extents. This routine |
4985 | * rpis consumed by fabric or port logins and is prepared to have | 5127 | * presumes the caller has released all rpis consumed by fabric or port |
4986 | * the header pages removed. | 5128 | * logins and is prepared to have the header pages removed. |
4987 | **/ | 5129 | **/ |
4988 | void | 5130 | void |
4989 | lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *phba) | 5131 | lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *phba) |
4990 | { | 5132 | { |
4991 | struct lpfc_rpi_hdr *rpi_hdr, *next_rpi_hdr; | 5133 | struct lpfc_rpi_hdr *rpi_hdr, *next_rpi_hdr; |
4992 | 5134 | ||
5135 | if (!phba->sli4_hba.rpi_hdrs_in_use) | ||
5136 | goto exit; | ||
5137 | |||
4993 | list_for_each_entry_safe(rpi_hdr, next_rpi_hdr, | 5138 | list_for_each_entry_safe(rpi_hdr, next_rpi_hdr, |
4994 | &phba->sli4_hba.lpfc_rpi_hdr_list, list) { | 5139 | &phba->sli4_hba.lpfc_rpi_hdr_list, list) { |
4995 | list_del(&rpi_hdr->list); | 5140 | list_del(&rpi_hdr->list); |
@@ -4998,9 +5143,9 @@ lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *phba) | |||
4998 | kfree(rpi_hdr->dmabuf); | 5143 | kfree(rpi_hdr->dmabuf); |
4999 | kfree(rpi_hdr); | 5144 | kfree(rpi_hdr); |
5000 | } | 5145 | } |
5001 | 5146 | exit: | |
5002 | phba->sli4_hba.next_rpi = phba->sli4_hba.max_cfg_param.rpi_base; | 5147 | /* There are no rpis available to the port now. */ |
5003 | memset(phba->sli4_hba.rpi_bmask, 0, sizeof(*phba->sli4_hba.rpi_bmask)); | 5148 | phba->sli4_hba.next_rpi = 0; |
5004 | } | 5149 | } |
5005 | 5150 | ||
5006 | /** | 5151 | /** |
@@ -5487,7 +5632,8 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba) | |||
5487 | /* Final checks. The port status should be clean. */ | 5632 | /* Final checks. The port status should be clean. */ |
5488 | if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, | 5633 | if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, |
5489 | ®_data.word0) || | 5634 | ®_data.word0) || |
5490 | bf_get(lpfc_sliport_status_err, ®_data)) { | 5635 | (bf_get(lpfc_sliport_status_err, ®_data) && |
5636 | !bf_get(lpfc_sliport_status_rn, ®_data))) { | ||
5491 | phba->work_status[0] = | 5637 | phba->work_status[0] = |
5492 | readl(phba->sli4_hba.u.if_type2. | 5638 | readl(phba->sli4_hba.u.if_type2. |
5493 | ERR1regaddr); | 5639 | ERR1regaddr); |
@@ -5741,7 +5887,12 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
5741 | { | 5887 | { |
5742 | LPFC_MBOXQ_t *pmb; | 5888 | LPFC_MBOXQ_t *pmb; |
5743 | struct lpfc_mbx_read_config *rd_config; | 5889 | struct lpfc_mbx_read_config *rd_config; |
5744 | uint32_t rc = 0; | 5890 | union lpfc_sli4_cfg_shdr *shdr; |
5891 | uint32_t shdr_status, shdr_add_status; | ||
5892 | struct lpfc_mbx_get_func_cfg *get_func_cfg; | ||
5893 | struct lpfc_rsrc_desc_fcfcoe *desc; | ||
5894 | uint32_t desc_count; | ||
5895 | int length, i, rc = 0; | ||
5745 | 5896 | ||
5746 | pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 5897 | pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
5747 | if (!pmb) { | 5898 | if (!pmb) { |
@@ -5763,6 +5914,8 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
5763 | rc = -EIO; | 5914 | rc = -EIO; |
5764 | } else { | 5915 | } else { |
5765 | rd_config = &pmb->u.mqe.un.rd_config; | 5916 | rd_config = &pmb->u.mqe.un.rd_config; |
5917 | phba->sli4_hba.extents_in_use = | ||
5918 | bf_get(lpfc_mbx_rd_conf_extnts_inuse, rd_config); | ||
5766 | phba->sli4_hba.max_cfg_param.max_xri = | 5919 | phba->sli4_hba.max_cfg_param.max_xri = |
5767 | bf_get(lpfc_mbx_rd_conf_xri_count, rd_config); | 5920 | bf_get(lpfc_mbx_rd_conf_xri_count, rd_config); |
5768 | phba->sli4_hba.max_cfg_param.xri_base = | 5921 | phba->sli4_hba.max_cfg_param.xri_base = |
@@ -5781,8 +5934,6 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
5781 | bf_get(lpfc_mbx_rd_conf_vfi_base, rd_config); | 5934 | bf_get(lpfc_mbx_rd_conf_vfi_base, rd_config); |
5782 | phba->sli4_hba.max_cfg_param.max_fcfi = | 5935 | phba->sli4_hba.max_cfg_param.max_fcfi = |
5783 | bf_get(lpfc_mbx_rd_conf_fcfi_count, rd_config); | 5936 | bf_get(lpfc_mbx_rd_conf_fcfi_count, rd_config); |
5784 | phba->sli4_hba.max_cfg_param.fcfi_base = | ||
5785 | bf_get(lpfc_mbx_rd_conf_fcfi_base, rd_config); | ||
5786 | phba->sli4_hba.max_cfg_param.max_eq = | 5937 | phba->sli4_hba.max_cfg_param.max_eq = |
5787 | bf_get(lpfc_mbx_rd_conf_eq_count, rd_config); | 5938 | bf_get(lpfc_mbx_rd_conf_eq_count, rd_config); |
5788 | phba->sli4_hba.max_cfg_param.max_rq = | 5939 | phba->sli4_hba.max_cfg_param.max_rq = |
@@ -5800,11 +5951,13 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
5800 | (phba->sli4_hba.max_cfg_param.max_vpi - 1) : 0; | 5951 | (phba->sli4_hba.max_cfg_param.max_vpi - 1) : 0; |
5801 | phba->max_vports = phba->max_vpi; | 5952 | phba->max_vports = phba->max_vpi; |
5802 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | 5953 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, |
5803 | "2003 cfg params XRI(B:%d M:%d), " | 5954 | "2003 cfg params Extents? %d " |
5955 | "XRI(B:%d M:%d), " | ||
5804 | "VPI(B:%d M:%d) " | 5956 | "VPI(B:%d M:%d) " |
5805 | "VFI(B:%d M:%d) " | 5957 | "VFI(B:%d M:%d) " |
5806 | "RPI(B:%d M:%d) " | 5958 | "RPI(B:%d M:%d) " |
5807 | "FCFI(B:%d M:%d)\n", | 5959 | "FCFI(Count:%d)\n", |
5960 | phba->sli4_hba.extents_in_use, | ||
5808 | phba->sli4_hba.max_cfg_param.xri_base, | 5961 | phba->sli4_hba.max_cfg_param.xri_base, |
5809 | phba->sli4_hba.max_cfg_param.max_xri, | 5962 | phba->sli4_hba.max_cfg_param.max_xri, |
5810 | phba->sli4_hba.max_cfg_param.vpi_base, | 5963 | phba->sli4_hba.max_cfg_param.vpi_base, |
@@ -5813,10 +5966,11 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
5813 | phba->sli4_hba.max_cfg_param.max_vfi, | 5966 | phba->sli4_hba.max_cfg_param.max_vfi, |
5814 | phba->sli4_hba.max_cfg_param.rpi_base, | 5967 | phba->sli4_hba.max_cfg_param.rpi_base, |
5815 | phba->sli4_hba.max_cfg_param.max_rpi, | 5968 | phba->sli4_hba.max_cfg_param.max_rpi, |
5816 | phba->sli4_hba.max_cfg_param.fcfi_base, | ||
5817 | phba->sli4_hba.max_cfg_param.max_fcfi); | 5969 | phba->sli4_hba.max_cfg_param.max_fcfi); |
5818 | } | 5970 | } |
5819 | mempool_free(pmb, phba->mbox_mem_pool); | 5971 | |
5972 | if (rc) | ||
5973 | goto read_cfg_out; | ||
5820 | 5974 | ||
5821 | /* Reset the DFT_HBA_Q_DEPTH to the max xri */ | 5975 | /* Reset the DFT_HBA_Q_DEPTH to the max xri */ |
5822 | if (phba->cfg_hba_queue_depth > | 5976 | if (phba->cfg_hba_queue_depth > |
@@ -5825,6 +5979,65 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
5825 | phba->cfg_hba_queue_depth = | 5979 | phba->cfg_hba_queue_depth = |
5826 | phba->sli4_hba.max_cfg_param.max_xri - | 5980 | phba->sli4_hba.max_cfg_param.max_xri - |
5827 | lpfc_sli4_get_els_iocb_cnt(phba); | 5981 | lpfc_sli4_get_els_iocb_cnt(phba); |
5982 | |||
5983 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
5984 | LPFC_SLI_INTF_IF_TYPE_2) | ||
5985 | goto read_cfg_out; | ||
5986 | |||
5987 | /* get the pf# and vf# for SLI4 if_type 2 port */ | ||
5988 | length = (sizeof(struct lpfc_mbx_get_func_cfg) - | ||
5989 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
5990 | lpfc_sli4_config(phba, pmb, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
5991 | LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG, | ||
5992 | length, LPFC_SLI4_MBX_EMBED); | ||
5993 | |||
5994 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); | ||
5995 | shdr = (union lpfc_sli4_cfg_shdr *) | ||
5996 | &pmb->u.mqe.un.sli4_config.header.cfg_shdr; | ||
5997 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
5998 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); | ||
5999 | if (rc || shdr_status || shdr_add_status) { | ||
6000 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
6001 | "3026 Mailbox failed , mbxCmd x%x " | ||
6002 | "GET_FUNCTION_CONFIG, mbxStatus x%x\n", | ||
6003 | bf_get(lpfc_mqe_command, &pmb->u.mqe), | ||
6004 | bf_get(lpfc_mqe_status, &pmb->u.mqe)); | ||
6005 | rc = -EIO; | ||
6006 | goto read_cfg_out; | ||
6007 | } | ||
6008 | |||
6009 | /* search for fc_fcoe resrouce descriptor */ | ||
6010 | get_func_cfg = &pmb->u.mqe.un.get_func_cfg; | ||
6011 | desc_count = get_func_cfg->func_cfg.rsrc_desc_count; | ||
6012 | |||
6013 | for (i = 0; i < LPFC_RSRC_DESC_MAX_NUM; i++) { | ||
6014 | desc = (struct lpfc_rsrc_desc_fcfcoe *) | ||
6015 | &get_func_cfg->func_cfg.desc[i]; | ||
6016 | if (LPFC_RSRC_DESC_TYPE_FCFCOE == | ||
6017 | bf_get(lpfc_rsrc_desc_pcie_type, desc)) { | ||
6018 | phba->sli4_hba.iov.pf_number = | ||
6019 | bf_get(lpfc_rsrc_desc_fcfcoe_pfnum, desc); | ||
6020 | phba->sli4_hba.iov.vf_number = | ||
6021 | bf_get(lpfc_rsrc_desc_fcfcoe_vfnum, desc); | ||
6022 | break; | ||
6023 | } | ||
6024 | } | ||
6025 | |||
6026 | if (i < LPFC_RSRC_DESC_MAX_NUM) | ||
6027 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | ||
6028 | "3027 GET_FUNCTION_CONFIG: pf_number:%d, " | ||
6029 | "vf_number:%d\n", phba->sli4_hba.iov.pf_number, | ||
6030 | phba->sli4_hba.iov.vf_number); | ||
6031 | else { | ||
6032 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
6033 | "3028 GET_FUNCTION_CONFIG: failed to find " | ||
6034 | "Resrouce Descriptor:x%x\n", | ||
6035 | LPFC_RSRC_DESC_TYPE_FCFCOE); | ||
6036 | rc = -EIO; | ||
6037 | } | ||
6038 | |||
6039 | read_cfg_out: | ||
6040 | mempool_free(pmb, phba->mbox_mem_pool); | ||
5828 | return rc; | 6041 | return rc; |
5829 | } | 6042 | } |
5830 | 6043 | ||
@@ -6229,8 +6442,10 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba) | |||
6229 | phba->sli4_hba.mbx_cq = NULL; | 6442 | phba->sli4_hba.mbx_cq = NULL; |
6230 | 6443 | ||
6231 | /* Release FCP response complete queue */ | 6444 | /* Release FCP response complete queue */ |
6232 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) | 6445 | fcp_qidx = 0; |
6446 | do | ||
6233 | lpfc_sli4_queue_free(phba->sli4_hba.fcp_cq[fcp_qidx]); | 6447 | lpfc_sli4_queue_free(phba->sli4_hba.fcp_cq[fcp_qidx]); |
6448 | while (++fcp_qidx < phba->cfg_fcp_eq_count); | ||
6234 | kfree(phba->sli4_hba.fcp_cq); | 6449 | kfree(phba->sli4_hba.fcp_cq); |
6235 | phba->sli4_hba.fcp_cq = NULL; | 6450 | phba->sli4_hba.fcp_cq = NULL; |
6236 | 6451 | ||
@@ -6353,16 +6568,24 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) | |||
6353 | phba->sli4_hba.sp_eq->queue_id); | 6568 | phba->sli4_hba.sp_eq->queue_id); |
6354 | 6569 | ||
6355 | /* Set up fast-path FCP Response Complete Queue */ | 6570 | /* Set up fast-path FCP Response Complete Queue */ |
6356 | for (fcp_cqidx = 0; fcp_cqidx < phba->cfg_fcp_eq_count; fcp_cqidx++) { | 6571 | fcp_cqidx = 0; |
6572 | do { | ||
6357 | if (!phba->sli4_hba.fcp_cq[fcp_cqidx]) { | 6573 | if (!phba->sli4_hba.fcp_cq[fcp_cqidx]) { |
6358 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 6574 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
6359 | "0526 Fast-path FCP CQ (%d) not " | 6575 | "0526 Fast-path FCP CQ (%d) not " |
6360 | "allocated\n", fcp_cqidx); | 6576 | "allocated\n", fcp_cqidx); |
6361 | goto out_destroy_fcp_cq; | 6577 | goto out_destroy_fcp_cq; |
6362 | } | 6578 | } |
6363 | rc = lpfc_cq_create(phba, phba->sli4_hba.fcp_cq[fcp_cqidx], | 6579 | if (phba->cfg_fcp_eq_count) |
6364 | phba->sli4_hba.fp_eq[fcp_cqidx], | 6580 | rc = lpfc_cq_create(phba, |
6365 | LPFC_WCQ, LPFC_FCP); | 6581 | phba->sli4_hba.fcp_cq[fcp_cqidx], |
6582 | phba->sli4_hba.fp_eq[fcp_cqidx], | ||
6583 | LPFC_WCQ, LPFC_FCP); | ||
6584 | else | ||
6585 | rc = lpfc_cq_create(phba, | ||
6586 | phba->sli4_hba.fcp_cq[fcp_cqidx], | ||
6587 | phba->sli4_hba.sp_eq, | ||
6588 | LPFC_WCQ, LPFC_FCP); | ||
6366 | if (rc) { | 6589 | if (rc) { |
6367 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 6590 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
6368 | "0527 Failed setup of fast-path FCP " | 6591 | "0527 Failed setup of fast-path FCP " |
@@ -6371,12 +6594,15 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) | |||
6371 | } | 6594 | } |
6372 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 6595 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
6373 | "2588 FCP CQ setup: cq[%d]-id=%d, " | 6596 | "2588 FCP CQ setup: cq[%d]-id=%d, " |
6374 | "parent eq[%d]-id=%d\n", | 6597 | "parent %seq[%d]-id=%d\n", |
6375 | fcp_cqidx, | 6598 | fcp_cqidx, |
6376 | phba->sli4_hba.fcp_cq[fcp_cqidx]->queue_id, | 6599 | phba->sli4_hba.fcp_cq[fcp_cqidx]->queue_id, |
6600 | (phba->cfg_fcp_eq_count) ? "" : "sp_", | ||
6377 | fcp_cqidx, | 6601 | fcp_cqidx, |
6378 | phba->sli4_hba.fp_eq[fcp_cqidx]->queue_id); | 6602 | (phba->cfg_fcp_eq_count) ? |
6379 | } | 6603 | phba->sli4_hba.fp_eq[fcp_cqidx]->queue_id : |
6604 | phba->sli4_hba.sp_eq->queue_id); | ||
6605 | } while (++fcp_cqidx < phba->cfg_fcp_eq_count); | ||
6380 | 6606 | ||
6381 | /* | 6607 | /* |
6382 | * Set up all the Work Queues (WQs) | 6608 | * Set up all the Work Queues (WQs) |
@@ -6445,7 +6671,9 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) | |||
6445 | fcp_cq_index, | 6671 | fcp_cq_index, |
6446 | phba->sli4_hba.fcp_cq[fcp_cq_index]->queue_id); | 6672 | phba->sli4_hba.fcp_cq[fcp_cq_index]->queue_id); |
6447 | /* Round robin FCP Work Queue's Completion Queue assignment */ | 6673 | /* Round robin FCP Work Queue's Completion Queue assignment */ |
6448 | fcp_cq_index = ((fcp_cq_index + 1) % phba->cfg_fcp_eq_count); | 6674 | if (phba->cfg_fcp_eq_count) |
6675 | fcp_cq_index = ((fcp_cq_index + 1) % | ||
6676 | phba->cfg_fcp_eq_count); | ||
6449 | } | 6677 | } |
6450 | 6678 | ||
6451 | /* | 6679 | /* |
@@ -6827,6 +7055,8 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) | |||
6827 | if (rdy_chk < 1000) | 7055 | if (rdy_chk < 1000) |
6828 | break; | 7056 | break; |
6829 | } | 7057 | } |
7058 | /* delay driver action following IF_TYPE_2 function reset */ | ||
7059 | msleep(100); | ||
6830 | break; | 7060 | break; |
6831 | case LPFC_SLI_INTF_IF_TYPE_1: | 7061 | case LPFC_SLI_INTF_IF_TYPE_1: |
6832 | default: | 7062 | default: |
@@ -7419,11 +7649,15 @@ enable_msix_vectors: | |||
7419 | /* | 7649 | /* |
7420 | * Assign MSI-X vectors to interrupt handlers | 7650 | * Assign MSI-X vectors to interrupt handlers |
7421 | */ | 7651 | */ |
7422 | 7652 | if (vectors > 1) | |
7423 | /* The first vector must associated to slow-path handler for MQ */ | 7653 | rc = request_irq(phba->sli4_hba.msix_entries[0].vector, |
7424 | rc = request_irq(phba->sli4_hba.msix_entries[0].vector, | 7654 | &lpfc_sli4_sp_intr_handler, IRQF_SHARED, |
7425 | &lpfc_sli4_sp_intr_handler, IRQF_SHARED, | 7655 | LPFC_SP_DRIVER_HANDLER_NAME, phba); |
7426 | LPFC_SP_DRIVER_HANDLER_NAME, phba); | 7656 | else |
7657 | /* All Interrupts need to be handled by one EQ */ | ||
7658 | rc = request_irq(phba->sli4_hba.msix_entries[0].vector, | ||
7659 | &lpfc_sli4_intr_handler, IRQF_SHARED, | ||
7660 | LPFC_DRIVER_NAME, phba); | ||
7427 | if (rc) { | 7661 | if (rc) { |
7428 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | 7662 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, |
7429 | "0485 MSI-X slow-path request_irq failed " | 7663 | "0485 MSI-X slow-path request_irq failed " |
@@ -7765,6 +7999,7 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba) | |||
7765 | { | 7999 | { |
7766 | int wait_cnt = 0; | 8000 | int wait_cnt = 0; |
7767 | LPFC_MBOXQ_t *mboxq; | 8001 | LPFC_MBOXQ_t *mboxq; |
8002 | struct pci_dev *pdev = phba->pcidev; | ||
7768 | 8003 | ||
7769 | lpfc_stop_hba_timers(phba); | 8004 | lpfc_stop_hba_timers(phba); |
7770 | phba->sli4_hba.intr_enable = 0; | 8005 | phba->sli4_hba.intr_enable = 0; |
@@ -7804,6 +8039,10 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba) | |||
7804 | /* Disable PCI subsystem interrupt */ | 8039 | /* Disable PCI subsystem interrupt */ |
7805 | lpfc_sli4_disable_intr(phba); | 8040 | lpfc_sli4_disable_intr(phba); |
7806 | 8041 | ||
8042 | /* Disable SR-IOV if enabled */ | ||
8043 | if (phba->cfg_sriov_nr_virtfn) | ||
8044 | pci_disable_sriov(pdev); | ||
8045 | |||
7807 | /* Stop kthread signal shall trigger work_done one more time */ | 8046 | /* Stop kthread signal shall trigger work_done one more time */ |
7808 | kthread_stop(phba->worker_thread); | 8047 | kthread_stop(phba->worker_thread); |
7809 | 8048 | ||
@@ -7878,6 +8117,11 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
7878 | sli4_params->hdr_pp_align = bf_get(hdr_pp_align, &mqe->un.sli4_params); | 8117 | sli4_params->hdr_pp_align = bf_get(hdr_pp_align, &mqe->un.sli4_params); |
7879 | sli4_params->sgl_pages_max = bf_get(sgl_pages, &mqe->un.sli4_params); | 8118 | sli4_params->sgl_pages_max = bf_get(sgl_pages, &mqe->un.sli4_params); |
7880 | sli4_params->sgl_pp_align = bf_get(sgl_pp_align, &mqe->un.sli4_params); | 8119 | sli4_params->sgl_pp_align = bf_get(sgl_pp_align, &mqe->un.sli4_params); |
8120 | |||
8121 | /* Make sure that sge_supp_len can be handled by the driver */ | ||
8122 | if (sli4_params->sge_supp_len > LPFC_MAX_SGE_SIZE) | ||
8123 | sli4_params->sge_supp_len = LPFC_MAX_SGE_SIZE; | ||
8124 | |||
7881 | return rc; | 8125 | return rc; |
7882 | } | 8126 | } |
7883 | 8127 | ||
@@ -7902,6 +8146,13 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
7902 | int length; | 8146 | int length; |
7903 | struct lpfc_sli4_parameters *mbx_sli4_parameters; | 8147 | struct lpfc_sli4_parameters *mbx_sli4_parameters; |
7904 | 8148 | ||
8149 | /* | ||
8150 | * By default, the driver assumes the SLI4 port requires RPI | ||
8151 | * header postings. The SLI4_PARAM response will correct this | ||
8152 | * assumption. | ||
8153 | */ | ||
8154 | phba->sli4_hba.rpi_hdrs_in_use = 1; | ||
8155 | |||
7905 | /* Read the port's SLI4 Config Parameters */ | 8156 | /* Read the port's SLI4 Config Parameters */ |
7906 | length = (sizeof(struct lpfc_mbx_get_sli4_parameters) - | 8157 | length = (sizeof(struct lpfc_mbx_get_sli4_parameters) - |
7907 | sizeof(struct lpfc_sli4_cfg_mhdr)); | 8158 | sizeof(struct lpfc_sli4_cfg_mhdr)); |
@@ -7938,6 +8189,13 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
7938 | mbx_sli4_parameters); | 8189 | mbx_sli4_parameters); |
7939 | sli4_params->sgl_pp_align = bf_get(cfg_sgl_pp_align, | 8190 | sli4_params->sgl_pp_align = bf_get(cfg_sgl_pp_align, |
7940 | mbx_sli4_parameters); | 8191 | mbx_sli4_parameters); |
8192 | phba->sli4_hba.extents_in_use = bf_get(cfg_ext, mbx_sli4_parameters); | ||
8193 | phba->sli4_hba.rpi_hdrs_in_use = bf_get(cfg_hdrr, mbx_sli4_parameters); | ||
8194 | |||
8195 | /* Make sure that sge_supp_len can be handled by the driver */ | ||
8196 | if (sli4_params->sge_supp_len > LPFC_MAX_SGE_SIZE) | ||
8197 | sli4_params->sge_supp_len = LPFC_MAX_SGE_SIZE; | ||
8198 | |||
7941 | return 0; | 8199 | return 0; |
7942 | } | 8200 | } |
7943 | 8201 | ||
@@ -8173,6 +8431,10 @@ lpfc_pci_remove_one_s3(struct pci_dev *pdev) | |||
8173 | 8431 | ||
8174 | lpfc_debugfs_terminate(vport); | 8432 | lpfc_debugfs_terminate(vport); |
8175 | 8433 | ||
8434 | /* Disable SR-IOV if enabled */ | ||
8435 | if (phba->cfg_sriov_nr_virtfn) | ||
8436 | pci_disable_sriov(pdev); | ||
8437 | |||
8176 | /* Disable interrupt */ | 8438 | /* Disable interrupt */ |
8177 | lpfc_sli_disable_intr(phba); | 8439 | lpfc_sli_disable_intr(phba); |
8178 | 8440 | ||
@@ -8565,6 +8827,97 @@ lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *phba) | |||
8565 | } | 8827 | } |
8566 | 8828 | ||
8567 | /** | 8829 | /** |
8830 | * lpfc_write_firmware - attempt to write a firmware image to the port | ||
8831 | * @phba: pointer to lpfc hba data structure. | ||
8832 | * @fw: pointer to firmware image returned from request_firmware. | ||
8833 | * | ||
8834 | * returns the number of bytes written if write is successful. | ||
8835 | * returns a negative error value if there were errors. | ||
8836 | * returns 0 if firmware matches currently active firmware on port. | ||
8837 | **/ | ||
8838 | int | ||
8839 | lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw) | ||
8840 | { | ||
8841 | char fwrev[32]; | ||
8842 | struct lpfc_grp_hdr *image = (struct lpfc_grp_hdr *)fw->data; | ||
8843 | struct list_head dma_buffer_list; | ||
8844 | int i, rc = 0; | ||
8845 | struct lpfc_dmabuf *dmabuf, *next; | ||
8846 | uint32_t offset = 0, temp_offset = 0; | ||
8847 | |||
8848 | INIT_LIST_HEAD(&dma_buffer_list); | ||
8849 | if ((image->magic_number != LPFC_GROUP_OJECT_MAGIC_NUM) || | ||
8850 | (bf_get(lpfc_grp_hdr_file_type, image) != LPFC_FILE_TYPE_GROUP) || | ||
8851 | (bf_get(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) || | ||
8852 | (image->size != fw->size)) { | ||
8853 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
8854 | "3022 Invalid FW image found. " | ||
8855 | "Magic:%d Type:%x ID:%x\n", | ||
8856 | image->magic_number, | ||
8857 | bf_get(lpfc_grp_hdr_file_type, image), | ||
8858 | bf_get(lpfc_grp_hdr_id, image)); | ||
8859 | return -EINVAL; | ||
8860 | } | ||
8861 | lpfc_decode_firmware_rev(phba, fwrev, 1); | ||
8862 | if (strncmp(fwrev, image->rev_name, strnlen(fwrev, 16))) { | ||
8863 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
8864 | "3023 Updating Firmware. Current Version:%s " | ||
8865 | "New Version:%s\n", | ||
8866 | fwrev, image->rev_name); | ||
8867 | for (i = 0; i < LPFC_MBX_WR_CONFIG_MAX_BDE; i++) { | ||
8868 | dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), | ||
8869 | GFP_KERNEL); | ||
8870 | if (!dmabuf) { | ||
8871 | rc = -ENOMEM; | ||
8872 | goto out; | ||
8873 | } | ||
8874 | dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, | ||
8875 | SLI4_PAGE_SIZE, | ||
8876 | &dmabuf->phys, | ||
8877 | GFP_KERNEL); | ||
8878 | if (!dmabuf->virt) { | ||
8879 | kfree(dmabuf); | ||
8880 | rc = -ENOMEM; | ||
8881 | goto out; | ||
8882 | } | ||
8883 | list_add_tail(&dmabuf->list, &dma_buffer_list); | ||
8884 | } | ||
8885 | while (offset < fw->size) { | ||
8886 | temp_offset = offset; | ||
8887 | list_for_each_entry(dmabuf, &dma_buffer_list, list) { | ||
8888 | if (offset + SLI4_PAGE_SIZE > fw->size) { | ||
8889 | temp_offset += fw->size - offset; | ||
8890 | memcpy(dmabuf->virt, | ||
8891 | fw->data + temp_offset, | ||
8892 | fw->size - offset); | ||
8893 | break; | ||
8894 | } | ||
8895 | temp_offset += SLI4_PAGE_SIZE; | ||
8896 | memcpy(dmabuf->virt, fw->data + temp_offset, | ||
8897 | SLI4_PAGE_SIZE); | ||
8898 | } | ||
8899 | rc = lpfc_wr_object(phba, &dma_buffer_list, | ||
8900 | (fw->size - offset), &offset); | ||
8901 | if (rc) { | ||
8902 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
8903 | "3024 Firmware update failed. " | ||
8904 | "%d\n", rc); | ||
8905 | goto out; | ||
8906 | } | ||
8907 | } | ||
8908 | rc = offset; | ||
8909 | } | ||
8910 | out: | ||
8911 | list_for_each_entry_safe(dmabuf, next, &dma_buffer_list, list) { | ||
8912 | list_del(&dmabuf->list); | ||
8913 | dma_free_coherent(&phba->pcidev->dev, SLI4_PAGE_SIZE, | ||
8914 | dmabuf->virt, dmabuf->phys); | ||
8915 | kfree(dmabuf); | ||
8916 | } | ||
8917 | return rc; | ||
8918 | } | ||
8919 | |||
8920 | /** | ||
8568 | * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys | 8921 | * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys |
8569 | * @pdev: pointer to PCI device | 8922 | * @pdev: pointer to PCI device |
8570 | * @pid: pointer to PCI device identifier | 8923 | * @pid: pointer to PCI device identifier |
@@ -8591,6 +8944,10 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
8591 | int error; | 8944 | int error; |
8592 | uint32_t cfg_mode, intr_mode; | 8945 | uint32_t cfg_mode, intr_mode; |
8593 | int mcnt; | 8946 | int mcnt; |
8947 | int adjusted_fcp_eq_count; | ||
8948 | int fcp_qidx; | ||
8949 | const struct firmware *fw; | ||
8950 | uint8_t file_name[16]; | ||
8594 | 8951 | ||
8595 | /* Allocate memory for HBA structure */ | 8952 | /* Allocate memory for HBA structure */ |
8596 | phba = lpfc_hba_alloc(pdev); | 8953 | phba = lpfc_hba_alloc(pdev); |
@@ -8688,11 +9045,25 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
8688 | error = -ENODEV; | 9045 | error = -ENODEV; |
8689 | goto out_free_sysfs_attr; | 9046 | goto out_free_sysfs_attr; |
8690 | } | 9047 | } |
8691 | /* Default to single FCP EQ for non-MSI-X */ | 9048 | /* Default to single EQ for non-MSI-X */ |
8692 | if (phba->intr_type != MSIX) | 9049 | if (phba->intr_type != MSIX) |
8693 | phba->cfg_fcp_eq_count = 1; | 9050 | adjusted_fcp_eq_count = 0; |
8694 | else if (phba->sli4_hba.msix_vec_nr < phba->cfg_fcp_eq_count) | 9051 | else if (phba->sli4_hba.msix_vec_nr < |
8695 | phba->cfg_fcp_eq_count = phba->sli4_hba.msix_vec_nr - 1; | 9052 | phba->cfg_fcp_eq_count + 1) |
9053 | adjusted_fcp_eq_count = phba->sli4_hba.msix_vec_nr - 1; | ||
9054 | else | ||
9055 | adjusted_fcp_eq_count = phba->cfg_fcp_eq_count; | ||
9056 | /* Free unused EQs */ | ||
9057 | for (fcp_qidx = adjusted_fcp_eq_count; | ||
9058 | fcp_qidx < phba->cfg_fcp_eq_count; | ||
9059 | fcp_qidx++) { | ||
9060 | lpfc_sli4_queue_free(phba->sli4_hba.fp_eq[fcp_qidx]); | ||
9061 | /* do not delete the first fcp_cq */ | ||
9062 | if (fcp_qidx) | ||
9063 | lpfc_sli4_queue_free( | ||
9064 | phba->sli4_hba.fcp_cq[fcp_qidx]); | ||
9065 | } | ||
9066 | phba->cfg_fcp_eq_count = adjusted_fcp_eq_count; | ||
8696 | /* Set up SLI-4 HBA */ | 9067 | /* Set up SLI-4 HBA */ |
8697 | if (lpfc_sli4_hba_setup(phba)) { | 9068 | if (lpfc_sli4_hba_setup(phba)) { |
8698 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 9069 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
@@ -8731,6 +9102,14 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
8731 | /* Perform post initialization setup */ | 9102 | /* Perform post initialization setup */ |
8732 | lpfc_post_init_setup(phba); | 9103 | lpfc_post_init_setup(phba); |
8733 | 9104 | ||
9105 | /* check for firmware upgrade or downgrade */ | ||
9106 | snprintf(file_name, 16, "%s.grp", phba->ModelName); | ||
9107 | error = request_firmware(&fw, file_name, &phba->pcidev->dev); | ||
9108 | if (!error) { | ||
9109 | lpfc_write_firmware(phba, fw); | ||
9110 | release_firmware(fw); | ||
9111 | } | ||
9112 | |||
8734 | /* Check if there are static vports to be created. */ | 9113 | /* Check if there are static vports to be created. */ |
8735 | lpfc_create_static_vport(phba); | 9114 | lpfc_create_static_vport(phba); |
8736 | 9115 | ||
@@ -9498,6 +9877,10 @@ static struct pci_device_id lpfc_id_table[] = { | |||
9498 | PCI_ANY_ID, PCI_ANY_ID, }, | 9877 | PCI_ANY_ID, PCI_ANY_ID, }, |
9499 | {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE, | 9878 | {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE, |
9500 | PCI_ANY_ID, PCI_ANY_ID, }, | 9879 | PCI_ANY_ID, PCI_ANY_ID, }, |
9880 | {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC_VF, | ||
9881 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
9882 | {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE_VF, | ||
9883 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
9501 | { 0 } | 9884 | { 0 } |
9502 | }; | 9885 | }; |
9503 | 9886 | ||
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index e6ce9033f85e..556767028353 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -610,7 +610,8 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi) | |||
610 | mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm); | 610 | mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm); |
611 | mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys); | 611 | mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys); |
612 | mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys); | 612 | mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys); |
613 | mb->un.varRdSparm.vpi = vpi + phba->vpi_base; | 613 | if (phba->sli_rev >= LPFC_SLI_REV3) |
614 | mb->un.varRdSparm.vpi = phba->vpi_ids[vpi]; | ||
614 | 615 | ||
615 | /* save address for completion */ | 616 | /* save address for completion */ |
616 | pmb->context1 = mp; | 617 | pmb->context1 = mp; |
@@ -643,9 +644,10 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did, | |||
643 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 644 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
644 | 645 | ||
645 | mb->un.varUnregDID.did = did; | 646 | mb->un.varUnregDID.did = did; |
646 | if (vpi != 0xffff) | ||
647 | vpi += phba->vpi_base; | ||
648 | mb->un.varUnregDID.vpi = vpi; | 647 | mb->un.varUnregDID.vpi = vpi; |
648 | if ((vpi != 0xffff) && | ||
649 | (phba->sli_rev == LPFC_SLI_REV4)) | ||
650 | mb->un.varUnregDID.vpi = phba->vpi_ids[vpi]; | ||
649 | 651 | ||
650 | mb->mbxCommand = MBX_UNREG_D_ID; | 652 | mb->mbxCommand = MBX_UNREG_D_ID; |
651 | mb->mbxOwner = OWN_HOST; | 653 | mb->mbxOwner = OWN_HOST; |
@@ -738,12 +740,10 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, | |||
738 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 740 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
739 | 741 | ||
740 | mb->un.varRegLogin.rpi = 0; | 742 | mb->un.varRegLogin.rpi = 0; |
741 | if (phba->sli_rev == LPFC_SLI_REV4) { | 743 | if (phba->sli_rev == LPFC_SLI_REV4) |
742 | mb->un.varRegLogin.rpi = rpi; | 744 | mb->un.varRegLogin.rpi = phba->sli4_hba.rpi_ids[rpi]; |
743 | if (mb->un.varRegLogin.rpi == LPFC_RPI_ALLOC_ERROR) | 745 | if (phba->sli_rev >= LPFC_SLI_REV3) |
744 | return 1; | 746 | mb->un.varRegLogin.vpi = phba->vpi_ids[vpi]; |
745 | } | ||
746 | mb->un.varRegLogin.vpi = vpi + phba->vpi_base; | ||
747 | mb->un.varRegLogin.did = did; | 747 | mb->un.varRegLogin.did = did; |
748 | mb->mbxOwner = OWN_HOST; | 748 | mb->mbxOwner = OWN_HOST; |
749 | /* Get a buffer to hold NPorts Service Parameters */ | 749 | /* Get a buffer to hold NPorts Service Parameters */ |
@@ -757,7 +757,7 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, | |||
757 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, | 757 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, |
758 | "0302 REG_LOGIN: no buffers, VPI:%d DID:x%x, " | 758 | "0302 REG_LOGIN: no buffers, VPI:%d DID:x%x, " |
759 | "rpi x%x\n", vpi, did, rpi); | 759 | "rpi x%x\n", vpi, did, rpi); |
760 | return (1); | 760 | return 1; |
761 | } | 761 | } |
762 | INIT_LIST_HEAD(&mp->list); | 762 | INIT_LIST_HEAD(&mp->list); |
763 | sparam = mp->virt; | 763 | sparam = mp->virt; |
@@ -773,7 +773,7 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, | |||
773 | mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys); | 773 | mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys); |
774 | mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys); | 774 | mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys); |
775 | 775 | ||
776 | return (0); | 776 | return 0; |
777 | } | 777 | } |
778 | 778 | ||
779 | /** | 779 | /** |
@@ -789,6 +789,9 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, | |||
789 | * | 789 | * |
790 | * This routine prepares the mailbox command for unregistering remote port | 790 | * This routine prepares the mailbox command for unregistering remote port |
791 | * login. | 791 | * login. |
792 | * | ||
793 | * For SLI4 ports, the rpi passed to this function must be the physical | ||
794 | * rpi value, not the logical index. | ||
792 | **/ | 795 | **/ |
793 | void | 796 | void |
794 | lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, | 797 | lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, |
@@ -799,9 +802,10 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, | |||
799 | mb = &pmb->u.mb; | 802 | mb = &pmb->u.mb; |
800 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 803 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
801 | 804 | ||
802 | mb->un.varUnregLogin.rpi = (uint16_t) rpi; | 805 | mb->un.varUnregLogin.rpi = rpi; |
803 | mb->un.varUnregLogin.rsvd1 = 0; | 806 | mb->un.varUnregLogin.rsvd1 = 0; |
804 | mb->un.varUnregLogin.vpi = vpi + phba->vpi_base; | 807 | if (phba->sli_rev >= LPFC_SLI_REV3) |
808 | mb->un.varUnregLogin.vpi = phba->vpi_ids[vpi]; | ||
805 | 809 | ||
806 | mb->mbxCommand = MBX_UNREG_LOGIN; | 810 | mb->mbxCommand = MBX_UNREG_LOGIN; |
807 | mb->mbxOwner = OWN_HOST; | 811 | mb->mbxOwner = OWN_HOST; |
@@ -825,9 +829,16 @@ lpfc_sli4_unreg_all_rpis(struct lpfc_vport *vport) | |||
825 | 829 | ||
826 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 830 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
827 | if (mbox) { | 831 | if (mbox) { |
828 | lpfc_unreg_login(phba, vport->vpi, | 832 | /* |
829 | vport->vpi + phba->vpi_base, mbox); | 833 | * For SLI4 functions, the rpi field is overloaded for |
830 | mbox->u.mb.un.varUnregLogin.rsvd1 = 0x4000 ; | 834 | * the vport context unreg all. This routine passes |
835 | * 0 for the rpi field in lpfc_unreg_login for compatibility | ||
836 | * with SLI3 and then overrides the rpi field with the | ||
837 | * expected value for SLI4. | ||
838 | */ | ||
839 | lpfc_unreg_login(phba, vport->vpi, phba->vpi_ids[vport->vpi], | ||
840 | mbox); | ||
841 | mbox->u.mb.un.varUnregLogin.rsvd1 = 0x4000; | ||
831 | mbox->vport = vport; | 842 | mbox->vport = vport; |
832 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 843 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
833 | mbox->context1 = NULL; | 844 | mbox->context1 = NULL; |
@@ -865,9 +876,13 @@ lpfc_reg_vpi(struct lpfc_vport *vport, LPFC_MBOXQ_t *pmb) | |||
865 | if ((phba->sli_rev == LPFC_SLI_REV4) && | 876 | if ((phba->sli_rev == LPFC_SLI_REV4) && |
866 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) | 877 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) |
867 | mb->un.varRegVpi.upd = 1; | 878 | mb->un.varRegVpi.upd = 1; |
868 | mb->un.varRegVpi.vpi = vport->vpi + vport->phba->vpi_base; | 879 | |
880 | mb->un.varRegVpi.vpi = phba->vpi_ids[vport->vpi]; | ||
869 | mb->un.varRegVpi.sid = vport->fc_myDID; | 881 | mb->un.varRegVpi.sid = vport->fc_myDID; |
870 | mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base; | 882 | if (phba->sli_rev == LPFC_SLI_REV4) |
883 | mb->un.varRegVpi.vfi = phba->sli4_hba.vfi_ids[vport->vfi]; | ||
884 | else | ||
885 | mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base; | ||
871 | memcpy(mb->un.varRegVpi.wwn, &vport->fc_portname, | 886 | memcpy(mb->un.varRegVpi.wwn, &vport->fc_portname, |
872 | sizeof(struct lpfc_name)); | 887 | sizeof(struct lpfc_name)); |
873 | mb->un.varRegVpi.wwn[0] = cpu_to_le32(mb->un.varRegVpi.wwn[0]); | 888 | mb->un.varRegVpi.wwn[0] = cpu_to_le32(mb->un.varRegVpi.wwn[0]); |
@@ -901,10 +916,10 @@ lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb) | |||
901 | MAILBOX_t *mb = &pmb->u.mb; | 916 | MAILBOX_t *mb = &pmb->u.mb; |
902 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 917 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
903 | 918 | ||
904 | if (phba->sli_rev < LPFC_SLI_REV4) | 919 | if (phba->sli_rev == LPFC_SLI_REV3) |
905 | mb->un.varUnregVpi.vpi = vpi + phba->vpi_base; | 920 | mb->un.varUnregVpi.vpi = phba->vpi_ids[vpi]; |
906 | else | 921 | else if (phba->sli_rev >= LPFC_SLI_REV4) |
907 | mb->un.varUnregVpi.sli4_vpi = vpi + phba->vpi_base; | 922 | mb->un.varUnregVpi.sli4_vpi = phba->vpi_ids[vpi]; |
908 | 923 | ||
909 | mb->mbxCommand = MBX_UNREG_VPI; | 924 | mb->mbxCommand = MBX_UNREG_VPI; |
910 | mb->mbxOwner = OWN_HOST; | 925 | mb->mbxOwner = OWN_HOST; |
@@ -1735,12 +1750,12 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox, | |||
1735 | return length; | 1750 | return length; |
1736 | } | 1751 | } |
1737 | 1752 | ||
1738 | /* Setup for the none-embedded mbox command */ | 1753 | /* Setup for the non-embedded mbox command */ |
1739 | pcount = (SLI4_PAGE_ALIGN(length))/SLI4_PAGE_SIZE; | 1754 | pcount = (SLI4_PAGE_ALIGN(length))/SLI4_PAGE_SIZE; |
1740 | pcount = (pcount > LPFC_SLI4_MBX_SGE_MAX_PAGES) ? | 1755 | pcount = (pcount > LPFC_SLI4_MBX_SGE_MAX_PAGES) ? |
1741 | LPFC_SLI4_MBX_SGE_MAX_PAGES : pcount; | 1756 | LPFC_SLI4_MBX_SGE_MAX_PAGES : pcount; |
1742 | /* Allocate record for keeping SGE virtual addresses */ | 1757 | /* Allocate record for keeping SGE virtual addresses */ |
1743 | mbox->sge_array = kmalloc(sizeof(struct lpfc_mbx_nembed_sge_virt), | 1758 | mbox->sge_array = kzalloc(sizeof(struct lpfc_mbx_nembed_sge_virt), |
1744 | GFP_KERNEL); | 1759 | GFP_KERNEL); |
1745 | if (!mbox->sge_array) { | 1760 | if (!mbox->sge_array) { |
1746 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, | 1761 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, |
@@ -1790,12 +1805,87 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox, | |||
1790 | /* The sub-header is in DMA memory, which needs endian converstion */ | 1805 | /* The sub-header is in DMA memory, which needs endian converstion */ |
1791 | if (cfg_shdr) | 1806 | if (cfg_shdr) |
1792 | lpfc_sli_pcimem_bcopy(cfg_shdr, cfg_shdr, | 1807 | lpfc_sli_pcimem_bcopy(cfg_shdr, cfg_shdr, |
1793 | sizeof(union lpfc_sli4_cfg_shdr)); | 1808 | sizeof(union lpfc_sli4_cfg_shdr)); |
1794 | |||
1795 | return alloc_len; | 1809 | return alloc_len; |
1796 | } | 1810 | } |
1797 | 1811 | ||
1798 | /** | 1812 | /** |
1813 | * lpfc_sli4_mbox_rsrc_extent - Initialize the opcode resource extent. | ||
1814 | * @phba: pointer to lpfc hba data structure. | ||
1815 | * @mbox: pointer to an allocated lpfc mbox resource. | ||
1816 | * @exts_count: the number of extents, if required, to allocate. | ||
1817 | * @rsrc_type: the resource extent type. | ||
1818 | * @emb: true if LPFC_SLI4_MBX_EMBED. false if LPFC_SLI4_MBX_NEMBED. | ||
1819 | * | ||
1820 | * This routine completes the subcommand header for SLI4 resource extent | ||
1821 | * mailbox commands. It is called after lpfc_sli4_config. The caller must | ||
1822 | * pass an allocated mailbox and the attributes required to initialize the | ||
1823 | * mailbox correctly. | ||
1824 | * | ||
1825 | * Return: the actual length of the mbox command allocated. | ||
1826 | **/ | ||
1827 | int | ||
1828 | lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *phba, struct lpfcMboxq *mbox, | ||
1829 | uint16_t exts_count, uint16_t rsrc_type, bool emb) | ||
1830 | { | ||
1831 | uint8_t opcode = 0; | ||
1832 | struct lpfc_mbx_nembed_rsrc_extent *n_rsrc_extnt = NULL; | ||
1833 | void *virtaddr = NULL; | ||
1834 | |||
1835 | /* Set up SLI4 ioctl command header fields */ | ||
1836 | if (emb == LPFC_SLI4_MBX_NEMBED) { | ||
1837 | /* Get the first SGE entry from the non-embedded DMA memory */ | ||
1838 | virtaddr = mbox->sge_array->addr[0]; | ||
1839 | if (virtaddr == NULL) | ||
1840 | return 1; | ||
1841 | n_rsrc_extnt = (struct lpfc_mbx_nembed_rsrc_extent *) virtaddr; | ||
1842 | } | ||
1843 | |||
1844 | /* | ||
1845 | * The resource type is common to all extent Opcodes and resides in the | ||
1846 | * same position. | ||
1847 | */ | ||
1848 | if (emb == LPFC_SLI4_MBX_EMBED) | ||
1849 | bf_set(lpfc_mbx_alloc_rsrc_extents_type, | ||
1850 | &mbox->u.mqe.un.alloc_rsrc_extents.u.req, | ||
1851 | rsrc_type); | ||
1852 | else { | ||
1853 | /* This is DMA data. Byteswap is required. */ | ||
1854 | bf_set(lpfc_mbx_alloc_rsrc_extents_type, | ||
1855 | n_rsrc_extnt, rsrc_type); | ||
1856 | lpfc_sli_pcimem_bcopy(&n_rsrc_extnt->word4, | ||
1857 | &n_rsrc_extnt->word4, | ||
1858 | sizeof(uint32_t)); | ||
1859 | } | ||
1860 | |||
1861 | /* Complete the initialization for the particular Opcode. */ | ||
1862 | opcode = lpfc_sli4_mbox_opcode_get(phba, mbox); | ||
1863 | switch (opcode) { | ||
1864 | case LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT: | ||
1865 | if (emb == LPFC_SLI4_MBX_EMBED) | ||
1866 | bf_set(lpfc_mbx_alloc_rsrc_extents_cnt, | ||
1867 | &mbox->u.mqe.un.alloc_rsrc_extents.u.req, | ||
1868 | exts_count); | ||
1869 | else | ||
1870 | bf_set(lpfc_mbx_alloc_rsrc_extents_cnt, | ||
1871 | n_rsrc_extnt, exts_count); | ||
1872 | break; | ||
1873 | case LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT: | ||
1874 | case LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO: | ||
1875 | case LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT: | ||
1876 | /* Initialization is complete.*/ | ||
1877 | break; | ||
1878 | default: | ||
1879 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, | ||
1880 | "2929 Resource Extent Opcode x%x is " | ||
1881 | "unsupported\n", opcode); | ||
1882 | return 1; | ||
1883 | } | ||
1884 | |||
1885 | return 0; | ||
1886 | } | ||
1887 | |||
1888 | /** | ||
1799 | * lpfc_sli4_mbox_opcode_get - Get the opcode from a sli4 mailbox command | 1889 | * lpfc_sli4_mbox_opcode_get - Get the opcode from a sli4 mailbox command |
1800 | * @phba: pointer to lpfc hba data structure. | 1890 | * @phba: pointer to lpfc hba data structure. |
1801 | * @mbox: pointer to lpfc mbox command. | 1891 | * @mbox: pointer to lpfc mbox command. |
@@ -1939,9 +2029,12 @@ lpfc_init_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport) | |||
1939 | bf_set(lpfc_init_vfi_vr, init_vfi, 1); | 2029 | bf_set(lpfc_init_vfi_vr, init_vfi, 1); |
1940 | bf_set(lpfc_init_vfi_vt, init_vfi, 1); | 2030 | bf_set(lpfc_init_vfi_vt, init_vfi, 1); |
1941 | bf_set(lpfc_init_vfi_vp, init_vfi, 1); | 2031 | bf_set(lpfc_init_vfi_vp, init_vfi, 1); |
1942 | bf_set(lpfc_init_vfi_vfi, init_vfi, vport->vfi + vport->phba->vfi_base); | 2032 | bf_set(lpfc_init_vfi_vfi, init_vfi, |
1943 | bf_set(lpfc_init_vpi_vpi, init_vfi, vport->vpi + vport->phba->vpi_base); | 2033 | vport->phba->sli4_hba.vfi_ids[vport->vfi]); |
1944 | bf_set(lpfc_init_vfi_fcfi, init_vfi, vport->phba->fcf.fcfi); | 2034 | bf_set(lpfc_init_vpi_vpi, init_vfi, |
2035 | vport->phba->vpi_ids[vport->vpi]); | ||
2036 | bf_set(lpfc_init_vfi_fcfi, init_vfi, | ||
2037 | vport->phba->fcf.fcfi); | ||
1945 | } | 2038 | } |
1946 | 2039 | ||
1947 | /** | 2040 | /** |
@@ -1964,9 +2057,10 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys) | |||
1964 | reg_vfi = &mbox->u.mqe.un.reg_vfi; | 2057 | reg_vfi = &mbox->u.mqe.un.reg_vfi; |
1965 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_REG_VFI); | 2058 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_REG_VFI); |
1966 | bf_set(lpfc_reg_vfi_vp, reg_vfi, 1); | 2059 | bf_set(lpfc_reg_vfi_vp, reg_vfi, 1); |
1967 | bf_set(lpfc_reg_vfi_vfi, reg_vfi, vport->vfi + vport->phba->vfi_base); | 2060 | bf_set(lpfc_reg_vfi_vfi, reg_vfi, |
2061 | vport->phba->sli4_hba.vfi_ids[vport->vfi]); | ||
1968 | bf_set(lpfc_reg_vfi_fcfi, reg_vfi, vport->phba->fcf.fcfi); | 2062 | bf_set(lpfc_reg_vfi_fcfi, reg_vfi, vport->phba->fcf.fcfi); |
1969 | bf_set(lpfc_reg_vfi_vpi, reg_vfi, vport->vpi + vport->phba->vpi_base); | 2063 | bf_set(lpfc_reg_vfi_vpi, reg_vfi, vport->phba->vpi_ids[vport->vpi]); |
1970 | memcpy(reg_vfi->wwn, &vport->fc_portname, sizeof(struct lpfc_name)); | 2064 | memcpy(reg_vfi->wwn, &vport->fc_portname, sizeof(struct lpfc_name)); |
1971 | reg_vfi->wwn[0] = cpu_to_le32(reg_vfi->wwn[0]); | 2065 | reg_vfi->wwn[0] = cpu_to_le32(reg_vfi->wwn[0]); |
1972 | reg_vfi->wwn[1] = cpu_to_le32(reg_vfi->wwn[1]); | 2066 | reg_vfi->wwn[1] = cpu_to_le32(reg_vfi->wwn[1]); |
@@ -1997,9 +2091,9 @@ lpfc_init_vpi(struct lpfc_hba *phba, struct lpfcMboxq *mbox, uint16_t vpi) | |||
1997 | memset(mbox, 0, sizeof(*mbox)); | 2091 | memset(mbox, 0, sizeof(*mbox)); |
1998 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_INIT_VPI); | 2092 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_INIT_VPI); |
1999 | bf_set(lpfc_init_vpi_vpi, &mbox->u.mqe.un.init_vpi, | 2093 | bf_set(lpfc_init_vpi_vpi, &mbox->u.mqe.un.init_vpi, |
2000 | vpi + phba->vpi_base); | 2094 | phba->vpi_ids[vpi]); |
2001 | bf_set(lpfc_init_vpi_vfi, &mbox->u.mqe.un.init_vpi, | 2095 | bf_set(lpfc_init_vpi_vfi, &mbox->u.mqe.un.init_vpi, |
2002 | phba->pport->vfi + phba->vfi_base); | 2096 | phba->sli4_hba.vfi_ids[phba->pport->vfi]); |
2003 | } | 2097 | } |
2004 | 2098 | ||
2005 | /** | 2099 | /** |
@@ -2019,7 +2113,7 @@ lpfc_unreg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport) | |||
2019 | memset(mbox, 0, sizeof(*mbox)); | 2113 | memset(mbox, 0, sizeof(*mbox)); |
2020 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_UNREG_VFI); | 2114 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_UNREG_VFI); |
2021 | bf_set(lpfc_unreg_vfi_vfi, &mbox->u.mqe.un.unreg_vfi, | 2115 | bf_set(lpfc_unreg_vfi_vfi, &mbox->u.mqe.un.unreg_vfi, |
2022 | vport->vfi + vport->phba->vfi_base); | 2116 | vport->phba->sli4_hba.vfi_ids[vport->vfi]); |
2023 | } | 2117 | } |
2024 | 2118 | ||
2025 | /** | 2119 | /** |
@@ -2131,12 +2225,14 @@ lpfc_unreg_fcfi(struct lpfcMboxq *mbox, uint16_t fcfi) | |||
2131 | void | 2225 | void |
2132 | lpfc_resume_rpi(struct lpfcMboxq *mbox, struct lpfc_nodelist *ndlp) | 2226 | lpfc_resume_rpi(struct lpfcMboxq *mbox, struct lpfc_nodelist *ndlp) |
2133 | { | 2227 | { |
2228 | struct lpfc_hba *phba = ndlp->phba; | ||
2134 | struct lpfc_mbx_resume_rpi *resume_rpi; | 2229 | struct lpfc_mbx_resume_rpi *resume_rpi; |
2135 | 2230 | ||
2136 | memset(mbox, 0, sizeof(*mbox)); | 2231 | memset(mbox, 0, sizeof(*mbox)); |
2137 | resume_rpi = &mbox->u.mqe.un.resume_rpi; | 2232 | resume_rpi = &mbox->u.mqe.un.resume_rpi; |
2138 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_RESUME_RPI); | 2233 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_RESUME_RPI); |
2139 | bf_set(lpfc_resume_rpi_index, resume_rpi, ndlp->nlp_rpi); | 2234 | bf_set(lpfc_resume_rpi_index, resume_rpi, |
2235 | phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); | ||
2140 | bf_set(lpfc_resume_rpi_ii, resume_rpi, RESUME_INDEX_RPI); | 2236 | bf_set(lpfc_resume_rpi_ii, resume_rpi, RESUME_INDEX_RPI); |
2141 | resume_rpi->event_tag = ndlp->phba->fc_eventTag; | 2237 | resume_rpi->event_tag = ndlp->phba->fc_eventTag; |
2142 | } | 2238 | } |
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index cbb48ee8b0bb..10d5b5e41499 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c | |||
@@ -62,7 +62,6 @@ int | |||
62 | lpfc_mem_alloc(struct lpfc_hba *phba, int align) | 62 | lpfc_mem_alloc(struct lpfc_hba *phba, int align) |
63 | { | 63 | { |
64 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | 64 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; |
65 | int longs; | ||
66 | int i; | 65 | int i; |
67 | 66 | ||
68 | if (phba->sli_rev == LPFC_SLI_REV4) | 67 | if (phba->sli_rev == LPFC_SLI_REV4) |
@@ -138,17 +137,8 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) | |||
138 | phba->lpfc_hrb_pool = NULL; | 137 | phba->lpfc_hrb_pool = NULL; |
139 | phba->lpfc_drb_pool = NULL; | 138 | phba->lpfc_drb_pool = NULL; |
140 | } | 139 | } |
141 | /* vpi zero is reserved for the physical port so add 1 to max */ | ||
142 | longs = ((phba->max_vpi + 1) + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
143 | phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), GFP_KERNEL); | ||
144 | if (!phba->vpi_bmask) | ||
145 | goto fail_free_dbq_pool; | ||
146 | 140 | ||
147 | return 0; | 141 | return 0; |
148 | |||
149 | fail_free_dbq_pool: | ||
150 | pci_pool_destroy(phba->lpfc_drb_pool); | ||
151 | phba->lpfc_drb_pool = NULL; | ||
152 | fail_free_hrb_pool: | 142 | fail_free_hrb_pool: |
153 | pci_pool_destroy(phba->lpfc_hrb_pool); | 143 | pci_pool_destroy(phba->lpfc_hrb_pool); |
154 | phba->lpfc_hrb_pool = NULL; | 144 | phba->lpfc_hrb_pool = NULL; |
@@ -191,9 +181,6 @@ lpfc_mem_free(struct lpfc_hba *phba) | |||
191 | int i; | 181 | int i; |
192 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | 182 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; |
193 | 183 | ||
194 | /* Free VPI bitmask memory */ | ||
195 | kfree(phba->vpi_bmask); | ||
196 | |||
197 | /* Free HBQ pools */ | 184 | /* Free HBQ pools */ |
198 | lpfc_sli_hbqbuf_free_all(phba); | 185 | lpfc_sli_hbqbuf_free_all(phba); |
199 | if (phba->lpfc_drb_pool) | 186 | if (phba->lpfc_drb_pool) |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 0d92d4205ea6..2ddd02f7c603 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -350,11 +350,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
350 | ndlp->nlp_maxframe = | 350 | ndlp->nlp_maxframe = |
351 | ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; | 351 | ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; |
352 | 352 | ||
353 | /* | 353 | /* no need to reg_login if we are already in one of these states */ |
354 | * Need to unreg_login if we are already in one of these states and | ||
355 | * change to NPR state. This will block the port until after the ACC | ||
356 | * completes and the reg_login is issued and completed. | ||
357 | */ | ||
358 | switch (ndlp->nlp_state) { | 354 | switch (ndlp->nlp_state) { |
359 | case NLP_STE_NPR_NODE: | 355 | case NLP_STE_NPR_NODE: |
360 | if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) | 356 | if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) |
@@ -363,9 +359,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
363 | case NLP_STE_PRLI_ISSUE: | 359 | case NLP_STE_PRLI_ISSUE: |
364 | case NLP_STE_UNMAPPED_NODE: | 360 | case NLP_STE_UNMAPPED_NODE: |
365 | case NLP_STE_MAPPED_NODE: | 361 | case NLP_STE_MAPPED_NODE: |
366 | lpfc_unreg_rpi(vport, ndlp); | 362 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); |
367 | ndlp->nlp_prev_state = ndlp->nlp_state; | 363 | return 1; |
368 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | ||
369 | } | 364 | } |
370 | 365 | ||
371 | if ((vport->fc_flag & FC_PT2PT) && | 366 | if ((vport->fc_flag & FC_PT2PT) && |
@@ -657,6 +652,7 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
657 | lpfc_unreg_rpi(vport, ndlp); | 652 | lpfc_unreg_rpi(vport, ndlp); |
658 | return 0; | 653 | return 0; |
659 | } | 654 | } |
655 | |||
660 | /** | 656 | /** |
661 | * lpfc_release_rpi - Release a RPI by issuing unreg_login mailbox cmd. | 657 | * lpfc_release_rpi - Release a RPI by issuing unreg_login mailbox cmd. |
662 | * @phba : Pointer to lpfc_hba structure. | 658 | * @phba : Pointer to lpfc_hba structure. |
@@ -1399,8 +1395,11 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, | |||
1399 | if (mb->mbxStatus) { | 1395 | if (mb->mbxStatus) { |
1400 | /* RegLogin failed */ | 1396 | /* RegLogin failed */ |
1401 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, | 1397 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, |
1402 | "0246 RegLogin failed Data: x%x x%x x%x\n", | 1398 | "0246 RegLogin failed Data: x%x x%x x%x x%x " |
1403 | did, mb->mbxStatus, vport->port_state); | 1399 | "x%x\n", |
1400 | did, mb->mbxStatus, vport->port_state, | ||
1401 | mb->un.varRegLogin.vpi, | ||
1402 | mb->un.varRegLogin.rpi); | ||
1404 | /* | 1403 | /* |
1405 | * If RegLogin failed due to lack of HBA resources do not | 1404 | * If RegLogin failed due to lack of HBA resources do not |
1406 | * retry discovery. | 1405 | * retry discovery. |
@@ -1424,7 +1423,10 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, | |||
1424 | return ndlp->nlp_state; | 1423 | return ndlp->nlp_state; |
1425 | } | 1424 | } |
1426 | 1425 | ||
1427 | ndlp->nlp_rpi = mb->un.varWords[0]; | 1426 | /* SLI4 ports have preallocated logical rpis. */ |
1427 | if (vport->phba->sli_rev < LPFC_SLI_REV4) | ||
1428 | ndlp->nlp_rpi = mb->un.varWords[0]; | ||
1429 | |||
1428 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 1430 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
1429 | 1431 | ||
1430 | /* Only if we are not a fabric nport do we issue PRLI */ | 1432 | /* Only if we are not a fabric nport do we issue PRLI */ |
@@ -2025,7 +2027,9 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport, | |||
2025 | MAILBOX_t *mb = &pmb->u.mb; | 2027 | MAILBOX_t *mb = &pmb->u.mb; |
2026 | 2028 | ||
2027 | if (!mb->mbxStatus) { | 2029 | if (!mb->mbxStatus) { |
2028 | ndlp->nlp_rpi = mb->un.varWords[0]; | 2030 | /* SLI4 ports have preallocated logical rpis. */ |
2031 | if (vport->phba->sli_rev < LPFC_SLI_REV4) | ||
2032 | ndlp->nlp_rpi = mb->un.varWords[0]; | ||
2029 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 2033 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
2030 | } else { | 2034 | } else { |
2031 | if (ndlp->nlp_flag & NLP_NODEV_REMOVE) { | 2035 | if (ndlp->nlp_flag & NLP_NODEV_REMOVE) { |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 84e4481b2406..3ccc97496ebf 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -743,7 +743,14 @@ lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba) | |||
743 | if (bcnt == 0) | 743 | if (bcnt == 0) |
744 | continue; | 744 | continue; |
745 | /* Now, post the SCSI buffer list sgls as a block */ | 745 | /* Now, post the SCSI buffer list sgls as a block */ |
746 | status = lpfc_sli4_post_scsi_sgl_block(phba, &sblist, bcnt); | 746 | if (!phba->sli4_hba.extents_in_use) |
747 | status = lpfc_sli4_post_scsi_sgl_block(phba, | ||
748 | &sblist, | ||
749 | bcnt); | ||
750 | else | ||
751 | status = lpfc_sli4_post_scsi_sgl_blk_ext(phba, | ||
752 | &sblist, | ||
753 | bcnt); | ||
747 | /* Reset SCSI buffer count for next round of posting */ | 754 | /* Reset SCSI buffer count for next round of posting */ |
748 | bcnt = 0; | 755 | bcnt = 0; |
749 | while (!list_empty(&sblist)) { | 756 | while (!list_empty(&sblist)) { |
@@ -787,7 +794,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
787 | dma_addr_t pdma_phys_fcp_cmd; | 794 | dma_addr_t pdma_phys_fcp_cmd; |
788 | dma_addr_t pdma_phys_fcp_rsp; | 795 | dma_addr_t pdma_phys_fcp_rsp; |
789 | dma_addr_t pdma_phys_bpl, pdma_phys_bpl1; | 796 | dma_addr_t pdma_phys_bpl, pdma_phys_bpl1; |
790 | uint16_t iotag, last_xritag = NO_XRI; | 797 | uint16_t iotag, last_xritag = NO_XRI, lxri = 0; |
791 | int status = 0, index; | 798 | int status = 0, index; |
792 | int bcnt; | 799 | int bcnt; |
793 | int non_sequential_xri = 0; | 800 | int non_sequential_xri = 0; |
@@ -823,13 +830,15 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
823 | break; | 830 | break; |
824 | } | 831 | } |
825 | 832 | ||
826 | psb->cur_iocbq.sli4_xritag = lpfc_sli4_next_xritag(phba); | 833 | lxri = lpfc_sli4_next_xritag(phba); |
827 | if (psb->cur_iocbq.sli4_xritag == NO_XRI) { | 834 | if (lxri == NO_XRI) { |
828 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, | 835 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, |
829 | psb->data, psb->dma_handle); | 836 | psb->data, psb->dma_handle); |
830 | kfree(psb); | 837 | kfree(psb); |
831 | break; | 838 | break; |
832 | } | 839 | } |
840 | psb->cur_iocbq.sli4_lxritag = lxri; | ||
841 | psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri]; | ||
833 | if (last_xritag != NO_XRI | 842 | if (last_xritag != NO_XRI |
834 | && psb->cur_iocbq.sli4_xritag != (last_xritag+1)) { | 843 | && psb->cur_iocbq.sli4_xritag != (last_xritag+1)) { |
835 | non_sequential_xri = 1; | 844 | non_sequential_xri = 1; |
@@ -861,6 +870,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
861 | */ | 870 | */ |
862 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_cmd)); | 871 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_cmd)); |
863 | sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_cmd)); | 872 | sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_cmd)); |
873 | sgl->word2 = le32_to_cpu(sgl->word2); | ||
864 | bf_set(lpfc_sli4_sge_last, sgl, 0); | 874 | bf_set(lpfc_sli4_sge_last, sgl, 0); |
865 | sgl->word2 = cpu_to_le32(sgl->word2); | 875 | sgl->word2 = cpu_to_le32(sgl->word2); |
866 | sgl->sge_len = cpu_to_le32(sizeof(struct fcp_cmnd)); | 876 | sgl->sge_len = cpu_to_le32(sizeof(struct fcp_cmnd)); |
@@ -869,6 +879,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
869 | /* Setup the physical region for the FCP RSP */ | 879 | /* Setup the physical region for the FCP RSP */ |
870 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_rsp)); | 880 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_rsp)); |
871 | sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_rsp)); | 881 | sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_rsp)); |
882 | sgl->word2 = le32_to_cpu(sgl->word2); | ||
872 | bf_set(lpfc_sli4_sge_last, sgl, 1); | 883 | bf_set(lpfc_sli4_sge_last, sgl, 1); |
873 | sgl->word2 = cpu_to_le32(sgl->word2); | 884 | sgl->word2 = cpu_to_le32(sgl->word2); |
874 | sgl->sge_len = cpu_to_le32(sizeof(struct fcp_rsp)); | 885 | sgl->sge_len = cpu_to_le32(sizeof(struct fcp_rsp)); |
@@ -914,7 +925,21 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
914 | } | 925 | } |
915 | } | 926 | } |
916 | if (bcnt) { | 927 | if (bcnt) { |
917 | status = lpfc_sli4_post_scsi_sgl_block(phba, &sblist, bcnt); | 928 | if (!phba->sli4_hba.extents_in_use) |
929 | status = lpfc_sli4_post_scsi_sgl_block(phba, | ||
930 | &sblist, | ||
931 | bcnt); | ||
932 | else | ||
933 | status = lpfc_sli4_post_scsi_sgl_blk_ext(phba, | ||
934 | &sblist, | ||
935 | bcnt); | ||
936 | |||
937 | if (status) { | ||
938 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | ||
939 | "3021 SCSI SGL post error %d\n", | ||
940 | status); | ||
941 | bcnt = 0; | ||
942 | } | ||
918 | /* Reset SCSI buffer count for next round of posting */ | 943 | /* Reset SCSI buffer count for next round of posting */ |
919 | while (!list_empty(&sblist)) { | 944 | while (!list_empty(&sblist)) { |
920 | list_remove_head(&sblist, psb, struct lpfc_scsi_buf, | 945 | list_remove_head(&sblist, psb, struct lpfc_scsi_buf, |
@@ -2081,6 +2106,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
2081 | dma_len = sg_dma_len(sgel); | 2106 | dma_len = sg_dma_len(sgel); |
2082 | sgl->addr_lo = cpu_to_le32(putPaddrLow(physaddr)); | 2107 | sgl->addr_lo = cpu_to_le32(putPaddrLow(physaddr)); |
2083 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(physaddr)); | 2108 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(physaddr)); |
2109 | sgl->word2 = le32_to_cpu(sgl->word2); | ||
2084 | if ((num_bde + 1) == nseg) | 2110 | if ((num_bde + 1) == nseg) |
2085 | bf_set(lpfc_sli4_sge_last, sgl, 1); | 2111 | bf_set(lpfc_sli4_sge_last, sgl, 1); |
2086 | else | 2112 | else |
@@ -2794,6 +2820,9 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
2794 | * of the scsi_cmnd request_buffer | 2820 | * of the scsi_cmnd request_buffer |
2795 | */ | 2821 | */ |
2796 | piocbq->iocb.ulpContext = pnode->nlp_rpi; | 2822 | piocbq->iocb.ulpContext = pnode->nlp_rpi; |
2823 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
2824 | piocbq->iocb.ulpContext = | ||
2825 | phba->sli4_hba.rpi_ids[pnode->nlp_rpi]; | ||
2797 | if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE) | 2826 | if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE) |
2798 | piocbq->iocb.ulpFCP2Rcvy = 1; | 2827 | piocbq->iocb.ulpFCP2Rcvy = 1; |
2799 | else | 2828 | else |
@@ -2807,7 +2836,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
2807 | } | 2836 | } |
2808 | 2837 | ||
2809 | /** | 2838 | /** |
2810 | * lpfc_scsi_prep_task_mgmt_cmnd - Convert SLI3 scsi TM cmd to FCP info unit | 2839 | * lpfc_scsi_prep_task_mgmt_cmd - Convert SLI3 scsi TM cmd to FCP info unit |
2811 | * @vport: The virtual port for which this call is being executed. | 2840 | * @vport: The virtual port for which this call is being executed. |
2812 | * @lpfc_cmd: Pointer to lpfc_scsi_buf data structure. | 2841 | * @lpfc_cmd: Pointer to lpfc_scsi_buf data structure. |
2813 | * @lun: Logical unit number. | 2842 | * @lun: Logical unit number. |
@@ -2851,6 +2880,10 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, | |||
2851 | lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd); | 2880 | lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd); |
2852 | piocb->ulpCommand = CMD_FCP_ICMND64_CR; | 2881 | piocb->ulpCommand = CMD_FCP_ICMND64_CR; |
2853 | piocb->ulpContext = ndlp->nlp_rpi; | 2882 | piocb->ulpContext = ndlp->nlp_rpi; |
2883 | if (vport->phba->sli_rev == LPFC_SLI_REV4) { | ||
2884 | piocb->ulpContext = | ||
2885 | vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | ||
2886 | } | ||
2854 | if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { | 2887 | if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { |
2855 | piocb->ulpFCP2Rcvy = 1; | 2888 | piocb->ulpFCP2Rcvy = 1; |
2856 | } | 2889 | } |
@@ -3405,9 +3438,10 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, | |||
3405 | 3438 | ||
3406 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, | 3439 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, |
3407 | "0702 Issue %s to TGT %d LUN %d " | 3440 | "0702 Issue %s to TGT %d LUN %d " |
3408 | "rpi x%x nlp_flag x%x\n", | 3441 | "rpi x%x nlp_flag x%x Data: x%x x%x\n", |
3409 | lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, | 3442 | lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, |
3410 | pnode->nlp_rpi, pnode->nlp_flag); | 3443 | pnode->nlp_rpi, pnode->nlp_flag, iocbq->sli4_xritag, |
3444 | iocbq->iocb_flag); | ||
3411 | 3445 | ||
3412 | status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING, | 3446 | status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING, |
3413 | iocbq, iocbqrsp, lpfc_cmd->timeout); | 3447 | iocbq, iocbqrsp, lpfc_cmd->timeout); |
@@ -3419,10 +3453,12 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, | |||
3419 | ret = FAILED; | 3453 | ret = FAILED; |
3420 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; | 3454 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; |
3421 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, | 3455 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, |
3422 | "0727 TMF %s to TGT %d LUN %d failed (%d, %d)\n", | 3456 | "0727 TMF %s to TGT %d LUN %d failed (%d, %d) " |
3457 | "iocb_flag x%x\n", | ||
3423 | lpfc_taskmgmt_name(task_mgmt_cmd), | 3458 | lpfc_taskmgmt_name(task_mgmt_cmd), |
3424 | tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, | 3459 | tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, |
3425 | iocbqrsp->iocb.un.ulpWord[4]); | 3460 | iocbqrsp->iocb.un.ulpWord[4], |
3461 | iocbq->iocb_flag); | ||
3426 | } else if (status == IOCB_BUSY) | 3462 | } else if (status == IOCB_BUSY) |
3427 | ret = FAILED; | 3463 | ret = FAILED; |
3428 | else | 3464 | else |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index fd5835e1c039..98999bbd8cbf 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -65,6 +65,9 @@ static struct lpfc_iocbq *lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *, | |||
65 | struct lpfc_iocbq *); | 65 | struct lpfc_iocbq *); |
66 | static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *, | 66 | static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *, |
67 | struct hbq_dmabuf *); | 67 | struct hbq_dmabuf *); |
68 | static int lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *, struct lpfc_queue *, | ||
69 | struct lpfc_cqe *); | ||
70 | |||
68 | static IOCB_t * | 71 | static IOCB_t * |
69 | lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) | 72 | lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) |
70 | { | 73 | { |
@@ -456,7 +459,6 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba) | |||
456 | struct lpfc_iocbq * iocbq = NULL; | 459 | struct lpfc_iocbq * iocbq = NULL; |
457 | 460 | ||
458 | list_remove_head(lpfc_iocb_list, iocbq, struct lpfc_iocbq, list); | 461 | list_remove_head(lpfc_iocb_list, iocbq, struct lpfc_iocbq, list); |
459 | |||
460 | if (iocbq) | 462 | if (iocbq) |
461 | phba->iocb_cnt++; | 463 | phba->iocb_cnt++; |
462 | if (phba->iocb_cnt > phba->iocb_max) | 464 | if (phba->iocb_cnt > phba->iocb_max) |
@@ -479,13 +481,10 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba) | |||
479 | static struct lpfc_sglq * | 481 | static struct lpfc_sglq * |
480 | __lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xritag) | 482 | __lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xritag) |
481 | { | 483 | { |
482 | uint16_t adj_xri; | ||
483 | struct lpfc_sglq *sglq; | 484 | struct lpfc_sglq *sglq; |
484 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | 485 | |
485 | if (adj_xri > phba->sli4_hba.max_cfg_param.max_xri) | 486 | sglq = phba->sli4_hba.lpfc_sglq_active_list[xritag]; |
486 | return NULL; | 487 | phba->sli4_hba.lpfc_sglq_active_list[xritag] = NULL; |
487 | sglq = phba->sli4_hba.lpfc_sglq_active_list[adj_xri]; | ||
488 | phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = NULL; | ||
489 | return sglq; | 488 | return sglq; |
490 | } | 489 | } |
491 | 490 | ||
@@ -504,12 +503,9 @@ __lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xritag) | |||
504 | struct lpfc_sglq * | 503 | struct lpfc_sglq * |
505 | __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag) | 504 | __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag) |
506 | { | 505 | { |
507 | uint16_t adj_xri; | ||
508 | struct lpfc_sglq *sglq; | 506 | struct lpfc_sglq *sglq; |
509 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | 507 | |
510 | if (adj_xri > phba->sli4_hba.max_cfg_param.max_xri) | 508 | sglq = phba->sli4_hba.lpfc_sglq_active_list[xritag]; |
511 | return NULL; | ||
512 | sglq = phba->sli4_hba.lpfc_sglq_active_list[adj_xri]; | ||
513 | return sglq; | 509 | return sglq; |
514 | } | 510 | } |
515 | 511 | ||
@@ -532,7 +528,6 @@ static int | |||
532 | __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | 528 | __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, |
533 | uint16_t xritag, uint16_t rxid, uint16_t send_rrq) | 529 | uint16_t xritag, uint16_t rxid, uint16_t send_rrq) |
534 | { | 530 | { |
535 | uint16_t adj_xri; | ||
536 | struct lpfc_node_rrq *rrq; | 531 | struct lpfc_node_rrq *rrq; |
537 | int empty; | 532 | int empty; |
538 | uint32_t did = 0; | 533 | uint32_t did = 0; |
@@ -553,21 +548,19 @@ __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
553 | /* | 548 | /* |
554 | * set the active bit even if there is no mem available. | 549 | * set the active bit even if there is no mem available. |
555 | */ | 550 | */ |
556 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | ||
557 | |||
558 | if (NLP_CHK_FREE_REQ(ndlp)) | 551 | if (NLP_CHK_FREE_REQ(ndlp)) |
559 | goto out; | 552 | goto out; |
560 | 553 | ||
561 | if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING)) | 554 | if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING)) |
562 | goto out; | 555 | goto out; |
563 | 556 | ||
564 | if (test_and_set_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) | 557 | if (test_and_set_bit(xritag, ndlp->active_rrqs.xri_bitmap)) |
565 | goto out; | 558 | goto out; |
566 | 559 | ||
567 | rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL); | 560 | rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL); |
568 | if (rrq) { | 561 | if (rrq) { |
569 | rrq->send_rrq = send_rrq; | 562 | rrq->send_rrq = send_rrq; |
570 | rrq->xritag = xritag; | 563 | rrq->xritag = phba->sli4_hba.xri_ids[xritag]; |
571 | rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1); | 564 | rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1); |
572 | rrq->ndlp = ndlp; | 565 | rrq->ndlp = ndlp; |
573 | rrq->nlp_DID = ndlp->nlp_DID; | 566 | rrq->nlp_DID = ndlp->nlp_DID; |
@@ -603,7 +596,6 @@ lpfc_clr_rrq_active(struct lpfc_hba *phba, | |||
603 | uint16_t xritag, | 596 | uint16_t xritag, |
604 | struct lpfc_node_rrq *rrq) | 597 | struct lpfc_node_rrq *rrq) |
605 | { | 598 | { |
606 | uint16_t adj_xri; | ||
607 | struct lpfc_nodelist *ndlp = NULL; | 599 | struct lpfc_nodelist *ndlp = NULL; |
608 | 600 | ||
609 | if ((rrq->vport) && NLP_CHK_NODE_ACT(rrq->ndlp)) | 601 | if ((rrq->vport) && NLP_CHK_NODE_ACT(rrq->ndlp)) |
@@ -619,8 +611,7 @@ lpfc_clr_rrq_active(struct lpfc_hba *phba, | |||
619 | if (!ndlp) | 611 | if (!ndlp) |
620 | goto out; | 612 | goto out; |
621 | 613 | ||
622 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | 614 | if (test_and_clear_bit(xritag, ndlp->active_rrqs.xri_bitmap)) { |
623 | if (test_and_clear_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) { | ||
624 | rrq->send_rrq = 0; | 615 | rrq->send_rrq = 0; |
625 | rrq->xritag = 0; | 616 | rrq->xritag = 0; |
626 | rrq->rrq_stop_time = 0; | 617 | rrq->rrq_stop_time = 0; |
@@ -796,12 +787,9 @@ int | |||
796 | lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | 787 | lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, |
797 | uint16_t xritag) | 788 | uint16_t xritag) |
798 | { | 789 | { |
799 | uint16_t adj_xri; | ||
800 | |||
801 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | ||
802 | if (!ndlp) | 790 | if (!ndlp) |
803 | return 0; | 791 | return 0; |
804 | if (test_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) | 792 | if (test_bit(xritag, ndlp->active_rrqs.xri_bitmap)) |
805 | return 1; | 793 | return 1; |
806 | else | 794 | else |
807 | return 0; | 795 | return 0; |
@@ -841,7 +829,7 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
841 | * @piocb: Pointer to the iocbq. | 829 | * @piocb: Pointer to the iocbq. |
842 | * | 830 | * |
843 | * This function is called with hbalock held. This function | 831 | * This function is called with hbalock held. This function |
844 | * Gets a new driver sglq object from the sglq list. If the | 832 | * gets a new driver sglq object from the sglq list. If the |
845 | * list is not empty then it is successful, it returns pointer to the newly | 833 | * list is not empty then it is successful, it returns pointer to the newly |
846 | * allocated sglq object else it returns NULL. | 834 | * allocated sglq object else it returns NULL. |
847 | **/ | 835 | **/ |
@@ -851,7 +839,6 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) | |||
851 | struct list_head *lpfc_sgl_list = &phba->sli4_hba.lpfc_sgl_list; | 839 | struct list_head *lpfc_sgl_list = &phba->sli4_hba.lpfc_sgl_list; |
852 | struct lpfc_sglq *sglq = NULL; | 840 | struct lpfc_sglq *sglq = NULL; |
853 | struct lpfc_sglq *start_sglq = NULL; | 841 | struct lpfc_sglq *start_sglq = NULL; |
854 | uint16_t adj_xri; | ||
855 | struct lpfc_scsi_buf *lpfc_cmd; | 842 | struct lpfc_scsi_buf *lpfc_cmd; |
856 | struct lpfc_nodelist *ndlp; | 843 | struct lpfc_nodelist *ndlp; |
857 | int found = 0; | 844 | int found = 0; |
@@ -870,8 +857,6 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) | |||
870 | while (!found) { | 857 | while (!found) { |
871 | if (!sglq) | 858 | if (!sglq) |
872 | return NULL; | 859 | return NULL; |
873 | adj_xri = sglq->sli4_xritag - | ||
874 | phba->sli4_hba.max_cfg_param.xri_base; | ||
875 | if (lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) { | 860 | if (lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) { |
876 | /* This xri has an rrq outstanding for this DID. | 861 | /* This xri has an rrq outstanding for this DID. |
877 | * put it back in the list and get another xri. | 862 | * put it back in the list and get another xri. |
@@ -888,7 +873,7 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) | |||
888 | } | 873 | } |
889 | sglq->ndlp = ndlp; | 874 | sglq->ndlp = ndlp; |
890 | found = 1; | 875 | found = 1; |
891 | phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = sglq; | 876 | phba->sli4_hba.lpfc_sglq_active_list[sglq->sli4_lxritag] = sglq; |
892 | sglq->state = SGL_ALLOCATED; | 877 | sglq->state = SGL_ALLOCATED; |
893 | } | 878 | } |
894 | return sglq; | 879 | return sglq; |
@@ -944,7 +929,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
944 | if (iocbq->sli4_xritag == NO_XRI) | 929 | if (iocbq->sli4_xritag == NO_XRI) |
945 | sglq = NULL; | 930 | sglq = NULL; |
946 | else | 931 | else |
947 | sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag); | 932 | sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_lxritag); |
933 | |||
948 | if (sglq) { | 934 | if (sglq) { |
949 | if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) && | 935 | if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) && |
950 | (sglq->state != SGL_XRI_ABORTED)) { | 936 | (sglq->state != SGL_XRI_ABORTED)) { |
@@ -971,6 +957,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
971 | * Clean all volatile data fields, preserve iotag and node struct. | 957 | * Clean all volatile data fields, preserve iotag and node struct. |
972 | */ | 958 | */ |
973 | memset((char *)iocbq + start_clean, 0, sizeof(*iocbq) - start_clean); | 959 | memset((char *)iocbq + start_clean, 0, sizeof(*iocbq) - start_clean); |
960 | iocbq->sli4_lxritag = NO_XRI; | ||
974 | iocbq->sli4_xritag = NO_XRI; | 961 | iocbq->sli4_xritag = NO_XRI; |
975 | list_add_tail(&iocbq->list, &phba->lpfc_iocb_list); | 962 | list_add_tail(&iocbq->list, &phba->lpfc_iocb_list); |
976 | } | 963 | } |
@@ -2113,7 +2100,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2113 | pmb->u.mb.mbxCommand == MBX_REG_LOGIN64 && | 2100 | pmb->u.mb.mbxCommand == MBX_REG_LOGIN64 && |
2114 | !pmb->u.mb.mbxStatus) { | 2101 | !pmb->u.mb.mbxStatus) { |
2115 | rpi = pmb->u.mb.un.varWords[0]; | 2102 | rpi = pmb->u.mb.un.varWords[0]; |
2116 | vpi = pmb->u.mb.un.varRegLogin.vpi - phba->vpi_base; | 2103 | vpi = pmb->u.mb.un.varRegLogin.vpi; |
2117 | lpfc_unreg_login(phba, vpi, rpi, pmb); | 2104 | lpfc_unreg_login(phba, vpi, rpi, pmb); |
2118 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 2105 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
2119 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | 2106 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); |
@@ -3881,8 +3868,10 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba) | |||
3881 | list_del_init(&phba->sli4_hba.els_cq->list); | 3868 | list_del_init(&phba->sli4_hba.els_cq->list); |
3882 | for (qindx = 0; qindx < phba->cfg_fcp_wq_count; qindx++) | 3869 | for (qindx = 0; qindx < phba->cfg_fcp_wq_count; qindx++) |
3883 | list_del_init(&phba->sli4_hba.fcp_wq[qindx]->list); | 3870 | list_del_init(&phba->sli4_hba.fcp_wq[qindx]->list); |
3884 | for (qindx = 0; qindx < phba->cfg_fcp_eq_count; qindx++) | 3871 | qindx = 0; |
3872 | do | ||
3885 | list_del_init(&phba->sli4_hba.fcp_cq[qindx]->list); | 3873 | list_del_init(&phba->sli4_hba.fcp_cq[qindx]->list); |
3874 | while (++qindx < phba->cfg_fcp_eq_count); | ||
3886 | spin_unlock_irq(&phba->hbalock); | 3875 | spin_unlock_irq(&phba->hbalock); |
3887 | 3876 | ||
3888 | /* Now physically reset the device */ | 3877 | /* Now physically reset the device */ |
@@ -4318,6 +4307,7 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) | |||
4318 | continue; | 4307 | continue; |
4319 | } else if (rc) | 4308 | } else if (rc) |
4320 | break; | 4309 | break; |
4310 | |||
4321 | phba->link_state = LPFC_INIT_MBX_CMDS; | 4311 | phba->link_state = LPFC_INIT_MBX_CMDS; |
4322 | lpfc_config_port(phba, pmb); | 4312 | lpfc_config_port(phba, pmb); |
4323 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); | 4313 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); |
@@ -4421,7 +4411,8 @@ int | |||
4421 | lpfc_sli_hba_setup(struct lpfc_hba *phba) | 4411 | lpfc_sli_hba_setup(struct lpfc_hba *phba) |
4422 | { | 4412 | { |
4423 | uint32_t rc; | 4413 | uint32_t rc; |
4424 | int mode = 3; | 4414 | int mode = 3, i; |
4415 | int longs; | ||
4425 | 4416 | ||
4426 | switch (lpfc_sli_mode) { | 4417 | switch (lpfc_sli_mode) { |
4427 | case 2: | 4418 | case 2: |
@@ -4491,6 +4482,35 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) | |||
4491 | if (rc) | 4482 | if (rc) |
4492 | goto lpfc_sli_hba_setup_error; | 4483 | goto lpfc_sli_hba_setup_error; |
4493 | 4484 | ||
4485 | /* Initialize VPIs. */ | ||
4486 | if (phba->sli_rev == LPFC_SLI_REV3) { | ||
4487 | /* | ||
4488 | * The VPI bitmask and physical ID array are allocated | ||
4489 | * and initialized once only - at driver load. A port | ||
4490 | * reset doesn't need to reinitialize this memory. | ||
4491 | */ | ||
4492 | if ((phba->vpi_bmask == NULL) && (phba->vpi_ids == NULL)) { | ||
4493 | longs = (phba->max_vpi + BITS_PER_LONG) / BITS_PER_LONG; | ||
4494 | phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), | ||
4495 | GFP_KERNEL); | ||
4496 | if (!phba->vpi_bmask) { | ||
4497 | rc = -ENOMEM; | ||
4498 | goto lpfc_sli_hba_setup_error; | ||
4499 | } | ||
4500 | |||
4501 | phba->vpi_ids = kzalloc( | ||
4502 | (phba->max_vpi+1) * sizeof(uint16_t), | ||
4503 | GFP_KERNEL); | ||
4504 | if (!phba->vpi_ids) { | ||
4505 | kfree(phba->vpi_bmask); | ||
4506 | rc = -ENOMEM; | ||
4507 | goto lpfc_sli_hba_setup_error; | ||
4508 | } | ||
4509 | for (i = 0; i < phba->max_vpi; i++) | ||
4510 | phba->vpi_ids[i] = i; | ||
4511 | } | ||
4512 | } | ||
4513 | |||
4494 | /* Init HBQs */ | 4514 | /* Init HBQs */ |
4495 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { | 4515 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { |
4496 | rc = lpfc_sli_hbq_setup(phba); | 4516 | rc = lpfc_sli_hbq_setup(phba); |
@@ -4677,9 +4697,11 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) | |||
4677 | 4697 | ||
4678 | lpfc_sli4_cq_release(phba->sli4_hba.mbx_cq, LPFC_QUEUE_REARM); | 4698 | lpfc_sli4_cq_release(phba->sli4_hba.mbx_cq, LPFC_QUEUE_REARM); |
4679 | lpfc_sli4_cq_release(phba->sli4_hba.els_cq, LPFC_QUEUE_REARM); | 4699 | lpfc_sli4_cq_release(phba->sli4_hba.els_cq, LPFC_QUEUE_REARM); |
4680 | for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) | 4700 | fcp_eqidx = 0; |
4701 | do | ||
4681 | lpfc_sli4_cq_release(phba->sli4_hba.fcp_cq[fcp_eqidx], | 4702 | lpfc_sli4_cq_release(phba->sli4_hba.fcp_cq[fcp_eqidx], |
4682 | LPFC_QUEUE_REARM); | 4703 | LPFC_QUEUE_REARM); |
4704 | while (++fcp_eqidx < phba->cfg_fcp_eq_count); | ||
4683 | lpfc_sli4_eq_release(phba->sli4_hba.sp_eq, LPFC_QUEUE_REARM); | 4705 | lpfc_sli4_eq_release(phba->sli4_hba.sp_eq, LPFC_QUEUE_REARM); |
4684 | for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) | 4706 | for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) |
4685 | lpfc_sli4_eq_release(phba->sli4_hba.fp_eq[fcp_eqidx], | 4707 | lpfc_sli4_eq_release(phba->sli4_hba.fp_eq[fcp_eqidx], |
@@ -4687,6 +4709,803 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) | |||
4687 | } | 4709 | } |
4688 | 4710 | ||
4689 | /** | 4711 | /** |
4712 | * lpfc_sli4_get_avail_extnt_rsrc - Get available resource extent count. | ||
4713 | * @phba: Pointer to HBA context object. | ||
4714 | * @type: The resource extent type. | ||
4715 | * | ||
4716 | * This function allocates all SLI4 resource identifiers. | ||
4717 | **/ | ||
4718 | static int | ||
4719 | lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type, | ||
4720 | uint16_t *extnt_count, uint16_t *extnt_size) | ||
4721 | { | ||
4722 | int rc = 0; | ||
4723 | uint32_t length; | ||
4724 | uint32_t mbox_tmo; | ||
4725 | struct lpfc_mbx_get_rsrc_extent_info *rsrc_info; | ||
4726 | LPFC_MBOXQ_t *mbox; | ||
4727 | |||
4728 | mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
4729 | if (!mbox) | ||
4730 | return -ENOMEM; | ||
4731 | |||
4732 | /* Find out how many extents are available for this resource type */ | ||
4733 | length = (sizeof(struct lpfc_mbx_get_rsrc_extent_info) - | ||
4734 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
4735 | lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
4736 | LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO, | ||
4737 | length, LPFC_SLI4_MBX_EMBED); | ||
4738 | |||
4739 | /* Send an extents count of 0 - the GET doesn't use it. */ | ||
4740 | rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, 0, type, | ||
4741 | LPFC_SLI4_MBX_EMBED); | ||
4742 | if (unlikely(rc)) { | ||
4743 | rc = -EIO; | ||
4744 | goto err_exit; | ||
4745 | } | ||
4746 | |||
4747 | if (!phba->sli4_hba.intr_enable) | ||
4748 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
4749 | else { | ||
4750 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
4751 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
4752 | } | ||
4753 | if (unlikely(rc)) { | ||
4754 | rc = -EIO; | ||
4755 | goto err_exit; | ||
4756 | } | ||
4757 | |||
4758 | rsrc_info = &mbox->u.mqe.un.rsrc_extent_info; | ||
4759 | if (bf_get(lpfc_mbox_hdr_status, | ||
4760 | &rsrc_info->header.cfg_shdr.response)) { | ||
4761 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, | ||
4762 | "2930 Failed to get resource extents " | ||
4763 | "Status 0x%x Add'l Status 0x%x\n", | ||
4764 | bf_get(lpfc_mbox_hdr_status, | ||
4765 | &rsrc_info->header.cfg_shdr.response), | ||
4766 | bf_get(lpfc_mbox_hdr_add_status, | ||
4767 | &rsrc_info->header.cfg_shdr.response)); | ||
4768 | rc = -EIO; | ||
4769 | goto err_exit; | ||
4770 | } | ||
4771 | |||
4772 | *extnt_count = bf_get(lpfc_mbx_get_rsrc_extent_info_cnt, | ||
4773 | &rsrc_info->u.rsp); | ||
4774 | *extnt_size = bf_get(lpfc_mbx_get_rsrc_extent_info_size, | ||
4775 | &rsrc_info->u.rsp); | ||
4776 | err_exit: | ||
4777 | mempool_free(mbox, phba->mbox_mem_pool); | ||
4778 | return rc; | ||
4779 | } | ||
4780 | |||
4781 | /** | ||
4782 | * lpfc_sli4_chk_avail_extnt_rsrc - Check for available SLI4 resource extents. | ||
4783 | * @phba: Pointer to HBA context object. | ||
4784 | * @type: The extent type to check. | ||
4785 | * | ||
4786 | * This function reads the current available extents from the port and checks | ||
4787 | * if the extent count or extent size has changed since the last access. | ||
4788 | * Callers use this routine post port reset to understand if there is a | ||
4789 | * extent reprovisioning requirement. | ||
4790 | * | ||
4791 | * Returns: | ||
4792 | * -Error: error indicates problem. | ||
4793 | * 1: Extent count or size has changed. | ||
4794 | * 0: No changes. | ||
4795 | **/ | ||
4796 | static int | ||
4797 | lpfc_sli4_chk_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type) | ||
4798 | { | ||
4799 | uint16_t curr_ext_cnt, rsrc_ext_cnt; | ||
4800 | uint16_t size_diff, rsrc_ext_size; | ||
4801 | int rc = 0; | ||
4802 | struct lpfc_rsrc_blks *rsrc_entry; | ||
4803 | struct list_head *rsrc_blk_list = NULL; | ||
4804 | |||
4805 | size_diff = 0; | ||
4806 | curr_ext_cnt = 0; | ||
4807 | rc = lpfc_sli4_get_avail_extnt_rsrc(phba, type, | ||
4808 | &rsrc_ext_cnt, | ||
4809 | &rsrc_ext_size); | ||
4810 | if (unlikely(rc)) | ||
4811 | return -EIO; | ||
4812 | |||
4813 | switch (type) { | ||
4814 | case LPFC_RSC_TYPE_FCOE_RPI: | ||
4815 | rsrc_blk_list = &phba->sli4_hba.lpfc_rpi_blk_list; | ||
4816 | break; | ||
4817 | case LPFC_RSC_TYPE_FCOE_VPI: | ||
4818 | rsrc_blk_list = &phba->lpfc_vpi_blk_list; | ||
4819 | break; | ||
4820 | case LPFC_RSC_TYPE_FCOE_XRI: | ||
4821 | rsrc_blk_list = &phba->sli4_hba.lpfc_xri_blk_list; | ||
4822 | break; | ||
4823 | case LPFC_RSC_TYPE_FCOE_VFI: | ||
4824 | rsrc_blk_list = &phba->sli4_hba.lpfc_vfi_blk_list; | ||
4825 | break; | ||
4826 | default: | ||
4827 | break; | ||
4828 | } | ||
4829 | |||
4830 | list_for_each_entry(rsrc_entry, rsrc_blk_list, list) { | ||
4831 | curr_ext_cnt++; | ||
4832 | if (rsrc_entry->rsrc_size != rsrc_ext_size) | ||
4833 | size_diff++; | ||
4834 | } | ||
4835 | |||
4836 | if (curr_ext_cnt != rsrc_ext_cnt || size_diff != 0) | ||
4837 | rc = 1; | ||
4838 | |||
4839 | return rc; | ||
4840 | } | ||
4841 | |||
4842 | /** | ||
4843 | * lpfc_sli4_cfg_post_extnts - | ||
4844 | * @phba: Pointer to HBA context object. | ||
4845 | * @extnt_cnt - number of available extents. | ||
4846 | * @type - the extent type (rpi, xri, vfi, vpi). | ||
4847 | * @emb - buffer to hold either MBX_EMBED or MBX_NEMBED operation. | ||
4848 | * @mbox - pointer to the caller's allocated mailbox structure. | ||
4849 | * | ||
4850 | * This function executes the extents allocation request. It also | ||
4851 | * takes care of the amount of memory needed to allocate or get the | ||
4852 | * allocated extents. It is the caller's responsibility to evaluate | ||
4853 | * the response. | ||
4854 | * | ||
4855 | * Returns: | ||
4856 | * -Error: Error value describes the condition found. | ||
4857 | * 0: if successful | ||
4858 | **/ | ||
4859 | static int | ||
4860 | lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt, | ||
4861 | uint16_t type, bool *emb, LPFC_MBOXQ_t *mbox) | ||
4862 | { | ||
4863 | int rc = 0; | ||
4864 | uint32_t req_len; | ||
4865 | uint32_t emb_len; | ||
4866 | uint32_t alloc_len, mbox_tmo; | ||
4867 | |||
4868 | /* Calculate the total requested length of the dma memory */ | ||
4869 | req_len = *extnt_cnt * sizeof(uint16_t); | ||
4870 | |||
4871 | /* | ||
4872 | * Calculate the size of an embedded mailbox. The uint32_t | ||
4873 | * accounts for extents-specific word. | ||
4874 | */ | ||
4875 | emb_len = sizeof(MAILBOX_t) - sizeof(struct mbox_header) - | ||
4876 | sizeof(uint32_t); | ||
4877 | |||
4878 | /* | ||
4879 | * Presume the allocation and response will fit into an embedded | ||
4880 | * mailbox. If not true, reconfigure to a non-embedded mailbox. | ||
4881 | */ | ||
4882 | *emb = LPFC_SLI4_MBX_EMBED; | ||
4883 | if (req_len > emb_len) { | ||
4884 | req_len = *extnt_cnt * sizeof(uint16_t) + | ||
4885 | sizeof(union lpfc_sli4_cfg_shdr) + | ||
4886 | sizeof(uint32_t); | ||
4887 | *emb = LPFC_SLI4_MBX_NEMBED; | ||
4888 | } | ||
4889 | |||
4890 | alloc_len = lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
4891 | LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT, | ||
4892 | req_len, *emb); | ||
4893 | if (alloc_len < req_len) { | ||
4894 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
4895 | "9000 Allocated DMA memory size (x%x) is " | ||
4896 | "less than the requested DMA memory " | ||
4897 | "size (x%x)\n", alloc_len, req_len); | ||
4898 | return -ENOMEM; | ||
4899 | } | ||
4900 | rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, *extnt_cnt, type, *emb); | ||
4901 | if (unlikely(rc)) | ||
4902 | return -EIO; | ||
4903 | |||
4904 | if (!phba->sli4_hba.intr_enable) | ||
4905 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
4906 | else { | ||
4907 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
4908 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
4909 | } | ||
4910 | |||
4911 | if (unlikely(rc)) | ||
4912 | rc = -EIO; | ||
4913 | return rc; | ||
4914 | } | ||
4915 | |||
4916 | /** | ||
4917 | * lpfc_sli4_alloc_extent - Allocate an SLI4 resource extent. | ||
4918 | * @phba: Pointer to HBA context object. | ||
4919 | * @type: The resource extent type to allocate. | ||
4920 | * | ||
4921 | * This function allocates the number of elements for the specified | ||
4922 | * resource type. | ||
4923 | **/ | ||
4924 | static int | ||
4925 | lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type) | ||
4926 | { | ||
4927 | bool emb = false; | ||
4928 | uint16_t rsrc_id_cnt, rsrc_cnt, rsrc_size; | ||
4929 | uint16_t rsrc_id, rsrc_start, j, k; | ||
4930 | uint16_t *ids; | ||
4931 | int i, rc; | ||
4932 | unsigned long longs; | ||
4933 | unsigned long *bmask; | ||
4934 | struct lpfc_rsrc_blks *rsrc_blks; | ||
4935 | LPFC_MBOXQ_t *mbox; | ||
4936 | uint32_t length; | ||
4937 | struct lpfc_id_range *id_array = NULL; | ||
4938 | void *virtaddr = NULL; | ||
4939 | struct lpfc_mbx_nembed_rsrc_extent *n_rsrc; | ||
4940 | struct lpfc_mbx_alloc_rsrc_extents *rsrc_ext; | ||
4941 | struct list_head *ext_blk_list; | ||
4942 | |||
4943 | rc = lpfc_sli4_get_avail_extnt_rsrc(phba, type, | ||
4944 | &rsrc_cnt, | ||
4945 | &rsrc_size); | ||
4946 | if (unlikely(rc)) | ||
4947 | return -EIO; | ||
4948 | |||
4949 | if ((rsrc_cnt == 0) || (rsrc_size == 0)) { | ||
4950 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, | ||
4951 | "3009 No available Resource Extents " | ||
4952 | "for resource type 0x%x: Count: 0x%x, " | ||
4953 | "Size 0x%x\n", type, rsrc_cnt, | ||
4954 | rsrc_size); | ||
4955 | return -ENOMEM; | ||
4956 | } | ||
4957 | |||
4958 | lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_INIT, | ||
4959 | "2903 Available Resource Extents " | ||
4960 | "for resource type 0x%x: Count: 0x%x, " | ||
4961 | "Size 0x%x\n", type, rsrc_cnt, | ||
4962 | rsrc_size); | ||
4963 | |||
4964 | mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
4965 | if (!mbox) | ||
4966 | return -ENOMEM; | ||
4967 | |||
4968 | rc = lpfc_sli4_cfg_post_extnts(phba, &rsrc_cnt, type, &emb, mbox); | ||
4969 | if (unlikely(rc)) { | ||
4970 | rc = -EIO; | ||
4971 | goto err_exit; | ||
4972 | } | ||
4973 | |||
4974 | /* | ||
4975 | * Figure out where the response is located. Then get local pointers | ||
4976 | * to the response data. The port does not guarantee to respond to | ||
4977 | * all extents counts request so update the local variable with the | ||
4978 | * allocated count from the port. | ||
4979 | */ | ||
4980 | if (emb == LPFC_SLI4_MBX_EMBED) { | ||
4981 | rsrc_ext = &mbox->u.mqe.un.alloc_rsrc_extents; | ||
4982 | id_array = &rsrc_ext->u.rsp.id[0]; | ||
4983 | rsrc_cnt = bf_get(lpfc_mbx_rsrc_cnt, &rsrc_ext->u.rsp); | ||
4984 | } else { | ||
4985 | virtaddr = mbox->sge_array->addr[0]; | ||
4986 | n_rsrc = (struct lpfc_mbx_nembed_rsrc_extent *) virtaddr; | ||
4987 | rsrc_cnt = bf_get(lpfc_mbx_rsrc_cnt, n_rsrc); | ||
4988 | id_array = &n_rsrc->id; | ||
4989 | } | ||
4990 | |||
4991 | longs = ((rsrc_cnt * rsrc_size) + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
4992 | rsrc_id_cnt = rsrc_cnt * rsrc_size; | ||
4993 | |||
4994 | /* | ||
4995 | * Based on the resource size and count, correct the base and max | ||
4996 | * resource values. | ||
4997 | */ | ||
4998 | length = sizeof(struct lpfc_rsrc_blks); | ||
4999 | switch (type) { | ||
5000 | case LPFC_RSC_TYPE_FCOE_RPI: | ||
5001 | phba->sli4_hba.rpi_bmask = kzalloc(longs * | ||
5002 | sizeof(unsigned long), | ||
5003 | GFP_KERNEL); | ||
5004 | if (unlikely(!phba->sli4_hba.rpi_bmask)) { | ||
5005 | rc = -ENOMEM; | ||
5006 | goto err_exit; | ||
5007 | } | ||
5008 | phba->sli4_hba.rpi_ids = kzalloc(rsrc_id_cnt * | ||
5009 | sizeof(uint16_t), | ||
5010 | GFP_KERNEL); | ||
5011 | if (unlikely(!phba->sli4_hba.rpi_ids)) { | ||
5012 | kfree(phba->sli4_hba.rpi_bmask); | ||
5013 | rc = -ENOMEM; | ||
5014 | goto err_exit; | ||
5015 | } | ||
5016 | |||
5017 | /* | ||
5018 | * The next_rpi was initialized with the maximum available | ||
5019 | * count but the port may allocate a smaller number. Catch | ||
5020 | * that case and update the next_rpi. | ||
5021 | */ | ||
5022 | phba->sli4_hba.next_rpi = rsrc_id_cnt; | ||
5023 | |||
5024 | /* Initialize local ptrs for common extent processing later. */ | ||
5025 | bmask = phba->sli4_hba.rpi_bmask; | ||
5026 | ids = phba->sli4_hba.rpi_ids; | ||
5027 | ext_blk_list = &phba->sli4_hba.lpfc_rpi_blk_list; | ||
5028 | break; | ||
5029 | case LPFC_RSC_TYPE_FCOE_VPI: | ||
5030 | phba->vpi_bmask = kzalloc(longs * | ||
5031 | sizeof(unsigned long), | ||
5032 | GFP_KERNEL); | ||
5033 | if (unlikely(!phba->vpi_bmask)) { | ||
5034 | rc = -ENOMEM; | ||
5035 | goto err_exit; | ||
5036 | } | ||
5037 | phba->vpi_ids = kzalloc(rsrc_id_cnt * | ||
5038 | sizeof(uint16_t), | ||
5039 | GFP_KERNEL); | ||
5040 | if (unlikely(!phba->vpi_ids)) { | ||
5041 | kfree(phba->vpi_bmask); | ||
5042 | rc = -ENOMEM; | ||
5043 | goto err_exit; | ||
5044 | } | ||
5045 | |||
5046 | /* Initialize local ptrs for common extent processing later. */ | ||
5047 | bmask = phba->vpi_bmask; | ||
5048 | ids = phba->vpi_ids; | ||
5049 | ext_blk_list = &phba->lpfc_vpi_blk_list; | ||
5050 | break; | ||
5051 | case LPFC_RSC_TYPE_FCOE_XRI: | ||
5052 | phba->sli4_hba.xri_bmask = kzalloc(longs * | ||
5053 | sizeof(unsigned long), | ||
5054 | GFP_KERNEL); | ||
5055 | if (unlikely(!phba->sli4_hba.xri_bmask)) { | ||
5056 | rc = -ENOMEM; | ||
5057 | goto err_exit; | ||
5058 | } | ||
5059 | phba->sli4_hba.xri_ids = kzalloc(rsrc_id_cnt * | ||
5060 | sizeof(uint16_t), | ||
5061 | GFP_KERNEL); | ||
5062 | if (unlikely(!phba->sli4_hba.xri_ids)) { | ||
5063 | kfree(phba->sli4_hba.xri_bmask); | ||
5064 | rc = -ENOMEM; | ||
5065 | goto err_exit; | ||
5066 | } | ||
5067 | |||
5068 | /* Initialize local ptrs for common extent processing later. */ | ||
5069 | bmask = phba->sli4_hba.xri_bmask; | ||
5070 | ids = phba->sli4_hba.xri_ids; | ||
5071 | ext_blk_list = &phba->sli4_hba.lpfc_xri_blk_list; | ||
5072 | break; | ||
5073 | case LPFC_RSC_TYPE_FCOE_VFI: | ||
5074 | phba->sli4_hba.vfi_bmask = kzalloc(longs * | ||
5075 | sizeof(unsigned long), | ||
5076 | GFP_KERNEL); | ||
5077 | if (unlikely(!phba->sli4_hba.vfi_bmask)) { | ||
5078 | rc = -ENOMEM; | ||
5079 | goto err_exit; | ||
5080 | } | ||
5081 | phba->sli4_hba.vfi_ids = kzalloc(rsrc_id_cnt * | ||
5082 | sizeof(uint16_t), | ||
5083 | GFP_KERNEL); | ||
5084 | if (unlikely(!phba->sli4_hba.vfi_ids)) { | ||
5085 | kfree(phba->sli4_hba.vfi_bmask); | ||
5086 | rc = -ENOMEM; | ||
5087 | goto err_exit; | ||
5088 | } | ||
5089 | |||
5090 | /* Initialize local ptrs for common extent processing later. */ | ||
5091 | bmask = phba->sli4_hba.vfi_bmask; | ||
5092 | ids = phba->sli4_hba.vfi_ids; | ||
5093 | ext_blk_list = &phba->sli4_hba.lpfc_vfi_blk_list; | ||
5094 | break; | ||
5095 | default: | ||
5096 | /* Unsupported Opcode. Fail call. */ | ||
5097 | id_array = NULL; | ||
5098 | bmask = NULL; | ||
5099 | ids = NULL; | ||
5100 | ext_blk_list = NULL; | ||
5101 | goto err_exit; | ||
5102 | } | ||
5103 | |||
5104 | /* | ||
5105 | * Complete initializing the extent configuration with the | ||
5106 | * allocated ids assigned to this function. The bitmask serves | ||
5107 | * as an index into the array and manages the available ids. The | ||
5108 | * array just stores the ids communicated to the port via the wqes. | ||
5109 | */ | ||
5110 | for (i = 0, j = 0, k = 0; i < rsrc_cnt; i++) { | ||
5111 | if ((i % 2) == 0) | ||
5112 | rsrc_id = bf_get(lpfc_mbx_rsrc_id_word4_0, | ||
5113 | &id_array[k]); | ||
5114 | else | ||
5115 | rsrc_id = bf_get(lpfc_mbx_rsrc_id_word4_1, | ||
5116 | &id_array[k]); | ||
5117 | |||
5118 | rsrc_blks = kzalloc(length, GFP_KERNEL); | ||
5119 | if (unlikely(!rsrc_blks)) { | ||
5120 | rc = -ENOMEM; | ||
5121 | kfree(bmask); | ||
5122 | kfree(ids); | ||
5123 | goto err_exit; | ||
5124 | } | ||
5125 | rsrc_blks->rsrc_start = rsrc_id; | ||
5126 | rsrc_blks->rsrc_size = rsrc_size; | ||
5127 | list_add_tail(&rsrc_blks->list, ext_blk_list); | ||
5128 | rsrc_start = rsrc_id; | ||
5129 | if ((type == LPFC_RSC_TYPE_FCOE_XRI) && (j == 0)) | ||
5130 | phba->sli4_hba.scsi_xri_start = rsrc_start + | ||
5131 | lpfc_sli4_get_els_iocb_cnt(phba); | ||
5132 | |||
5133 | while (rsrc_id < (rsrc_start + rsrc_size)) { | ||
5134 | ids[j] = rsrc_id; | ||
5135 | rsrc_id++; | ||
5136 | j++; | ||
5137 | } | ||
5138 | /* Entire word processed. Get next word.*/ | ||
5139 | if ((i % 2) == 1) | ||
5140 | k++; | ||
5141 | } | ||
5142 | err_exit: | ||
5143 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
5144 | return rc; | ||
5145 | } | ||
5146 | |||
5147 | /** | ||
5148 | * lpfc_sli4_dealloc_extent - Deallocate an SLI4 resource extent. | ||
5149 | * @phba: Pointer to HBA context object. | ||
5150 | * @type: the extent's type. | ||
5151 | * | ||
5152 | * This function deallocates all extents of a particular resource type. | ||
5153 | * SLI4 does not allow for deallocating a particular extent range. It | ||
5154 | * is the caller's responsibility to release all kernel memory resources. | ||
5155 | **/ | ||
5156 | static int | ||
5157 | lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type) | ||
5158 | { | ||
5159 | int rc; | ||
5160 | uint32_t length, mbox_tmo = 0; | ||
5161 | LPFC_MBOXQ_t *mbox; | ||
5162 | struct lpfc_mbx_dealloc_rsrc_extents *dealloc_rsrc; | ||
5163 | struct lpfc_rsrc_blks *rsrc_blk, *rsrc_blk_next; | ||
5164 | |||
5165 | mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
5166 | if (!mbox) | ||
5167 | return -ENOMEM; | ||
5168 | |||
5169 | /* | ||
5170 | * This function sends an embedded mailbox because it only sends the | ||
5171 | * the resource type. All extents of this type are released by the | ||
5172 | * port. | ||
5173 | */ | ||
5174 | length = (sizeof(struct lpfc_mbx_dealloc_rsrc_extents) - | ||
5175 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
5176 | lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
5177 | LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT, | ||
5178 | length, LPFC_SLI4_MBX_EMBED); | ||
5179 | |||
5180 | /* Send an extents count of 0 - the dealloc doesn't use it. */ | ||
5181 | rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, 0, type, | ||
5182 | LPFC_SLI4_MBX_EMBED); | ||
5183 | if (unlikely(rc)) { | ||
5184 | rc = -EIO; | ||
5185 | goto out_free_mbox; | ||
5186 | } | ||
5187 | if (!phba->sli4_hba.intr_enable) | ||
5188 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
5189 | else { | ||
5190 | mbox_tmo = lpfc_mbox_tmo_val(phba, mbox_tmo); | ||
5191 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
5192 | } | ||
5193 | if (unlikely(rc)) { | ||
5194 | rc = -EIO; | ||
5195 | goto out_free_mbox; | ||
5196 | } | ||
5197 | |||
5198 | dealloc_rsrc = &mbox->u.mqe.un.dealloc_rsrc_extents; | ||
5199 | if (bf_get(lpfc_mbox_hdr_status, | ||
5200 | &dealloc_rsrc->header.cfg_shdr.response)) { | ||
5201 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, | ||
5202 | "2919 Failed to release resource extents " | ||
5203 | "for type %d - Status 0x%x Add'l Status 0x%x. " | ||
5204 | "Resource memory not released.\n", | ||
5205 | type, | ||
5206 | bf_get(lpfc_mbox_hdr_status, | ||
5207 | &dealloc_rsrc->header.cfg_shdr.response), | ||
5208 | bf_get(lpfc_mbox_hdr_add_status, | ||
5209 | &dealloc_rsrc->header.cfg_shdr.response)); | ||
5210 | rc = -EIO; | ||
5211 | goto out_free_mbox; | ||
5212 | } | ||
5213 | |||
5214 | /* Release kernel memory resources for the specific type. */ | ||
5215 | switch (type) { | ||
5216 | case LPFC_RSC_TYPE_FCOE_VPI: | ||
5217 | kfree(phba->vpi_bmask); | ||
5218 | kfree(phba->vpi_ids); | ||
5219 | bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
5220 | list_for_each_entry_safe(rsrc_blk, rsrc_blk_next, | ||
5221 | &phba->lpfc_vpi_blk_list, list) { | ||
5222 | list_del_init(&rsrc_blk->list); | ||
5223 | kfree(rsrc_blk); | ||
5224 | } | ||
5225 | break; | ||
5226 | case LPFC_RSC_TYPE_FCOE_XRI: | ||
5227 | kfree(phba->sli4_hba.xri_bmask); | ||
5228 | kfree(phba->sli4_hba.xri_ids); | ||
5229 | bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
5230 | list_for_each_entry_safe(rsrc_blk, rsrc_blk_next, | ||
5231 | &phba->sli4_hba.lpfc_xri_blk_list, list) { | ||
5232 | list_del_init(&rsrc_blk->list); | ||
5233 | kfree(rsrc_blk); | ||
5234 | } | ||
5235 | break; | ||
5236 | case LPFC_RSC_TYPE_FCOE_VFI: | ||
5237 | kfree(phba->sli4_hba.vfi_bmask); | ||
5238 | kfree(phba->sli4_hba.vfi_ids); | ||
5239 | bf_set(lpfc_vfi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
5240 | list_for_each_entry_safe(rsrc_blk, rsrc_blk_next, | ||
5241 | &phba->sli4_hba.lpfc_vfi_blk_list, list) { | ||
5242 | list_del_init(&rsrc_blk->list); | ||
5243 | kfree(rsrc_blk); | ||
5244 | } | ||
5245 | break; | ||
5246 | case LPFC_RSC_TYPE_FCOE_RPI: | ||
5247 | /* RPI bitmask and physical id array are cleaned up earlier. */ | ||
5248 | list_for_each_entry_safe(rsrc_blk, rsrc_blk_next, | ||
5249 | &phba->sli4_hba.lpfc_rpi_blk_list, list) { | ||
5250 | list_del_init(&rsrc_blk->list); | ||
5251 | kfree(rsrc_blk); | ||
5252 | } | ||
5253 | break; | ||
5254 | default: | ||
5255 | break; | ||
5256 | } | ||
5257 | |||
5258 | bf_set(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
5259 | |||
5260 | out_free_mbox: | ||
5261 | mempool_free(mbox, phba->mbox_mem_pool); | ||
5262 | return rc; | ||
5263 | } | ||
5264 | |||
5265 | /** | ||
5266 | * lpfc_sli4_alloc_resource_identifiers - Allocate all SLI4 resource extents. | ||
5267 | * @phba: Pointer to HBA context object. | ||
5268 | * | ||
5269 | * This function allocates all SLI4 resource identifiers. | ||
5270 | **/ | ||
5271 | int | ||
5272 | lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) | ||
5273 | { | ||
5274 | int i, rc, error = 0; | ||
5275 | uint16_t count, base; | ||
5276 | unsigned long longs; | ||
5277 | |||
5278 | if (phba->sli4_hba.extents_in_use) { | ||
5279 | /* | ||
5280 | * The port supports resource extents. The XRI, VPI, VFI, RPI | ||
5281 | * resource extent count must be read and allocated before | ||
5282 | * provisioning the resource id arrays. | ||
5283 | */ | ||
5284 | if (bf_get(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags) == | ||
5285 | LPFC_IDX_RSRC_RDY) { | ||
5286 | /* | ||
5287 | * Extent-based resources are set - the driver could | ||
5288 | * be in a port reset. Figure out if any corrective | ||
5289 | * actions need to be taken. | ||
5290 | */ | ||
5291 | rc = lpfc_sli4_chk_avail_extnt_rsrc(phba, | ||
5292 | LPFC_RSC_TYPE_FCOE_VFI); | ||
5293 | if (rc != 0) | ||
5294 | error++; | ||
5295 | rc = lpfc_sli4_chk_avail_extnt_rsrc(phba, | ||
5296 | LPFC_RSC_TYPE_FCOE_VPI); | ||
5297 | if (rc != 0) | ||
5298 | error++; | ||
5299 | rc = lpfc_sli4_chk_avail_extnt_rsrc(phba, | ||
5300 | LPFC_RSC_TYPE_FCOE_XRI); | ||
5301 | if (rc != 0) | ||
5302 | error++; | ||
5303 | rc = lpfc_sli4_chk_avail_extnt_rsrc(phba, | ||
5304 | LPFC_RSC_TYPE_FCOE_RPI); | ||
5305 | if (rc != 0) | ||
5306 | error++; | ||
5307 | |||
5308 | /* | ||
5309 | * It's possible that the number of resources | ||
5310 | * provided to this port instance changed between | ||
5311 | * resets. Detect this condition and reallocate | ||
5312 | * resources. Otherwise, there is no action. | ||
5313 | */ | ||
5314 | if (error) { | ||
5315 | lpfc_printf_log(phba, KERN_INFO, | ||
5316 | LOG_MBOX | LOG_INIT, | ||
5317 | "2931 Detected extent resource " | ||
5318 | "change. Reallocating all " | ||
5319 | "extents.\n"); | ||
5320 | rc = lpfc_sli4_dealloc_extent(phba, | ||
5321 | LPFC_RSC_TYPE_FCOE_VFI); | ||
5322 | rc = lpfc_sli4_dealloc_extent(phba, | ||
5323 | LPFC_RSC_TYPE_FCOE_VPI); | ||
5324 | rc = lpfc_sli4_dealloc_extent(phba, | ||
5325 | LPFC_RSC_TYPE_FCOE_XRI); | ||
5326 | rc = lpfc_sli4_dealloc_extent(phba, | ||
5327 | LPFC_RSC_TYPE_FCOE_RPI); | ||
5328 | } else | ||
5329 | return 0; | ||
5330 | } | ||
5331 | |||
5332 | rc = lpfc_sli4_alloc_extent(phba, LPFC_RSC_TYPE_FCOE_VFI); | ||
5333 | if (unlikely(rc)) | ||
5334 | goto err_exit; | ||
5335 | |||
5336 | rc = lpfc_sli4_alloc_extent(phba, LPFC_RSC_TYPE_FCOE_VPI); | ||
5337 | if (unlikely(rc)) | ||
5338 | goto err_exit; | ||
5339 | |||
5340 | rc = lpfc_sli4_alloc_extent(phba, LPFC_RSC_TYPE_FCOE_RPI); | ||
5341 | if (unlikely(rc)) | ||
5342 | goto err_exit; | ||
5343 | |||
5344 | rc = lpfc_sli4_alloc_extent(phba, LPFC_RSC_TYPE_FCOE_XRI); | ||
5345 | if (unlikely(rc)) | ||
5346 | goto err_exit; | ||
5347 | bf_set(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags, | ||
5348 | LPFC_IDX_RSRC_RDY); | ||
5349 | return rc; | ||
5350 | } else { | ||
5351 | /* | ||
5352 | * The port does not support resource extents. The XRI, VPI, | ||
5353 | * VFI, RPI resource ids were determined from READ_CONFIG. | ||
5354 | * Just allocate the bitmasks and provision the resource id | ||
5355 | * arrays. If a port reset is active, the resources don't | ||
5356 | * need any action - just exit. | ||
5357 | */ | ||
5358 | if (bf_get(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags) == | ||
5359 | LPFC_IDX_RSRC_RDY) | ||
5360 | return 0; | ||
5361 | |||
5362 | /* RPIs. */ | ||
5363 | count = phba->sli4_hba.max_cfg_param.max_rpi; | ||
5364 | base = phba->sli4_hba.max_cfg_param.rpi_base; | ||
5365 | longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
5366 | phba->sli4_hba.rpi_bmask = kzalloc(longs * | ||
5367 | sizeof(unsigned long), | ||
5368 | GFP_KERNEL); | ||
5369 | if (unlikely(!phba->sli4_hba.rpi_bmask)) { | ||
5370 | rc = -ENOMEM; | ||
5371 | goto err_exit; | ||
5372 | } | ||
5373 | phba->sli4_hba.rpi_ids = kzalloc(count * | ||
5374 | sizeof(uint16_t), | ||
5375 | GFP_KERNEL); | ||
5376 | if (unlikely(!phba->sli4_hba.rpi_ids)) { | ||
5377 | rc = -ENOMEM; | ||
5378 | goto free_rpi_bmask; | ||
5379 | } | ||
5380 | |||
5381 | for (i = 0; i < count; i++) | ||
5382 | phba->sli4_hba.rpi_ids[i] = base + i; | ||
5383 | |||
5384 | /* VPIs. */ | ||
5385 | count = phba->sli4_hba.max_cfg_param.max_vpi; | ||
5386 | base = phba->sli4_hba.max_cfg_param.vpi_base; | ||
5387 | longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
5388 | phba->vpi_bmask = kzalloc(longs * | ||
5389 | sizeof(unsigned long), | ||
5390 | GFP_KERNEL); | ||
5391 | if (unlikely(!phba->vpi_bmask)) { | ||
5392 | rc = -ENOMEM; | ||
5393 | goto free_rpi_ids; | ||
5394 | } | ||
5395 | phba->vpi_ids = kzalloc(count * | ||
5396 | sizeof(uint16_t), | ||
5397 | GFP_KERNEL); | ||
5398 | if (unlikely(!phba->vpi_ids)) { | ||
5399 | rc = -ENOMEM; | ||
5400 | goto free_vpi_bmask; | ||
5401 | } | ||
5402 | |||
5403 | for (i = 0; i < count; i++) | ||
5404 | phba->vpi_ids[i] = base + i; | ||
5405 | |||
5406 | /* XRIs. */ | ||
5407 | count = phba->sli4_hba.max_cfg_param.max_xri; | ||
5408 | base = phba->sli4_hba.max_cfg_param.xri_base; | ||
5409 | longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
5410 | phba->sli4_hba.xri_bmask = kzalloc(longs * | ||
5411 | sizeof(unsigned long), | ||
5412 | GFP_KERNEL); | ||
5413 | if (unlikely(!phba->sli4_hba.xri_bmask)) { | ||
5414 | rc = -ENOMEM; | ||
5415 | goto free_vpi_ids; | ||
5416 | } | ||
5417 | phba->sli4_hba.xri_ids = kzalloc(count * | ||
5418 | sizeof(uint16_t), | ||
5419 | GFP_KERNEL); | ||
5420 | if (unlikely(!phba->sli4_hba.xri_ids)) { | ||
5421 | rc = -ENOMEM; | ||
5422 | goto free_xri_bmask; | ||
5423 | } | ||
5424 | |||
5425 | for (i = 0; i < count; i++) | ||
5426 | phba->sli4_hba.xri_ids[i] = base + i; | ||
5427 | |||
5428 | /* VFIs. */ | ||
5429 | count = phba->sli4_hba.max_cfg_param.max_vfi; | ||
5430 | base = phba->sli4_hba.max_cfg_param.vfi_base; | ||
5431 | longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
5432 | phba->sli4_hba.vfi_bmask = kzalloc(longs * | ||
5433 | sizeof(unsigned long), | ||
5434 | GFP_KERNEL); | ||
5435 | if (unlikely(!phba->sli4_hba.vfi_bmask)) { | ||
5436 | rc = -ENOMEM; | ||
5437 | goto free_xri_ids; | ||
5438 | } | ||
5439 | phba->sli4_hba.vfi_ids = kzalloc(count * | ||
5440 | sizeof(uint16_t), | ||
5441 | GFP_KERNEL); | ||
5442 | if (unlikely(!phba->sli4_hba.vfi_ids)) { | ||
5443 | rc = -ENOMEM; | ||
5444 | goto free_vfi_bmask; | ||
5445 | } | ||
5446 | |||
5447 | for (i = 0; i < count; i++) | ||
5448 | phba->sli4_hba.vfi_ids[i] = base + i; | ||
5449 | |||
5450 | /* | ||
5451 | * Mark all resources ready. An HBA reset doesn't need | ||
5452 | * to reset the initialization. | ||
5453 | */ | ||
5454 | bf_set(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags, | ||
5455 | LPFC_IDX_RSRC_RDY); | ||
5456 | return 0; | ||
5457 | } | ||
5458 | |||
5459 | free_vfi_bmask: | ||
5460 | kfree(phba->sli4_hba.vfi_bmask); | ||
5461 | free_xri_ids: | ||
5462 | kfree(phba->sli4_hba.xri_ids); | ||
5463 | free_xri_bmask: | ||
5464 | kfree(phba->sli4_hba.xri_bmask); | ||
5465 | free_vpi_ids: | ||
5466 | kfree(phba->vpi_ids); | ||
5467 | free_vpi_bmask: | ||
5468 | kfree(phba->vpi_bmask); | ||
5469 | free_rpi_ids: | ||
5470 | kfree(phba->sli4_hba.rpi_ids); | ||
5471 | free_rpi_bmask: | ||
5472 | kfree(phba->sli4_hba.rpi_bmask); | ||
5473 | err_exit: | ||
5474 | return rc; | ||
5475 | } | ||
5476 | |||
5477 | /** | ||
5478 | * lpfc_sli4_dealloc_resource_identifiers - Deallocate all SLI4 resource extents. | ||
5479 | * @phba: Pointer to HBA context object. | ||
5480 | * | ||
5481 | * This function allocates the number of elements for the specified | ||
5482 | * resource type. | ||
5483 | **/ | ||
5484 | int | ||
5485 | lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba) | ||
5486 | { | ||
5487 | if (phba->sli4_hba.extents_in_use) { | ||
5488 | lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_VPI); | ||
5489 | lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_RPI); | ||
5490 | lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_XRI); | ||
5491 | lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_VFI); | ||
5492 | } else { | ||
5493 | kfree(phba->vpi_bmask); | ||
5494 | kfree(phba->vpi_ids); | ||
5495 | bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
5496 | kfree(phba->sli4_hba.xri_bmask); | ||
5497 | kfree(phba->sli4_hba.xri_ids); | ||
5498 | bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
5499 | kfree(phba->sli4_hba.vfi_bmask); | ||
5500 | kfree(phba->sli4_hba.vfi_ids); | ||
5501 | bf_set(lpfc_vfi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
5502 | bf_set(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
5503 | } | ||
5504 | |||
5505 | return 0; | ||
5506 | } | ||
5507 | |||
5508 | /** | ||
4690 | * lpfc_sli4_hba_setup - SLI4 device intialization PCI function | 5509 | * lpfc_sli4_hba_setup - SLI4 device intialization PCI function |
4691 | * @phba: Pointer to HBA context object. | 5510 | * @phba: Pointer to HBA context object. |
4692 | * | 5511 | * |
@@ -4708,10 +5527,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
4708 | struct lpfc_vport *vport = phba->pport; | 5527 | struct lpfc_vport *vport = phba->pport; |
4709 | struct lpfc_dmabuf *mp; | 5528 | struct lpfc_dmabuf *mp; |
4710 | 5529 | ||
4711 | /* | ||
4712 | * TODO: Why does this routine execute these task in a different | ||
4713 | * order from probe? | ||
4714 | */ | ||
4715 | /* Perform a PCI function reset to start from clean */ | 5530 | /* Perform a PCI function reset to start from clean */ |
4716 | rc = lpfc_pci_function_reset(phba); | 5531 | rc = lpfc_pci_function_reset(phba); |
4717 | if (unlikely(rc)) | 5532 | if (unlikely(rc)) |
@@ -4740,7 +5555,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
4740 | * to read FCoE param config regions | 5555 | * to read FCoE param config regions |
4741 | */ | 5556 | */ |
4742 | if (lpfc_sli4_read_fcoe_params(phba, mboxq)) | 5557 | if (lpfc_sli4_read_fcoe_params(phba, mboxq)) |
4743 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, | 5558 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_INIT, |
4744 | "2570 Failed to read FCoE parameters\n"); | 5559 | "2570 Failed to read FCoE parameters\n"); |
4745 | 5560 | ||
4746 | /* Issue READ_REV to collect vpd and FW information. */ | 5561 | /* Issue READ_REV to collect vpd and FW information. */ |
@@ -4873,6 +5688,18 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
4873 | phba->sli3_options |= (LPFC_SLI3_NPIV_ENABLED | LPFC_SLI3_HBQ_ENABLED); | 5688 | phba->sli3_options |= (LPFC_SLI3_NPIV_ENABLED | LPFC_SLI3_HBQ_ENABLED); |
4874 | spin_unlock_irq(&phba->hbalock); | 5689 | spin_unlock_irq(&phba->hbalock); |
4875 | 5690 | ||
5691 | /* | ||
5692 | * Allocate all resources (xri,rpi,vpi,vfi) now. Subsequent | ||
5693 | * calls depends on these resources to complete port setup. | ||
5694 | */ | ||
5695 | rc = lpfc_sli4_alloc_resource_identifiers(phba); | ||
5696 | if (rc) { | ||
5697 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | ||
5698 | "2920 Failed to alloc Resource IDs " | ||
5699 | "rc = x%x\n", rc); | ||
5700 | goto out_free_mbox; | ||
5701 | } | ||
5702 | |||
4876 | /* Read the port's service parameters. */ | 5703 | /* Read the port's service parameters. */ |
4877 | rc = lpfc_read_sparam(phba, mboxq, vport->vpi); | 5704 | rc = lpfc_read_sparam(phba, mboxq, vport->vpi); |
4878 | if (rc) { | 5705 | if (rc) { |
@@ -4906,35 +5733,37 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
4906 | goto out_free_mbox; | 5733 | goto out_free_mbox; |
4907 | } | 5734 | } |
4908 | 5735 | ||
4909 | if (phba->cfg_soft_wwnn) | 5736 | lpfc_update_vport_wwn(vport); |
4910 | u64_to_wwn(phba->cfg_soft_wwnn, | ||
4911 | vport->fc_sparam.nodeName.u.wwn); | ||
4912 | if (phba->cfg_soft_wwpn) | ||
4913 | u64_to_wwn(phba->cfg_soft_wwpn, | ||
4914 | vport->fc_sparam.portName.u.wwn); | ||
4915 | memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName, | ||
4916 | sizeof(struct lpfc_name)); | ||
4917 | memcpy(&vport->fc_portname, &vport->fc_sparam.portName, | ||
4918 | sizeof(struct lpfc_name)); | ||
4919 | 5737 | ||
4920 | /* Update the fc_host data structures with new wwn. */ | 5738 | /* Update the fc_host data structures with new wwn. */ |
4921 | fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn); | 5739 | fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn); |
4922 | fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn); | 5740 | fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn); |
4923 | 5741 | ||
4924 | /* Register SGL pool to the device using non-embedded mailbox command */ | 5742 | /* Register SGL pool to the device using non-embedded mailbox command */ |
4925 | rc = lpfc_sli4_post_sgl_list(phba); | 5743 | if (!phba->sli4_hba.extents_in_use) { |
4926 | if (unlikely(rc)) { | 5744 | rc = lpfc_sli4_post_els_sgl_list(phba); |
4927 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | 5745 | if (unlikely(rc)) { |
4928 | "0582 Error %d during sgl post operation\n", | 5746 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, |
4929 | rc); | 5747 | "0582 Error %d during els sgl post " |
4930 | rc = -ENODEV; | 5748 | "operation\n", rc); |
4931 | goto out_free_mbox; | 5749 | rc = -ENODEV; |
5750 | goto out_free_mbox; | ||
5751 | } | ||
5752 | } else { | ||
5753 | rc = lpfc_sli4_post_els_sgl_list_ext(phba); | ||
5754 | if (unlikely(rc)) { | ||
5755 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | ||
5756 | "2560 Error %d during els sgl post " | ||
5757 | "operation\n", rc); | ||
5758 | rc = -ENODEV; | ||
5759 | goto out_free_mbox; | ||
5760 | } | ||
4932 | } | 5761 | } |
4933 | 5762 | ||
4934 | /* Register SCSI SGL pool to the device */ | 5763 | /* Register SCSI SGL pool to the device */ |
4935 | rc = lpfc_sli4_repost_scsi_sgl_list(phba); | 5764 | rc = lpfc_sli4_repost_scsi_sgl_list(phba); |
4936 | if (unlikely(rc)) { | 5765 | if (unlikely(rc)) { |
4937 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, | 5766 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, |
4938 | "0383 Error %d during scsi sgl post " | 5767 | "0383 Error %d during scsi sgl post " |
4939 | "operation\n", rc); | 5768 | "operation\n", rc); |
4940 | /* Some Scsi buffers were moved to the abort scsi list */ | 5769 | /* Some Scsi buffers were moved to the abort scsi list */ |
@@ -5747,10 +6576,15 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
5747 | lpfc_sli_pcimem_bcopy(&mbox_rgn->mcqe, &mboxq->mcqe, | 6576 | lpfc_sli_pcimem_bcopy(&mbox_rgn->mcqe, &mboxq->mcqe, |
5748 | sizeof(struct lpfc_mcqe)); | 6577 | sizeof(struct lpfc_mcqe)); |
5749 | mcqe_status = bf_get(lpfc_mcqe_status, &mbox_rgn->mcqe); | 6578 | mcqe_status = bf_get(lpfc_mcqe_status, &mbox_rgn->mcqe); |
5750 | 6579 | /* | |
5751 | /* Prefix the mailbox status with range x4000 to note SLI4 status. */ | 6580 | * When the CQE status indicates a failure and the mailbox status |
6581 | * indicates success then copy the CQE status into the mailbox status | ||
6582 | * (and prefix it with x4000). | ||
6583 | */ | ||
5752 | if (mcqe_status != MB_CQE_STATUS_SUCCESS) { | 6584 | if (mcqe_status != MB_CQE_STATUS_SUCCESS) { |
5753 | bf_set(lpfc_mqe_status, mb, LPFC_MBX_ERROR_RANGE | mcqe_status); | 6585 | if (bf_get(lpfc_mqe_status, mb) == MBX_SUCCESS) |
6586 | bf_set(lpfc_mqe_status, mb, | ||
6587 | (LPFC_MBX_ERROR_RANGE | mcqe_status)); | ||
5754 | rc = MBXERR_ERROR; | 6588 | rc = MBXERR_ERROR; |
5755 | } else | 6589 | } else |
5756 | lpfc_sli4_swap_str(phba, mboxq); | 6590 | lpfc_sli4_swap_str(phba, mboxq); |
@@ -5819,7 +6653,7 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, | |||
5819 | else | 6653 | else |
5820 | rc = -EIO; | 6654 | rc = -EIO; |
5821 | if (rc != MBX_SUCCESS) | 6655 | if (rc != MBX_SUCCESS) |
5822 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | 6656 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, |
5823 | "(%d):2541 Mailbox command x%x " | 6657 | "(%d):2541 Mailbox command x%x " |
5824 | "(x%x) cannot issue Data: x%x x%x\n", | 6658 | "(x%x) cannot issue Data: x%x x%x\n", |
5825 | mboxq->vport ? mboxq->vport->vpi : 0, | 6659 | mboxq->vport ? mboxq->vport->vpi : 0, |
@@ -6307,6 +7141,7 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, | |||
6307 | sgl->addr_hi = bpl->addrHigh; | 7141 | sgl->addr_hi = bpl->addrHigh; |
6308 | sgl->addr_lo = bpl->addrLow; | 7142 | sgl->addr_lo = bpl->addrLow; |
6309 | 7143 | ||
7144 | sgl->word2 = le32_to_cpu(sgl->word2); | ||
6310 | if ((i+1) == numBdes) | 7145 | if ((i+1) == numBdes) |
6311 | bf_set(lpfc_sli4_sge_last, sgl, 1); | 7146 | bf_set(lpfc_sli4_sge_last, sgl, 1); |
6312 | else | 7147 | else |
@@ -6343,6 +7178,7 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, | |||
6343 | cpu_to_le32(icmd->un.genreq64.bdl.addrHigh); | 7178 | cpu_to_le32(icmd->un.genreq64.bdl.addrHigh); |
6344 | sgl->addr_lo = | 7179 | sgl->addr_lo = |
6345 | cpu_to_le32(icmd->un.genreq64.bdl.addrLow); | 7180 | cpu_to_le32(icmd->un.genreq64.bdl.addrLow); |
7181 | sgl->word2 = le32_to_cpu(sgl->word2); | ||
6346 | bf_set(lpfc_sli4_sge_last, sgl, 1); | 7182 | bf_set(lpfc_sli4_sge_last, sgl, 1); |
6347 | sgl->word2 = cpu_to_le32(sgl->word2); | 7183 | sgl->word2 = cpu_to_le32(sgl->word2); |
6348 | sgl->sge_len = | 7184 | sgl->sge_len = |
@@ -6474,7 +7310,8 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
6474 | els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK) | 7310 | els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK) |
6475 | >> LPFC_FIP_ELS_ID_SHIFT); | 7311 | >> LPFC_FIP_ELS_ID_SHIFT); |
6476 | } | 7312 | } |
6477 | bf_set(wqe_temp_rpi, &wqe->els_req.wqe_com, ndlp->nlp_rpi); | 7313 | bf_set(wqe_temp_rpi, &wqe->els_req.wqe_com, |
7314 | phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); | ||
6478 | bf_set(wqe_els_id, &wqe->els_req.wqe_com, els_id); | 7315 | bf_set(wqe_els_id, &wqe->els_req.wqe_com, els_id); |
6479 | bf_set(wqe_dbde, &wqe->els_req.wqe_com, 1); | 7316 | bf_set(wqe_dbde, &wqe->els_req.wqe_com, 1); |
6480 | bf_set(wqe_iod, &wqe->els_req.wqe_com, LPFC_WQE_IOD_READ); | 7317 | bf_set(wqe_iod, &wqe->els_req.wqe_com, LPFC_WQE_IOD_READ); |
@@ -6623,14 +7460,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
6623 | iocbq->iocb.ulpContext); | 7460 | iocbq->iocb.ulpContext); |
6624 | if (!iocbq->iocb.ulpCt_h && iocbq->iocb.ulpCt_l) | 7461 | if (!iocbq->iocb.ulpCt_h && iocbq->iocb.ulpCt_l) |
6625 | bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, | 7462 | bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, |
6626 | iocbq->vport->vpi + phba->vpi_base); | 7463 | phba->vpi_ids[iocbq->vport->vpi]); |
6627 | bf_set(wqe_dbde, &wqe->xmit_els_rsp.wqe_com, 1); | 7464 | bf_set(wqe_dbde, &wqe->xmit_els_rsp.wqe_com, 1); |
6628 | bf_set(wqe_iod, &wqe->xmit_els_rsp.wqe_com, LPFC_WQE_IOD_WRITE); | 7465 | bf_set(wqe_iod, &wqe->xmit_els_rsp.wqe_com, LPFC_WQE_IOD_WRITE); |
6629 | bf_set(wqe_qosd, &wqe->xmit_els_rsp.wqe_com, 1); | 7466 | bf_set(wqe_qosd, &wqe->xmit_els_rsp.wqe_com, 1); |
6630 | bf_set(wqe_lenloc, &wqe->xmit_els_rsp.wqe_com, | 7467 | bf_set(wqe_lenloc, &wqe->xmit_els_rsp.wqe_com, |
6631 | LPFC_WQE_LENLOC_WORD3); | 7468 | LPFC_WQE_LENLOC_WORD3); |
6632 | bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0); | 7469 | bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0); |
6633 | bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp, ndlp->nlp_rpi); | 7470 | bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp, |
7471 | phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); | ||
6634 | command_type = OTHER_COMMAND; | 7472 | command_type = OTHER_COMMAND; |
6635 | break; | 7473 | break; |
6636 | case CMD_CLOSE_XRI_CN: | 7474 | case CMD_CLOSE_XRI_CN: |
@@ -6729,6 +7567,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
6729 | return IOCB_ERROR; | 7567 | return IOCB_ERROR; |
6730 | break; | 7568 | break; |
6731 | } | 7569 | } |
7570 | |||
6732 | bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag); | 7571 | bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag); |
6733 | bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag); | 7572 | bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag); |
6734 | wqe->generic.wqe_com.abort_tag = abort_tag; | 7573 | wqe->generic.wqe_com.abort_tag = abort_tag; |
@@ -6776,7 +7615,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
6776 | return IOCB_BUSY; | 7615 | return IOCB_BUSY; |
6777 | } | 7616 | } |
6778 | } else { | 7617 | } else { |
6779 | sglq = __lpfc_sli_get_sglq(phba, piocb); | 7618 | sglq = __lpfc_sli_get_sglq(phba, piocb); |
6780 | if (!sglq) { | 7619 | if (!sglq) { |
6781 | if (!(flag & SLI_IOCB_RET_IOCB)) { | 7620 | if (!(flag & SLI_IOCB_RET_IOCB)) { |
6782 | __lpfc_sli_ringtx_put(phba, | 7621 | __lpfc_sli_ringtx_put(phba, |
@@ -6789,11 +7628,11 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
6789 | } | 7628 | } |
6790 | } | 7629 | } |
6791 | } else if (piocb->iocb_flag & LPFC_IO_FCP) { | 7630 | } else if (piocb->iocb_flag & LPFC_IO_FCP) { |
6792 | sglq = NULL; /* These IO's already have an XRI and | 7631 | /* These IO's already have an XRI and a mapped sgl. */ |
6793 | * a mapped sgl. | 7632 | sglq = NULL; |
6794 | */ | ||
6795 | } else { | 7633 | } else { |
6796 | /* This is a continuation of a commandi,(CX) so this | 7634 | /* |
7635 | * This is a continuation of a commandi,(CX) so this | ||
6797 | * sglq is on the active list | 7636 | * sglq is on the active list |
6798 | */ | 7637 | */ |
6799 | sglq = __lpfc_get_active_sglq(phba, piocb->sli4_xritag); | 7638 | sglq = __lpfc_get_active_sglq(phba, piocb->sli4_xritag); |
@@ -6802,8 +7641,8 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
6802 | } | 7641 | } |
6803 | 7642 | ||
6804 | if (sglq) { | 7643 | if (sglq) { |
7644 | piocb->sli4_lxritag = sglq->sli4_lxritag; | ||
6805 | piocb->sli4_xritag = sglq->sli4_xritag; | 7645 | piocb->sli4_xritag = sglq->sli4_xritag; |
6806 | |||
6807 | if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocb, sglq)) | 7646 | if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocb, sglq)) |
6808 | return IOCB_ERROR; | 7647 | return IOCB_ERROR; |
6809 | } | 7648 | } |
@@ -9799,7 +10638,12 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe) | |||
9799 | break; | 10638 | break; |
9800 | case LPFC_WCQ: | 10639 | case LPFC_WCQ: |
9801 | while ((cqe = lpfc_sli4_cq_get(cq))) { | 10640 | while ((cqe = lpfc_sli4_cq_get(cq))) { |
9802 | workposted |= lpfc_sli4_sp_handle_cqe(phba, cq, cqe); | 10641 | if (cq->subtype == LPFC_FCP) |
10642 | workposted |= lpfc_sli4_fp_handle_wcqe(phba, cq, | ||
10643 | cqe); | ||
10644 | else | ||
10645 | workposted |= lpfc_sli4_sp_handle_cqe(phba, cq, | ||
10646 | cqe); | ||
9803 | if (!(++ecount % LPFC_GET_QE_REL_INT)) | 10647 | if (!(++ecount % LPFC_GET_QE_REL_INT)) |
9804 | lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM); | 10648 | lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM); |
9805 | } | 10649 | } |
@@ -11446,6 +12290,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, | |||
11446 | LPFC_MBOXQ_t *mbox; | 12290 | LPFC_MBOXQ_t *mbox; |
11447 | int rc; | 12291 | int rc; |
11448 | uint32_t shdr_status, shdr_add_status; | 12292 | uint32_t shdr_status, shdr_add_status; |
12293 | uint32_t mbox_tmo; | ||
11449 | union lpfc_sli4_cfg_shdr *shdr; | 12294 | union lpfc_sli4_cfg_shdr *shdr; |
11450 | 12295 | ||
11451 | if (xritag == NO_XRI) { | 12296 | if (xritag == NO_XRI) { |
@@ -11479,8 +12324,10 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, | |||
11479 | cpu_to_le32(putPaddrHigh(pdma_phys_addr1)); | 12324 | cpu_to_le32(putPaddrHigh(pdma_phys_addr1)); |
11480 | if (!phba->sli4_hba.intr_enable) | 12325 | if (!phba->sli4_hba.intr_enable) |
11481 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | 12326 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); |
11482 | else | 12327 | else { |
11483 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO); | 12328 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); |
12329 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
12330 | } | ||
11484 | /* The IOCTL status is embedded in the mailbox subheader. */ | 12331 | /* The IOCTL status is embedded in the mailbox subheader. */ |
11485 | shdr = (union lpfc_sli4_cfg_shdr *) &post_sgl_pages->header.cfg_shdr; | 12332 | shdr = (union lpfc_sli4_cfg_shdr *) &post_sgl_pages->header.cfg_shdr; |
11486 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | 12333 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); |
@@ -11498,6 +12345,76 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, | |||
11498 | } | 12345 | } |
11499 | 12346 | ||
11500 | /** | 12347 | /** |
12348 | * lpfc_sli4_init_rpi_hdrs - Post the rpi header memory region to the port | ||
12349 | * @phba: pointer to lpfc hba data structure. | ||
12350 | * | ||
12351 | * This routine is invoked to post rpi header templates to the | ||
12352 | * port for those SLI4 ports that do not support extents. This routine | ||
12353 | * posts a PAGE_SIZE memory region to the port to hold up to | ||
12354 | * PAGE_SIZE modulo 64 rpi context headers. This is an initialization routine | ||
12355 | * and should be called only when interrupts are disabled. | ||
12356 | * | ||
12357 | * Return codes | ||
12358 | * 0 - successful | ||
12359 | * -ERROR - otherwise. | ||
12360 | */ | ||
12361 | uint16_t | ||
12362 | lpfc_sli4_alloc_xri(struct lpfc_hba *phba) | ||
12363 | { | ||
12364 | unsigned long xri; | ||
12365 | |||
12366 | /* | ||
12367 | * Fetch the next logical xri. Because this index is logical, | ||
12368 | * the driver starts at 0 each time. | ||
12369 | */ | ||
12370 | spin_lock_irq(&phba->hbalock); | ||
12371 | xri = find_next_zero_bit(phba->sli4_hba.xri_bmask, | ||
12372 | phba->sli4_hba.max_cfg_param.max_xri, 0); | ||
12373 | if (xri >= phba->sli4_hba.max_cfg_param.max_xri) { | ||
12374 | spin_unlock_irq(&phba->hbalock); | ||
12375 | return NO_XRI; | ||
12376 | } else { | ||
12377 | set_bit(xri, phba->sli4_hba.xri_bmask); | ||
12378 | phba->sli4_hba.max_cfg_param.xri_used++; | ||
12379 | phba->sli4_hba.xri_count++; | ||
12380 | } | ||
12381 | |||
12382 | spin_unlock_irq(&phba->hbalock); | ||
12383 | return xri; | ||
12384 | } | ||
12385 | |||
12386 | /** | ||
12387 | * lpfc_sli4_free_xri - Release an xri for reuse. | ||
12388 | * @phba: pointer to lpfc hba data structure. | ||
12389 | * | ||
12390 | * This routine is invoked to release an xri to the pool of | ||
12391 | * available rpis maintained by the driver. | ||
12392 | **/ | ||
12393 | void | ||
12394 | __lpfc_sli4_free_xri(struct lpfc_hba *phba, int xri) | ||
12395 | { | ||
12396 | if (test_and_clear_bit(xri, phba->sli4_hba.xri_bmask)) { | ||
12397 | phba->sli4_hba.xri_count--; | ||
12398 | phba->sli4_hba.max_cfg_param.xri_used--; | ||
12399 | } | ||
12400 | } | ||
12401 | |||
12402 | /** | ||
12403 | * lpfc_sli4_free_xri - Release an xri for reuse. | ||
12404 | * @phba: pointer to lpfc hba data structure. | ||
12405 | * | ||
12406 | * This routine is invoked to release an xri to the pool of | ||
12407 | * available rpis maintained by the driver. | ||
12408 | **/ | ||
12409 | void | ||
12410 | lpfc_sli4_free_xri(struct lpfc_hba *phba, int xri) | ||
12411 | { | ||
12412 | spin_lock_irq(&phba->hbalock); | ||
12413 | __lpfc_sli4_free_xri(phba, xri); | ||
12414 | spin_unlock_irq(&phba->hbalock); | ||
12415 | } | ||
12416 | |||
12417 | /** | ||
11501 | * lpfc_sli4_next_xritag - Get an xritag for the io | 12418 | * lpfc_sli4_next_xritag - Get an xritag for the io |
11502 | * @phba: Pointer to HBA context object. | 12419 | * @phba: Pointer to HBA context object. |
11503 | * | 12420 | * |
@@ -11510,30 +12427,23 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, | |||
11510 | uint16_t | 12427 | uint16_t |
11511 | lpfc_sli4_next_xritag(struct lpfc_hba *phba) | 12428 | lpfc_sli4_next_xritag(struct lpfc_hba *phba) |
11512 | { | 12429 | { |
11513 | uint16_t xritag; | 12430 | uint16_t xri_index; |
11514 | 12431 | ||
11515 | spin_lock_irq(&phba->hbalock); | 12432 | xri_index = lpfc_sli4_alloc_xri(phba); |
11516 | xritag = phba->sli4_hba.next_xri; | 12433 | if (xri_index != NO_XRI) |
11517 | if ((xritag != (uint16_t) -1) && xritag < | 12434 | return xri_index; |
11518 | (phba->sli4_hba.max_cfg_param.max_xri | 12435 | |
11519 | + phba->sli4_hba.max_cfg_param.xri_base)) { | 12436 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
11520 | phba->sli4_hba.next_xri++; | ||
11521 | phba->sli4_hba.max_cfg_param.xri_used++; | ||
11522 | spin_unlock_irq(&phba->hbalock); | ||
11523 | return xritag; | ||
11524 | } | ||
11525 | spin_unlock_irq(&phba->hbalock); | ||
11526 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, | ||
11527 | "2004 Failed to allocate XRI.last XRITAG is %d" | 12437 | "2004 Failed to allocate XRI.last XRITAG is %d" |
11528 | " Max XRI is %d, Used XRI is %d\n", | 12438 | " Max XRI is %d, Used XRI is %d\n", |
11529 | phba->sli4_hba.next_xri, | 12439 | xri_index, |
11530 | phba->sli4_hba.max_cfg_param.max_xri, | 12440 | phba->sli4_hba.max_cfg_param.max_xri, |
11531 | phba->sli4_hba.max_cfg_param.xri_used); | 12441 | phba->sli4_hba.max_cfg_param.xri_used); |
11532 | return -1; | 12442 | return NO_XRI; |
11533 | } | 12443 | } |
11534 | 12444 | ||
11535 | /** | 12445 | /** |
11536 | * lpfc_sli4_post_sgl_list - post a block of sgl list to the firmware. | 12446 | * lpfc_sli4_post_els_sgl_list - post a block of ELS sgls to the port. |
11537 | * @phba: pointer to lpfc hba data structure. | 12447 | * @phba: pointer to lpfc hba data structure. |
11538 | * | 12448 | * |
11539 | * This routine is invoked to post a block of driver's sgl pages to the | 12449 | * This routine is invoked to post a block of driver's sgl pages to the |
@@ -11542,7 +12452,7 @@ lpfc_sli4_next_xritag(struct lpfc_hba *phba) | |||
11542 | * stopped. | 12452 | * stopped. |
11543 | **/ | 12453 | **/ |
11544 | int | 12454 | int |
11545 | lpfc_sli4_post_sgl_list(struct lpfc_hba *phba) | 12455 | lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba) |
11546 | { | 12456 | { |
11547 | struct lpfc_sglq *sglq_entry; | 12457 | struct lpfc_sglq *sglq_entry; |
11548 | struct lpfc_mbx_post_uembed_sgl_page1 *sgl; | 12458 | struct lpfc_mbx_post_uembed_sgl_page1 *sgl; |
@@ -11551,7 +12461,7 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba) | |||
11551 | LPFC_MBOXQ_t *mbox; | 12461 | LPFC_MBOXQ_t *mbox; |
11552 | uint32_t reqlen, alloclen, pg_pairs; | 12462 | uint32_t reqlen, alloclen, pg_pairs; |
11553 | uint32_t mbox_tmo; | 12463 | uint32_t mbox_tmo; |
11554 | uint16_t xritag_start = 0; | 12464 | uint16_t xritag_start = 0, lxri = 0; |
11555 | int els_xri_cnt, rc = 0; | 12465 | int els_xri_cnt, rc = 0; |
11556 | uint32_t shdr_status, shdr_add_status; | 12466 | uint32_t shdr_status, shdr_add_status; |
11557 | union lpfc_sli4_cfg_shdr *shdr; | 12467 | union lpfc_sli4_cfg_shdr *shdr; |
@@ -11568,11 +12478,8 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba) | |||
11568 | return -ENOMEM; | 12478 | return -ENOMEM; |
11569 | } | 12479 | } |
11570 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 12480 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
11571 | if (!mbox) { | 12481 | if (!mbox) |
11572 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
11573 | "2560 Failed to allocate mbox cmd memory\n"); | ||
11574 | return -ENOMEM; | 12482 | return -ENOMEM; |
11575 | } | ||
11576 | 12483 | ||
11577 | /* Allocate DMA memory and set up the non-embedded mailbox command */ | 12484 | /* Allocate DMA memory and set up the non-embedded mailbox command */ |
11578 | alloclen = lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE, | 12485 | alloclen = lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE, |
@@ -11587,15 +12494,30 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba) | |||
11587 | lpfc_sli4_mbox_cmd_free(phba, mbox); | 12494 | lpfc_sli4_mbox_cmd_free(phba, mbox); |
11588 | return -ENOMEM; | 12495 | return -ENOMEM; |
11589 | } | 12496 | } |
11590 | /* Get the first SGE entry from the non-embedded DMA memory */ | ||
11591 | viraddr = mbox->sge_array->addr[0]; | ||
11592 | |||
11593 | /* Set up the SGL pages in the non-embedded DMA pages */ | 12497 | /* Set up the SGL pages in the non-embedded DMA pages */ |
12498 | viraddr = mbox->sge_array->addr[0]; | ||
11594 | sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr; | 12499 | sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr; |
11595 | sgl_pg_pairs = &sgl->sgl_pg_pairs; | 12500 | sgl_pg_pairs = &sgl->sgl_pg_pairs; |
11596 | 12501 | ||
11597 | for (pg_pairs = 0; pg_pairs < els_xri_cnt; pg_pairs++) { | 12502 | for (pg_pairs = 0; pg_pairs < els_xri_cnt; pg_pairs++) { |
11598 | sglq_entry = phba->sli4_hba.lpfc_els_sgl_array[pg_pairs]; | 12503 | sglq_entry = phba->sli4_hba.lpfc_els_sgl_array[pg_pairs]; |
12504 | |||
12505 | /* | ||
12506 | * Assign the sglq a physical xri only if the driver has not | ||
12507 | * initialized those resources. A port reset only needs | ||
12508 | * the sglq's posted. | ||
12509 | */ | ||
12510 | if (bf_get(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags) != | ||
12511 | LPFC_XRI_RSRC_RDY) { | ||
12512 | lxri = lpfc_sli4_next_xritag(phba); | ||
12513 | if (lxri == NO_XRI) { | ||
12514 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
12515 | return -ENOMEM; | ||
12516 | } | ||
12517 | sglq_entry->sli4_lxritag = lxri; | ||
12518 | sglq_entry->sli4_xritag = phba->sli4_hba.xri_ids[lxri]; | ||
12519 | } | ||
12520 | |||
11599 | /* Set up the sge entry */ | 12521 | /* Set up the sge entry */ |
11600 | sgl_pg_pairs->sgl_pg0_addr_lo = | 12522 | sgl_pg_pairs->sgl_pg0_addr_lo = |
11601 | cpu_to_le32(putPaddrLow(sglq_entry->phys)); | 12523 | cpu_to_le32(putPaddrLow(sglq_entry->phys)); |
@@ -11605,16 +12527,17 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba) | |||
11605 | cpu_to_le32(putPaddrLow(0)); | 12527 | cpu_to_le32(putPaddrLow(0)); |
11606 | sgl_pg_pairs->sgl_pg1_addr_hi = | 12528 | sgl_pg_pairs->sgl_pg1_addr_hi = |
11607 | cpu_to_le32(putPaddrHigh(0)); | 12529 | cpu_to_le32(putPaddrHigh(0)); |
12530 | |||
11608 | /* Keep the first xritag on the list */ | 12531 | /* Keep the first xritag on the list */ |
11609 | if (pg_pairs == 0) | 12532 | if (pg_pairs == 0) |
11610 | xritag_start = sglq_entry->sli4_xritag; | 12533 | xritag_start = sglq_entry->sli4_xritag; |
11611 | sgl_pg_pairs++; | 12534 | sgl_pg_pairs++; |
11612 | } | 12535 | } |
12536 | |||
12537 | /* Complete initialization and perform endian conversion. */ | ||
11613 | bf_set(lpfc_post_sgl_pages_xri, sgl, xritag_start); | 12538 | bf_set(lpfc_post_sgl_pages_xri, sgl, xritag_start); |
11614 | bf_set(lpfc_post_sgl_pages_xricnt, sgl, els_xri_cnt); | 12539 | bf_set(lpfc_post_sgl_pages_xricnt, sgl, els_xri_cnt); |
11615 | /* Perform endian conversion if necessary */ | ||
11616 | sgl->word0 = cpu_to_le32(sgl->word0); | 12540 | sgl->word0 = cpu_to_le32(sgl->word0); |
11617 | |||
11618 | if (!phba->sli4_hba.intr_enable) | 12541 | if (!phba->sli4_hba.intr_enable) |
11619 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | 12542 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); |
11620 | else { | 12543 | else { |
@@ -11633,6 +12556,181 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba) | |||
11633 | shdr_status, shdr_add_status, rc); | 12556 | shdr_status, shdr_add_status, rc); |
11634 | rc = -ENXIO; | 12557 | rc = -ENXIO; |
11635 | } | 12558 | } |
12559 | |||
12560 | if (rc == 0) | ||
12561 | bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags, | ||
12562 | LPFC_XRI_RSRC_RDY); | ||
12563 | return rc; | ||
12564 | } | ||
12565 | |||
12566 | /** | ||
12567 | * lpfc_sli4_post_els_sgl_list_ext - post a block of ELS sgls to the port. | ||
12568 | * @phba: pointer to lpfc hba data structure. | ||
12569 | * | ||
12570 | * This routine is invoked to post a block of driver's sgl pages to the | ||
12571 | * HBA using non-embedded mailbox command. No Lock is held. This routine | ||
12572 | * is only called when the driver is loading and after all IO has been | ||
12573 | * stopped. | ||
12574 | **/ | ||
12575 | int | ||
12576 | lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba) | ||
12577 | { | ||
12578 | struct lpfc_sglq *sglq_entry; | ||
12579 | struct lpfc_mbx_post_uembed_sgl_page1 *sgl; | ||
12580 | struct sgl_page_pairs *sgl_pg_pairs; | ||
12581 | void *viraddr; | ||
12582 | LPFC_MBOXQ_t *mbox; | ||
12583 | uint32_t reqlen, alloclen, index; | ||
12584 | uint32_t mbox_tmo; | ||
12585 | uint16_t rsrc_start, rsrc_size, els_xri_cnt; | ||
12586 | uint16_t xritag_start = 0, lxri = 0; | ||
12587 | struct lpfc_rsrc_blks *rsrc_blk; | ||
12588 | int cnt, ttl_cnt, rc = 0; | ||
12589 | int loop_cnt; | ||
12590 | uint32_t shdr_status, shdr_add_status; | ||
12591 | union lpfc_sli4_cfg_shdr *shdr; | ||
12592 | |||
12593 | /* The number of sgls to be posted */ | ||
12594 | els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba); | ||
12595 | |||
12596 | reqlen = els_xri_cnt * sizeof(struct sgl_page_pairs) + | ||
12597 | sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t); | ||
12598 | if (reqlen > SLI4_PAGE_SIZE) { | ||
12599 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
12600 | "2989 Block sgl registration required DMA " | ||
12601 | "size (%d) great than a page\n", reqlen); | ||
12602 | return -ENOMEM; | ||
12603 | } | ||
12604 | |||
12605 | cnt = 0; | ||
12606 | ttl_cnt = 0; | ||
12607 | list_for_each_entry(rsrc_blk, &phba->sli4_hba.lpfc_xri_blk_list, | ||
12608 | list) { | ||
12609 | rsrc_start = rsrc_blk->rsrc_start; | ||
12610 | rsrc_size = rsrc_blk->rsrc_size; | ||
12611 | |||
12612 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
12613 | "3014 Working ELS Extent start %d, cnt %d\n", | ||
12614 | rsrc_start, rsrc_size); | ||
12615 | |||
12616 | loop_cnt = min(els_xri_cnt, rsrc_size); | ||
12617 | if (ttl_cnt + loop_cnt >= els_xri_cnt) { | ||
12618 | loop_cnt = els_xri_cnt - ttl_cnt; | ||
12619 | ttl_cnt = els_xri_cnt; | ||
12620 | } | ||
12621 | |||
12622 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
12623 | if (!mbox) | ||
12624 | return -ENOMEM; | ||
12625 | /* | ||
12626 | * Allocate DMA memory and set up the non-embedded mailbox | ||
12627 | * command. | ||
12628 | */ | ||
12629 | alloclen = lpfc_sli4_config(phba, mbox, | ||
12630 | LPFC_MBOX_SUBSYSTEM_FCOE, | ||
12631 | LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES, | ||
12632 | reqlen, LPFC_SLI4_MBX_NEMBED); | ||
12633 | if (alloclen < reqlen) { | ||
12634 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
12635 | "2987 Allocated DMA memory size (%d) " | ||
12636 | "is less than the requested DMA memory " | ||
12637 | "size (%d)\n", alloclen, reqlen); | ||
12638 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
12639 | return -ENOMEM; | ||
12640 | } | ||
12641 | |||
12642 | /* Set up the SGL pages in the non-embedded DMA pages */ | ||
12643 | viraddr = mbox->sge_array->addr[0]; | ||
12644 | sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr; | ||
12645 | sgl_pg_pairs = &sgl->sgl_pg_pairs; | ||
12646 | |||
12647 | /* | ||
12648 | * The starting resource may not begin at zero. Control | ||
12649 | * the loop variants via the block resource parameters, | ||
12650 | * but handle the sge pointers with a zero-based index | ||
12651 | * that doesn't get reset per loop pass. | ||
12652 | */ | ||
12653 | for (index = rsrc_start; | ||
12654 | index < rsrc_start + loop_cnt; | ||
12655 | index++) { | ||
12656 | sglq_entry = phba->sli4_hba.lpfc_els_sgl_array[cnt]; | ||
12657 | |||
12658 | /* | ||
12659 | * Assign the sglq a physical xri only if the driver | ||
12660 | * has not initialized those resources. A port reset | ||
12661 | * only needs the sglq's posted. | ||
12662 | */ | ||
12663 | if (bf_get(lpfc_xri_rsrc_rdy, | ||
12664 | &phba->sli4_hba.sli4_flags) != | ||
12665 | LPFC_XRI_RSRC_RDY) { | ||
12666 | lxri = lpfc_sli4_next_xritag(phba); | ||
12667 | if (lxri == NO_XRI) { | ||
12668 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
12669 | rc = -ENOMEM; | ||
12670 | goto err_exit; | ||
12671 | } | ||
12672 | sglq_entry->sli4_lxritag = lxri; | ||
12673 | sglq_entry->sli4_xritag = | ||
12674 | phba->sli4_hba.xri_ids[lxri]; | ||
12675 | } | ||
12676 | |||
12677 | /* Set up the sge entry */ | ||
12678 | sgl_pg_pairs->sgl_pg0_addr_lo = | ||
12679 | cpu_to_le32(putPaddrLow(sglq_entry->phys)); | ||
12680 | sgl_pg_pairs->sgl_pg0_addr_hi = | ||
12681 | cpu_to_le32(putPaddrHigh(sglq_entry->phys)); | ||
12682 | sgl_pg_pairs->sgl_pg1_addr_lo = | ||
12683 | cpu_to_le32(putPaddrLow(0)); | ||
12684 | sgl_pg_pairs->sgl_pg1_addr_hi = | ||
12685 | cpu_to_le32(putPaddrHigh(0)); | ||
12686 | |||
12687 | /* Track the starting physical XRI for the mailbox. */ | ||
12688 | if (index == rsrc_start) | ||
12689 | xritag_start = sglq_entry->sli4_xritag; | ||
12690 | sgl_pg_pairs++; | ||
12691 | cnt++; | ||
12692 | } | ||
12693 | |||
12694 | /* Complete initialization and perform endian conversion. */ | ||
12695 | rsrc_blk->rsrc_used += loop_cnt; | ||
12696 | bf_set(lpfc_post_sgl_pages_xri, sgl, xritag_start); | ||
12697 | bf_set(lpfc_post_sgl_pages_xricnt, sgl, loop_cnt); | ||
12698 | sgl->word0 = cpu_to_le32(sgl->word0); | ||
12699 | |||
12700 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
12701 | "3015 Post ELS Extent SGL, start %d, " | ||
12702 | "cnt %d, used %d\n", | ||
12703 | xritag_start, loop_cnt, rsrc_blk->rsrc_used); | ||
12704 | if (!phba->sli4_hba.intr_enable) | ||
12705 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
12706 | else { | ||
12707 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
12708 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
12709 | } | ||
12710 | shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr; | ||
12711 | shdr_status = bf_get(lpfc_mbox_hdr_status, | ||
12712 | &shdr->response); | ||
12713 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, | ||
12714 | &shdr->response); | ||
12715 | if (rc != MBX_TIMEOUT) | ||
12716 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
12717 | if (shdr_status || shdr_add_status || rc) { | ||
12718 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
12719 | "2988 POST_SGL_BLOCK mailbox " | ||
12720 | "command failed status x%x " | ||
12721 | "add_status x%x mbx status x%x\n", | ||
12722 | shdr_status, shdr_add_status, rc); | ||
12723 | rc = -ENXIO; | ||
12724 | goto err_exit; | ||
12725 | } | ||
12726 | if (ttl_cnt >= els_xri_cnt) | ||
12727 | break; | ||
12728 | } | ||
12729 | |||
12730 | err_exit: | ||
12731 | if (rc == 0) | ||
12732 | bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags, | ||
12733 | LPFC_XRI_RSRC_RDY); | ||
11636 | return rc; | 12734 | return rc; |
11637 | } | 12735 | } |
11638 | 12736 | ||
@@ -11693,6 +12791,7 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist, | |||
11693 | lpfc_sli4_mbox_cmd_free(phba, mbox); | 12791 | lpfc_sli4_mbox_cmd_free(phba, mbox); |
11694 | return -ENOMEM; | 12792 | return -ENOMEM; |
11695 | } | 12793 | } |
12794 | |||
11696 | /* Get the first SGE entry from the non-embedded DMA memory */ | 12795 | /* Get the first SGE entry from the non-embedded DMA memory */ |
11697 | viraddr = mbox->sge_array->addr[0]; | 12796 | viraddr = mbox->sge_array->addr[0]; |
11698 | 12797 | ||
@@ -11748,6 +12847,169 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist, | |||
11748 | } | 12847 | } |
11749 | 12848 | ||
11750 | /** | 12849 | /** |
12850 | * lpfc_sli4_post_scsi_sgl_blk_ext - post a block of scsi sgls to the port. | ||
12851 | * @phba: pointer to lpfc hba data structure. | ||
12852 | * @sblist: pointer to scsi buffer list. | ||
12853 | * @count: number of scsi buffers on the list. | ||
12854 | * | ||
12855 | * This routine is invoked to post a block of @count scsi sgl pages from a | ||
12856 | * SCSI buffer list @sblist to the HBA using non-embedded mailbox command. | ||
12857 | * No Lock is held. | ||
12858 | * | ||
12859 | **/ | ||
12860 | int | ||
12861 | lpfc_sli4_post_scsi_sgl_blk_ext(struct lpfc_hba *phba, struct list_head *sblist, | ||
12862 | int cnt) | ||
12863 | { | ||
12864 | struct lpfc_scsi_buf *psb = NULL; | ||
12865 | struct lpfc_mbx_post_uembed_sgl_page1 *sgl; | ||
12866 | struct sgl_page_pairs *sgl_pg_pairs; | ||
12867 | void *viraddr; | ||
12868 | LPFC_MBOXQ_t *mbox; | ||
12869 | uint32_t reqlen, alloclen, pg_pairs; | ||
12870 | uint32_t mbox_tmo; | ||
12871 | uint16_t xri_start = 0, scsi_xri_start; | ||
12872 | uint16_t rsrc_range; | ||
12873 | int rc = 0, avail_cnt; | ||
12874 | uint32_t shdr_status, shdr_add_status; | ||
12875 | dma_addr_t pdma_phys_bpl1; | ||
12876 | union lpfc_sli4_cfg_shdr *shdr; | ||
12877 | struct lpfc_rsrc_blks *rsrc_blk; | ||
12878 | uint32_t xri_cnt = 0; | ||
12879 | |||
12880 | /* Calculate the total requested length of the dma memory */ | ||
12881 | reqlen = cnt * sizeof(struct sgl_page_pairs) + | ||
12882 | sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t); | ||
12883 | if (reqlen > SLI4_PAGE_SIZE) { | ||
12884 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
12885 | "2932 Block sgl registration required DMA " | ||
12886 | "size (%d) great than a page\n", reqlen); | ||
12887 | return -ENOMEM; | ||
12888 | } | ||
12889 | |||
12890 | /* | ||
12891 | * The use of extents requires the driver to post the sgl headers | ||
12892 | * in multiple postings to meet the contiguous resource assignment. | ||
12893 | */ | ||
12894 | psb = list_prepare_entry(psb, sblist, list); | ||
12895 | scsi_xri_start = phba->sli4_hba.scsi_xri_start; | ||
12896 | list_for_each_entry(rsrc_blk, &phba->sli4_hba.lpfc_xri_blk_list, | ||
12897 | list) { | ||
12898 | rsrc_range = rsrc_blk->rsrc_start + rsrc_blk->rsrc_size; | ||
12899 | if (rsrc_range < scsi_xri_start) | ||
12900 | continue; | ||
12901 | else if (rsrc_blk->rsrc_used >= rsrc_blk->rsrc_size) | ||
12902 | continue; | ||
12903 | else | ||
12904 | avail_cnt = rsrc_blk->rsrc_size - rsrc_blk->rsrc_used; | ||
12905 | |||
12906 | reqlen = (avail_cnt * sizeof(struct sgl_page_pairs)) + | ||
12907 | sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t); | ||
12908 | /* | ||
12909 | * Allocate DMA memory and set up the non-embedded mailbox | ||
12910 | * command. The mbox is used to post an SGL page per loop | ||
12911 | * but the DMA memory has a use-once semantic so the mailbox | ||
12912 | * is used and freed per loop pass. | ||
12913 | */ | ||
12914 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
12915 | if (!mbox) { | ||
12916 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
12917 | "2933 Failed to allocate mbox cmd " | ||
12918 | "memory\n"); | ||
12919 | return -ENOMEM; | ||
12920 | } | ||
12921 | alloclen = lpfc_sli4_config(phba, mbox, | ||
12922 | LPFC_MBOX_SUBSYSTEM_FCOE, | ||
12923 | LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES, | ||
12924 | reqlen, | ||
12925 | LPFC_SLI4_MBX_NEMBED); | ||
12926 | if (alloclen < reqlen) { | ||
12927 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
12928 | "2934 Allocated DMA memory size (%d) " | ||
12929 | "is less than the requested DMA memory " | ||
12930 | "size (%d)\n", alloclen, reqlen); | ||
12931 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
12932 | return -ENOMEM; | ||
12933 | } | ||
12934 | |||
12935 | /* Get the first SGE entry from the non-embedded DMA memory */ | ||
12936 | viraddr = mbox->sge_array->addr[0]; | ||
12937 | |||
12938 | /* Set up the SGL pages in the non-embedded DMA pages */ | ||
12939 | sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr; | ||
12940 | sgl_pg_pairs = &sgl->sgl_pg_pairs; | ||
12941 | |||
12942 | /* pg_pairs tracks posted SGEs per loop iteration. */ | ||
12943 | pg_pairs = 0; | ||
12944 | list_for_each_entry_continue(psb, sblist, list) { | ||
12945 | /* Set up the sge entry */ | ||
12946 | sgl_pg_pairs->sgl_pg0_addr_lo = | ||
12947 | cpu_to_le32(putPaddrLow(psb->dma_phys_bpl)); | ||
12948 | sgl_pg_pairs->sgl_pg0_addr_hi = | ||
12949 | cpu_to_le32(putPaddrHigh(psb->dma_phys_bpl)); | ||
12950 | if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE) | ||
12951 | pdma_phys_bpl1 = psb->dma_phys_bpl + | ||
12952 | SGL_PAGE_SIZE; | ||
12953 | else | ||
12954 | pdma_phys_bpl1 = 0; | ||
12955 | sgl_pg_pairs->sgl_pg1_addr_lo = | ||
12956 | cpu_to_le32(putPaddrLow(pdma_phys_bpl1)); | ||
12957 | sgl_pg_pairs->sgl_pg1_addr_hi = | ||
12958 | cpu_to_le32(putPaddrHigh(pdma_phys_bpl1)); | ||
12959 | /* Keep the first xri for this extent. */ | ||
12960 | if (pg_pairs == 0) | ||
12961 | xri_start = psb->cur_iocbq.sli4_xritag; | ||
12962 | sgl_pg_pairs++; | ||
12963 | pg_pairs++; | ||
12964 | xri_cnt++; | ||
12965 | |||
12966 | /* | ||
12967 | * Track two exit conditions - the loop has constructed | ||
12968 | * all of the caller's SGE pairs or all available | ||
12969 | * resource IDs in this extent are consumed. | ||
12970 | */ | ||
12971 | if ((xri_cnt == cnt) || (pg_pairs >= avail_cnt)) | ||
12972 | break; | ||
12973 | } | ||
12974 | rsrc_blk->rsrc_used += pg_pairs; | ||
12975 | bf_set(lpfc_post_sgl_pages_xri, sgl, xri_start); | ||
12976 | bf_set(lpfc_post_sgl_pages_xricnt, sgl, pg_pairs); | ||
12977 | |||
12978 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
12979 | "3016 Post SCSI Extent SGL, start %d, cnt %d " | ||
12980 | "blk use %d\n", | ||
12981 | xri_start, pg_pairs, rsrc_blk->rsrc_used); | ||
12982 | /* Perform endian conversion if necessary */ | ||
12983 | sgl->word0 = cpu_to_le32(sgl->word0); | ||
12984 | if (!phba->sli4_hba.intr_enable) | ||
12985 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
12986 | else { | ||
12987 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
12988 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
12989 | } | ||
12990 | shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr; | ||
12991 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
12992 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, | ||
12993 | &shdr->response); | ||
12994 | if (rc != MBX_TIMEOUT) | ||
12995 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
12996 | if (shdr_status || shdr_add_status || rc) { | ||
12997 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
12998 | "2935 POST_SGL_BLOCK mailbox command " | ||
12999 | "failed status x%x add_status x%x " | ||
13000 | "mbx status x%x\n", | ||
13001 | shdr_status, shdr_add_status, rc); | ||
13002 | return -ENXIO; | ||
13003 | } | ||
13004 | |||
13005 | /* Post only what is requested. */ | ||
13006 | if (xri_cnt >= cnt) | ||
13007 | break; | ||
13008 | } | ||
13009 | return rc; | ||
13010 | } | ||
13011 | |||
13012 | /** | ||
11751 | * lpfc_fc_frame_check - Check that this frame is a valid frame to handle | 13013 | * lpfc_fc_frame_check - Check that this frame is a valid frame to handle |
11752 | * @phba: pointer to lpfc_hba struct that the frame was received on | 13014 | * @phba: pointer to lpfc_hba struct that the frame was received on |
11753 | * @fc_hdr: A pointer to the FC Header data (In Big Endian Format) | 13015 | * @fc_hdr: A pointer to the FC Header data (In Big Endian Format) |
@@ -12137,6 +13399,28 @@ lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba, | |||
12137 | } | 13399 | } |
12138 | 13400 | ||
12139 | /** | 13401 | /** |
13402 | * lpfc_sli4_xri_inrange - check xri is in range of xris owned by driver. | ||
13403 | * @phba: Pointer to HBA context object. | ||
13404 | * @xri: xri id in transaction. | ||
13405 | * | ||
13406 | * This function validates the xri maps to the known range of XRIs allocated an | ||
13407 | * used by the driver. | ||
13408 | **/ | ||
13409 | static uint16_t | ||
13410 | lpfc_sli4_xri_inrange(struct lpfc_hba *phba, | ||
13411 | uint16_t xri) | ||
13412 | { | ||
13413 | int i; | ||
13414 | |||
13415 | for (i = 0; i < phba->sli4_hba.max_cfg_param.max_xri; i++) { | ||
13416 | if (xri == phba->sli4_hba.xri_ids[i]) | ||
13417 | return i; | ||
13418 | } | ||
13419 | return NO_XRI; | ||
13420 | } | ||
13421 | |||
13422 | |||
13423 | /** | ||
12140 | * lpfc_sli4_seq_abort_rsp - bls rsp to sequence abort | 13424 | * lpfc_sli4_seq_abort_rsp - bls rsp to sequence abort |
12141 | * @phba: Pointer to HBA context object. | 13425 | * @phba: Pointer to HBA context object. |
12142 | * @fc_hdr: pointer to a FC frame header. | 13426 | * @fc_hdr: pointer to a FC frame header. |
@@ -12169,9 +13453,7 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, | |||
12169 | "SID:x%x\n", oxid, sid); | 13453 | "SID:x%x\n", oxid, sid); |
12170 | return; | 13454 | return; |
12171 | } | 13455 | } |
12172 | if (rxid >= phba->sli4_hba.max_cfg_param.xri_base | 13456 | if (lpfc_sli4_xri_inrange(phba, rxid)) |
12173 | && rxid <= (phba->sli4_hba.max_cfg_param.max_xri | ||
12174 | + phba->sli4_hba.max_cfg_param.xri_base)) | ||
12175 | lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0); | 13457 | lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0); |
12176 | 13458 | ||
12177 | /* Allocate buffer for rsp iocb */ | 13459 | /* Allocate buffer for rsp iocb */ |
@@ -12194,12 +13476,13 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, | |||
12194 | icmd->ulpBdeCount = 0; | 13476 | icmd->ulpBdeCount = 0; |
12195 | icmd->ulpLe = 1; | 13477 | icmd->ulpLe = 1; |
12196 | icmd->ulpClass = CLASS3; | 13478 | icmd->ulpClass = CLASS3; |
12197 | icmd->ulpContext = ndlp->nlp_rpi; | 13479 | icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; |
12198 | ctiocb->context1 = ndlp; | 13480 | ctiocb->context1 = ndlp; |
12199 | 13481 | ||
12200 | ctiocb->iocb_cmpl = NULL; | 13482 | ctiocb->iocb_cmpl = NULL; |
12201 | ctiocb->vport = phba->pport; | 13483 | ctiocb->vport = phba->pport; |
12202 | ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl; | 13484 | ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl; |
13485 | ctiocb->sli4_lxritag = NO_XRI; | ||
12203 | ctiocb->sli4_xritag = NO_XRI; | 13486 | ctiocb->sli4_xritag = NO_XRI; |
12204 | 13487 | ||
12205 | /* If the oxid maps to the FCP XRI range or if it is out of range, | 13488 | /* If the oxid maps to the FCP XRI range or if it is out of range, |
@@ -12380,8 +13663,8 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) | |||
12380 | first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS; | 13663 | first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS; |
12381 | first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX; | 13664 | first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX; |
12382 | first_iocbq->iocb.ulpContext = be16_to_cpu(fc_hdr->fh_ox_id); | 13665 | first_iocbq->iocb.ulpContext = be16_to_cpu(fc_hdr->fh_ox_id); |
12383 | first_iocbq->iocb.unsli3.rcvsli3.vpi = | 13666 | /* iocbq is prepped for internal consumption. Logical vpi. */ |
12384 | vport->vpi + vport->phba->vpi_base; | 13667 | first_iocbq->iocb.unsli3.rcvsli3.vpi = vport->vpi; |
12385 | /* put the first buffer into the first IOCBq */ | 13668 | /* put the first buffer into the first IOCBq */ |
12386 | first_iocbq->context2 = &seq_dmabuf->dbuf; | 13669 | first_iocbq->context2 = &seq_dmabuf->dbuf; |
12387 | first_iocbq->context3 = NULL; | 13670 | first_iocbq->context3 = NULL; |
@@ -12461,7 +13744,7 @@ lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport, | |||
12461 | &phba->sli.ring[LPFC_ELS_RING], | 13744 | &phba->sli.ring[LPFC_ELS_RING], |
12462 | iocbq, fc_hdr->fh_r_ctl, | 13745 | iocbq, fc_hdr->fh_r_ctl, |
12463 | fc_hdr->fh_type)) | 13746 | fc_hdr->fh_type)) |
12464 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, | 13747 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
12465 | "2540 Ring %d handler: unexpected Rctl " | 13748 | "2540 Ring %d handler: unexpected Rctl " |
12466 | "x%x Type x%x received\n", | 13749 | "x%x Type x%x received\n", |
12467 | LPFC_ELS_RING, | 13750 | LPFC_ELS_RING, |
@@ -12558,9 +13841,24 @@ lpfc_sli4_post_all_rpi_hdrs(struct lpfc_hba *phba) | |||
12558 | { | 13841 | { |
12559 | struct lpfc_rpi_hdr *rpi_page; | 13842 | struct lpfc_rpi_hdr *rpi_page; |
12560 | uint32_t rc = 0; | 13843 | uint32_t rc = 0; |
13844 | uint16_t lrpi = 0; | ||
13845 | |||
13846 | /* SLI4 ports that support extents do not require RPI headers. */ | ||
13847 | if (!phba->sli4_hba.rpi_hdrs_in_use) | ||
13848 | goto exit; | ||
13849 | if (phba->sli4_hba.extents_in_use) | ||
13850 | return -EIO; | ||
12561 | 13851 | ||
12562 | /* Post all rpi memory regions to the port. */ | ||
12563 | list_for_each_entry(rpi_page, &phba->sli4_hba.lpfc_rpi_hdr_list, list) { | 13852 | list_for_each_entry(rpi_page, &phba->sli4_hba.lpfc_rpi_hdr_list, list) { |
13853 | /* | ||
13854 | * Assign the rpi headers a physical rpi only if the driver | ||
13855 | * has not initialized those resources. A port reset only | ||
13856 | * needs the headers posted. | ||
13857 | */ | ||
13858 | if (bf_get(lpfc_rpi_rsrc_rdy, &phba->sli4_hba.sli4_flags) != | ||
13859 | LPFC_RPI_RSRC_RDY) | ||
13860 | rpi_page->start_rpi = phba->sli4_hba.rpi_ids[lrpi]; | ||
13861 | |||
12564 | rc = lpfc_sli4_post_rpi_hdr(phba, rpi_page); | 13862 | rc = lpfc_sli4_post_rpi_hdr(phba, rpi_page); |
12565 | if (rc != MBX_SUCCESS) { | 13863 | if (rc != MBX_SUCCESS) { |
12566 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 13864 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
@@ -12571,6 +13869,9 @@ lpfc_sli4_post_all_rpi_hdrs(struct lpfc_hba *phba) | |||
12571 | } | 13869 | } |
12572 | } | 13870 | } |
12573 | 13871 | ||
13872 | exit: | ||
13873 | bf_set(lpfc_rpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, | ||
13874 | LPFC_RPI_RSRC_RDY); | ||
12574 | return rc; | 13875 | return rc; |
12575 | } | 13876 | } |
12576 | 13877 | ||
@@ -12594,10 +13895,15 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) | |||
12594 | LPFC_MBOXQ_t *mboxq; | 13895 | LPFC_MBOXQ_t *mboxq; |
12595 | struct lpfc_mbx_post_hdr_tmpl *hdr_tmpl; | 13896 | struct lpfc_mbx_post_hdr_tmpl *hdr_tmpl; |
12596 | uint32_t rc = 0; | 13897 | uint32_t rc = 0; |
12597 | uint32_t mbox_tmo; | ||
12598 | uint32_t shdr_status, shdr_add_status; | 13898 | uint32_t shdr_status, shdr_add_status; |
12599 | union lpfc_sli4_cfg_shdr *shdr; | 13899 | union lpfc_sli4_cfg_shdr *shdr; |
12600 | 13900 | ||
13901 | /* SLI4 ports that support extents do not require RPI headers. */ | ||
13902 | if (!phba->sli4_hba.rpi_hdrs_in_use) | ||
13903 | return rc; | ||
13904 | if (phba->sli4_hba.extents_in_use) | ||
13905 | return -EIO; | ||
13906 | |||
12601 | /* The port is notified of the header region via a mailbox command. */ | 13907 | /* The port is notified of the header region via a mailbox command. */ |
12602 | mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 13908 | mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
12603 | if (!mboxq) { | 13909 | if (!mboxq) { |
@@ -12609,16 +13915,19 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) | |||
12609 | 13915 | ||
12610 | /* Post all rpi memory regions to the port. */ | 13916 | /* Post all rpi memory regions to the port. */ |
12611 | hdr_tmpl = &mboxq->u.mqe.un.hdr_tmpl; | 13917 | hdr_tmpl = &mboxq->u.mqe.un.hdr_tmpl; |
12612 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
12613 | lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | 13918 | lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE, |
12614 | LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE, | 13919 | LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE, |
12615 | sizeof(struct lpfc_mbx_post_hdr_tmpl) - | 13920 | sizeof(struct lpfc_mbx_post_hdr_tmpl) - |
12616 | sizeof(struct lpfc_sli4_cfg_mhdr), | 13921 | sizeof(struct lpfc_sli4_cfg_mhdr), |
12617 | LPFC_SLI4_MBX_EMBED); | 13922 | LPFC_SLI4_MBX_EMBED); |
12618 | bf_set(lpfc_mbx_post_hdr_tmpl_page_cnt, | 13923 | |
12619 | hdr_tmpl, rpi_page->page_count); | 13924 | |
13925 | /* Post the physical rpi to the port for this rpi header. */ | ||
12620 | bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl, | 13926 | bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl, |
12621 | rpi_page->start_rpi); | 13927 | rpi_page->start_rpi); |
13928 | bf_set(lpfc_mbx_post_hdr_tmpl_page_cnt, | ||
13929 | hdr_tmpl, rpi_page->page_count); | ||
13930 | |||
12622 | hdr_tmpl->rpi_paddr_lo = putPaddrLow(rpi_page->dmabuf->phys); | 13931 | hdr_tmpl->rpi_paddr_lo = putPaddrLow(rpi_page->dmabuf->phys); |
12623 | hdr_tmpl->rpi_paddr_hi = putPaddrHigh(rpi_page->dmabuf->phys); | 13932 | hdr_tmpl->rpi_paddr_hi = putPaddrHigh(rpi_page->dmabuf->phys); |
12624 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); | 13933 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); |
@@ -12653,22 +13962,21 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) | |||
12653 | int | 13962 | int |
12654 | lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | 13963 | lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) |
12655 | { | 13964 | { |
12656 | int rpi; | 13965 | unsigned long rpi; |
12657 | uint16_t max_rpi, rpi_base, rpi_limit; | 13966 | uint16_t max_rpi, rpi_limit; |
12658 | uint16_t rpi_remaining; | 13967 | uint16_t rpi_remaining, lrpi = 0; |
12659 | struct lpfc_rpi_hdr *rpi_hdr; | 13968 | struct lpfc_rpi_hdr *rpi_hdr; |
12660 | 13969 | ||
12661 | max_rpi = phba->sli4_hba.max_cfg_param.max_rpi; | 13970 | max_rpi = phba->sli4_hba.max_cfg_param.max_rpi; |
12662 | rpi_base = phba->sli4_hba.max_cfg_param.rpi_base; | ||
12663 | rpi_limit = phba->sli4_hba.next_rpi; | 13971 | rpi_limit = phba->sli4_hba.next_rpi; |
12664 | 13972 | ||
12665 | /* | 13973 | /* |
12666 | * The valid rpi range is not guaranteed to be zero-based. Start | 13974 | * Fetch the next logical rpi. Because this index is logical, |
12667 | * the search at the rpi_base as reported by the port. | 13975 | * the driver starts at 0 each time. |
12668 | */ | 13976 | */ |
12669 | spin_lock_irq(&phba->hbalock); | 13977 | spin_lock_irq(&phba->hbalock); |
12670 | rpi = find_next_zero_bit(phba->sli4_hba.rpi_bmask, rpi_limit, rpi_base); | 13978 | rpi = find_next_zero_bit(phba->sli4_hba.rpi_bmask, rpi_limit, 0); |
12671 | if (rpi >= rpi_limit || rpi < rpi_base) | 13979 | if (rpi >= rpi_limit) |
12672 | rpi = LPFC_RPI_ALLOC_ERROR; | 13980 | rpi = LPFC_RPI_ALLOC_ERROR; |
12673 | else { | 13981 | else { |
12674 | set_bit(rpi, phba->sli4_hba.rpi_bmask); | 13982 | set_bit(rpi, phba->sli4_hba.rpi_bmask); |
@@ -12678,7 +13986,7 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
12678 | 13986 | ||
12679 | /* | 13987 | /* |
12680 | * Don't try to allocate more rpi header regions if the device limit | 13988 | * Don't try to allocate more rpi header regions if the device limit |
12681 | * on available rpis max has been exhausted. | 13989 | * has been exhausted. |
12682 | */ | 13990 | */ |
12683 | if ((rpi == LPFC_RPI_ALLOC_ERROR) && | 13991 | if ((rpi == LPFC_RPI_ALLOC_ERROR) && |
12684 | (phba->sli4_hba.rpi_count >= max_rpi)) { | 13992 | (phba->sli4_hba.rpi_count >= max_rpi)) { |
@@ -12687,13 +13995,21 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
12687 | } | 13995 | } |
12688 | 13996 | ||
12689 | /* | 13997 | /* |
13998 | * RPI header postings are not required for SLI4 ports capable of | ||
13999 | * extents. | ||
14000 | */ | ||
14001 | if (!phba->sli4_hba.rpi_hdrs_in_use) { | ||
14002 | spin_unlock_irq(&phba->hbalock); | ||
14003 | return rpi; | ||
14004 | } | ||
14005 | |||
14006 | /* | ||
12690 | * If the driver is running low on rpi resources, allocate another | 14007 | * If the driver is running low on rpi resources, allocate another |
12691 | * page now. Note that the next_rpi value is used because | 14008 | * page now. Note that the next_rpi value is used because |
12692 | * it represents how many are actually in use whereas max_rpi notes | 14009 | * it represents how many are actually in use whereas max_rpi notes |
12693 | * how many are supported max by the device. | 14010 | * how many are supported max by the device. |
12694 | */ | 14011 | */ |
12695 | rpi_remaining = phba->sli4_hba.next_rpi - rpi_base - | 14012 | rpi_remaining = phba->sli4_hba.next_rpi - phba->sli4_hba.rpi_count; |
12696 | phba->sli4_hba.rpi_count; | ||
12697 | spin_unlock_irq(&phba->hbalock); | 14013 | spin_unlock_irq(&phba->hbalock); |
12698 | if (rpi_remaining < LPFC_RPI_LOW_WATER_MARK) { | 14014 | if (rpi_remaining < LPFC_RPI_LOW_WATER_MARK) { |
12699 | rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); | 14015 | rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); |
@@ -12702,6 +14018,8 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
12702 | "2002 Error Could not grow rpi " | 14018 | "2002 Error Could not grow rpi " |
12703 | "count\n"); | 14019 | "count\n"); |
12704 | } else { | 14020 | } else { |
14021 | lrpi = rpi_hdr->start_rpi; | ||
14022 | rpi_hdr->start_rpi = phba->sli4_hba.rpi_ids[lrpi]; | ||
12705 | lpfc_sli4_post_rpi_hdr(phba, rpi_hdr); | 14023 | lpfc_sli4_post_rpi_hdr(phba, rpi_hdr); |
12706 | } | 14024 | } |
12707 | } | 14025 | } |
@@ -12751,6 +14069,8 @@ void | |||
12751 | lpfc_sli4_remove_rpis(struct lpfc_hba *phba) | 14069 | lpfc_sli4_remove_rpis(struct lpfc_hba *phba) |
12752 | { | 14070 | { |
12753 | kfree(phba->sli4_hba.rpi_bmask); | 14071 | kfree(phba->sli4_hba.rpi_bmask); |
14072 | kfree(phba->sli4_hba.rpi_ids); | ||
14073 | bf_set(lpfc_rpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
12754 | } | 14074 | } |
12755 | 14075 | ||
12756 | /** | 14076 | /** |
@@ -13490,6 +14810,96 @@ out: | |||
13490 | } | 14810 | } |
13491 | 14811 | ||
13492 | /** | 14812 | /** |
14813 | * lpfc_wr_object - write an object to the firmware | ||
14814 | * @phba: HBA structure that indicates port to create a queue on. | ||
14815 | * @dmabuf_list: list of dmabufs to write to the port. | ||
14816 | * @size: the total byte value of the objects to write to the port. | ||
14817 | * @offset: the current offset to be used to start the transfer. | ||
14818 | * | ||
14819 | * This routine will create a wr_object mailbox command to send to the port. | ||
14820 | * the mailbox command will be constructed using the dma buffers described in | ||
14821 | * @dmabuf_list to create a list of BDEs. This routine will fill in as many | ||
14822 | * BDEs that the imbedded mailbox can support. The @offset variable will be | ||
14823 | * used to indicate the starting offset of the transfer and will also return | ||
14824 | * the offset after the write object mailbox has completed. @size is used to | ||
14825 | * determine the end of the object and whether the eof bit should be set. | ||
14826 | * | ||
14827 | * Return 0 is successful and offset will contain the the new offset to use | ||
14828 | * for the next write. | ||
14829 | * Return negative value for error cases. | ||
14830 | **/ | ||
14831 | int | ||
14832 | lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list, | ||
14833 | uint32_t size, uint32_t *offset) | ||
14834 | { | ||
14835 | struct lpfc_mbx_wr_object *wr_object; | ||
14836 | LPFC_MBOXQ_t *mbox; | ||
14837 | int rc = 0, i = 0; | ||
14838 | uint32_t shdr_status, shdr_add_status; | ||
14839 | uint32_t mbox_tmo; | ||
14840 | union lpfc_sli4_cfg_shdr *shdr; | ||
14841 | struct lpfc_dmabuf *dmabuf; | ||
14842 | uint32_t written = 0; | ||
14843 | |||
14844 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
14845 | if (!mbox) | ||
14846 | return -ENOMEM; | ||
14847 | |||
14848 | lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
14849 | LPFC_MBOX_OPCODE_WRITE_OBJECT, | ||
14850 | sizeof(struct lpfc_mbx_wr_object) - | ||
14851 | sizeof(struct lpfc_sli4_cfg_mhdr), LPFC_SLI4_MBX_EMBED); | ||
14852 | |||
14853 | wr_object = (struct lpfc_mbx_wr_object *)&mbox->u.mqe.un.wr_object; | ||
14854 | wr_object->u.request.write_offset = *offset; | ||
14855 | sprintf((uint8_t *)wr_object->u.request.object_name, "/"); | ||
14856 | wr_object->u.request.object_name[0] = | ||
14857 | cpu_to_le32(wr_object->u.request.object_name[0]); | ||
14858 | bf_set(lpfc_wr_object_eof, &wr_object->u.request, 0); | ||
14859 | list_for_each_entry(dmabuf, dmabuf_list, list) { | ||
14860 | if (i >= LPFC_MBX_WR_CONFIG_MAX_BDE || written >= size) | ||
14861 | break; | ||
14862 | wr_object->u.request.bde[i].addrLow = putPaddrLow(dmabuf->phys); | ||
14863 | wr_object->u.request.bde[i].addrHigh = | ||
14864 | putPaddrHigh(dmabuf->phys); | ||
14865 | if (written + SLI4_PAGE_SIZE >= size) { | ||
14866 | wr_object->u.request.bde[i].tus.f.bdeSize = | ||
14867 | (size - written); | ||
14868 | written += (size - written); | ||
14869 | bf_set(lpfc_wr_object_eof, &wr_object->u.request, 1); | ||
14870 | } else { | ||
14871 | wr_object->u.request.bde[i].tus.f.bdeSize = | ||
14872 | SLI4_PAGE_SIZE; | ||
14873 | written += SLI4_PAGE_SIZE; | ||
14874 | } | ||
14875 | i++; | ||
14876 | } | ||
14877 | wr_object->u.request.bde_count = i; | ||
14878 | bf_set(lpfc_wr_object_write_length, &wr_object->u.request, written); | ||
14879 | if (!phba->sli4_hba.intr_enable) | ||
14880 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
14881 | else { | ||
14882 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
14883 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
14884 | } | ||
14885 | /* The IOCTL status is embedded in the mailbox subheader. */ | ||
14886 | shdr = (union lpfc_sli4_cfg_shdr *) &wr_object->header.cfg_shdr; | ||
14887 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
14888 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); | ||
14889 | if (rc != MBX_TIMEOUT) | ||
14890 | mempool_free(mbox, phba->mbox_mem_pool); | ||
14891 | if (shdr_status || shdr_add_status || rc) { | ||
14892 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
14893 | "3025 Write Object mailbox failed with " | ||
14894 | "status x%x add_status x%x, mbx status x%x\n", | ||
14895 | shdr_status, shdr_add_status, rc); | ||
14896 | rc = -ENXIO; | ||
14897 | } else | ||
14898 | *offset += wr_object->u.response.actual_write_length; | ||
14899 | return rc; | ||
14900 | } | ||
14901 | |||
14902 | /** | ||
13493 | * lpfc_cleanup_pending_mbox - Free up vport discovery mailbox commands. | 14903 | * lpfc_cleanup_pending_mbox - Free up vport discovery mailbox commands. |
13494 | * @vport: pointer to vport data structure. | 14904 | * @vport: pointer to vport data structure. |
13495 | * | 14905 | * |
@@ -13644,7 +15054,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) | |||
13644 | * never happen | 15054 | * never happen |
13645 | */ | 15055 | */ |
13646 | sglq = __lpfc_clear_active_sglq(phba, | 15056 | sglq = __lpfc_clear_active_sglq(phba, |
13647 | sglq->sli4_xritag); | 15057 | sglq->sli4_lxritag); |
13648 | spin_unlock_irqrestore(&phba->hbalock, iflags); | 15058 | spin_unlock_irqrestore(&phba->hbalock, iflags); |
13649 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 15059 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
13650 | "2823 txq empty and txq_cnt is %d\n ", | 15060 | "2823 txq empty and txq_cnt is %d\n ", |
@@ -13656,6 +15066,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) | |||
13656 | /* The xri and iocb resources secured, | 15066 | /* The xri and iocb resources secured, |
13657 | * attempt to issue request | 15067 | * attempt to issue request |
13658 | */ | 15068 | */ |
15069 | piocbq->sli4_lxritag = sglq->sli4_lxritag; | ||
13659 | piocbq->sli4_xritag = sglq->sli4_xritag; | 15070 | piocbq->sli4_xritag = sglq->sli4_xritag; |
13660 | if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq)) | 15071 | if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq)) |
13661 | fail_msg = "to convert bpl to sgl"; | 15072 | fail_msg = "to convert bpl to sgl"; |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 453577c21c14..a0075b0af142 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -52,6 +52,7 @@ struct lpfc_iocbq { | |||
52 | struct list_head clist; | 52 | struct list_head clist; |
53 | struct list_head dlist; | 53 | struct list_head dlist; |
54 | uint16_t iotag; /* pre-assigned IO tag */ | 54 | uint16_t iotag; /* pre-assigned IO tag */ |
55 | uint16_t sli4_lxritag; /* logical pre-assigned XRI. */ | ||
55 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ | 56 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ |
56 | struct lpfc_cq_event cq_event; | 57 | struct lpfc_cq_event cq_event; |
57 | 58 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 1a3cbf88f2ce..4b1703554a26 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
@@ -310,7 +310,6 @@ struct lpfc_max_cfg_param { | |||
310 | uint16_t vfi_base; | 310 | uint16_t vfi_base; |
311 | uint16_t vfi_used; | 311 | uint16_t vfi_used; |
312 | uint16_t max_fcfi; | 312 | uint16_t max_fcfi; |
313 | uint16_t fcfi_base; | ||
314 | uint16_t fcfi_used; | 313 | uint16_t fcfi_used; |
315 | uint16_t max_eq; | 314 | uint16_t max_eq; |
316 | uint16_t max_rq; | 315 | uint16_t max_rq; |
@@ -365,6 +364,11 @@ struct lpfc_pc_sli4_params { | |||
365 | uint8_t rqv; | 364 | uint8_t rqv; |
366 | }; | 365 | }; |
367 | 366 | ||
367 | struct lpfc_iov { | ||
368 | uint32_t pf_number; | ||
369 | uint32_t vf_number; | ||
370 | }; | ||
371 | |||
368 | /* SLI4 HBA data structure entries */ | 372 | /* SLI4 HBA data structure entries */ |
369 | struct lpfc_sli4_hba { | 373 | struct lpfc_sli4_hba { |
370 | void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for | 374 | void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for |
@@ -444,10 +448,13 @@ struct lpfc_sli4_hba { | |||
444 | uint32_t intr_enable; | 448 | uint32_t intr_enable; |
445 | struct lpfc_bmbx bmbx; | 449 | struct lpfc_bmbx bmbx; |
446 | struct lpfc_max_cfg_param max_cfg_param; | 450 | struct lpfc_max_cfg_param max_cfg_param; |
451 | uint16_t extents_in_use; /* must allocate resource extents. */ | ||
452 | uint16_t rpi_hdrs_in_use; /* must post rpi hdrs if set. */ | ||
447 | uint16_t next_xri; /* last_xri - max_cfg_param.xri_base = used */ | 453 | uint16_t next_xri; /* last_xri - max_cfg_param.xri_base = used */ |
448 | uint16_t next_rpi; | 454 | uint16_t next_rpi; |
449 | uint16_t scsi_xri_max; | 455 | uint16_t scsi_xri_max; |
450 | uint16_t scsi_xri_cnt; | 456 | uint16_t scsi_xri_cnt; |
457 | uint16_t scsi_xri_start; | ||
451 | struct list_head lpfc_free_sgl_list; | 458 | struct list_head lpfc_free_sgl_list; |
452 | struct list_head lpfc_sgl_list; | 459 | struct list_head lpfc_sgl_list; |
453 | struct lpfc_sglq **lpfc_els_sgl_array; | 460 | struct lpfc_sglq **lpfc_els_sgl_array; |
@@ -458,7 +465,17 @@ struct lpfc_sli4_hba { | |||
458 | struct lpfc_sglq **lpfc_sglq_active_list; | 465 | struct lpfc_sglq **lpfc_sglq_active_list; |
459 | struct list_head lpfc_rpi_hdr_list; | 466 | struct list_head lpfc_rpi_hdr_list; |
460 | unsigned long *rpi_bmask; | 467 | unsigned long *rpi_bmask; |
468 | uint16_t *rpi_ids; | ||
461 | uint16_t rpi_count; | 469 | uint16_t rpi_count; |
470 | struct list_head lpfc_rpi_blk_list; | ||
471 | unsigned long *xri_bmask; | ||
472 | uint16_t *xri_ids; | ||
473 | uint16_t xri_count; | ||
474 | struct list_head lpfc_xri_blk_list; | ||
475 | unsigned long *vfi_bmask; | ||
476 | uint16_t *vfi_ids; | ||
477 | uint16_t vfi_count; | ||
478 | struct list_head lpfc_vfi_blk_list; | ||
462 | struct lpfc_sli4_flags sli4_flags; | 479 | struct lpfc_sli4_flags sli4_flags; |
463 | struct list_head sp_queue_event; | 480 | struct list_head sp_queue_event; |
464 | struct list_head sp_cqe_event_pool; | 481 | struct list_head sp_cqe_event_pool; |
@@ -467,6 +484,7 @@ struct lpfc_sli4_hba { | |||
467 | struct list_head sp_els_xri_aborted_work_queue; | 484 | struct list_head sp_els_xri_aborted_work_queue; |
468 | struct list_head sp_unsol_work_queue; | 485 | struct list_head sp_unsol_work_queue; |
469 | struct lpfc_sli4_link link_state; | 486 | struct lpfc_sli4_link link_state; |
487 | struct lpfc_iov iov; | ||
470 | spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */ | 488 | spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */ |
471 | spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */ | 489 | spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */ |
472 | }; | 490 | }; |
@@ -490,6 +508,7 @@ struct lpfc_sglq { | |||
490 | enum lpfc_sgl_state state; | 508 | enum lpfc_sgl_state state; |
491 | struct lpfc_nodelist *ndlp; /* ndlp associated with IO */ | 509 | struct lpfc_nodelist *ndlp; /* ndlp associated with IO */ |
492 | uint16_t iotag; /* pre-assigned IO tag */ | 510 | uint16_t iotag; /* pre-assigned IO tag */ |
511 | uint16_t sli4_lxritag; /* logical pre-assigned xri. */ | ||
493 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ | 512 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ |
494 | struct sli4_sge *sgl; /* pre-assigned SGL */ | 513 | struct sli4_sge *sgl; /* pre-assigned SGL */ |
495 | void *virt; /* virtual address. */ | 514 | void *virt; /* virtual address. */ |
@@ -504,6 +523,13 @@ struct lpfc_rpi_hdr { | |||
504 | uint32_t start_rpi; | 523 | uint32_t start_rpi; |
505 | }; | 524 | }; |
506 | 525 | ||
526 | struct lpfc_rsrc_blks { | ||
527 | struct list_head list; | ||
528 | uint16_t rsrc_start; | ||
529 | uint16_t rsrc_size; | ||
530 | uint16_t rsrc_used; | ||
531 | }; | ||
532 | |||
507 | /* | 533 | /* |
508 | * SLI4 specific function prototypes | 534 | * SLI4 specific function prototypes |
509 | */ | 535 | */ |
@@ -543,8 +569,11 @@ int lpfc_sli4_post_sgl(struct lpfc_hba *, dma_addr_t, dma_addr_t, uint16_t); | |||
543 | int lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *); | 569 | int lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *); |
544 | uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *); | 570 | uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *); |
545 | int lpfc_sli4_post_async_mbox(struct lpfc_hba *); | 571 | int lpfc_sli4_post_async_mbox(struct lpfc_hba *); |
546 | int lpfc_sli4_post_sgl_list(struct lpfc_hba *phba); | 572 | int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba); |
573 | int lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba); | ||
547 | int lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *, struct list_head *, int); | 574 | int lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *, struct list_head *, int); |
575 | int lpfc_sli4_post_scsi_sgl_blk_ext(struct lpfc_hba *, struct list_head *, | ||
576 | int); | ||
548 | struct lpfc_cq_event *__lpfc_sli4_cq_event_alloc(struct lpfc_hba *); | 577 | struct lpfc_cq_event *__lpfc_sli4_cq_event_alloc(struct lpfc_hba *); |
549 | struct lpfc_cq_event *lpfc_sli4_cq_event_alloc(struct lpfc_hba *); | 578 | struct lpfc_cq_event *lpfc_sli4_cq_event_alloc(struct lpfc_hba *); |
550 | void __lpfc_sli4_cq_event_release(struct lpfc_hba *, struct lpfc_cq_event *); | 579 | void __lpfc_sli4_cq_event_release(struct lpfc_hba *, struct lpfc_cq_event *); |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 30ba5440c67a..1feb551a57bc 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
@@ -83,7 +83,7 @@ inline void lpfc_vport_set_state(struct lpfc_vport *vport, | |||
83 | static int | 83 | static int |
84 | lpfc_alloc_vpi(struct lpfc_hba *phba) | 84 | lpfc_alloc_vpi(struct lpfc_hba *phba) |
85 | { | 85 | { |
86 | int vpi; | 86 | unsigned long vpi; |
87 | 87 | ||
88 | spin_lock_irq(&phba->hbalock); | 88 | spin_lock_irq(&phba->hbalock); |
89 | /* Start at bit 1 because vpi zero is reserved for the physical port */ | 89 | /* Start at bit 1 because vpi zero is reserved for the physical port */ |
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 046dcc672ec1..7370c084b178 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
@@ -33,9 +33,9 @@ | |||
33 | /* | 33 | /* |
34 | * MegaRAID SAS Driver meta data | 34 | * MegaRAID SAS Driver meta data |
35 | */ | 35 | */ |
36 | #define MEGASAS_VERSION "00.00.05.34-rc1" | 36 | #define MEGASAS_VERSION "00.00.05.38-rc1" |
37 | #define MEGASAS_RELDATE "Feb. 24, 2011" | 37 | #define MEGASAS_RELDATE "May. 11, 2011" |
38 | #define MEGASAS_EXT_VERSION "Thu. Feb. 24 17:00:00 PDT 2011" | 38 | #define MEGASAS_EXT_VERSION "Wed. May. 11 17:00:00 PDT 2011" |
39 | 39 | ||
40 | /* | 40 | /* |
41 | * Device IDs | 41 | * Device IDs |
@@ -76,8 +76,8 @@ | |||
76 | #define MFI_STATE_READY 0xB0000000 | 76 | #define MFI_STATE_READY 0xB0000000 |
77 | #define MFI_STATE_OPERATIONAL 0xC0000000 | 77 | #define MFI_STATE_OPERATIONAL 0xC0000000 |
78 | #define MFI_STATE_FAULT 0xF0000000 | 78 | #define MFI_STATE_FAULT 0xF0000000 |
79 | #define MFI_RESET_REQUIRED 0x00000001 | 79 | #define MFI_RESET_REQUIRED 0x00000001 |
80 | 80 | #define MFI_RESET_ADAPTER 0x00000002 | |
81 | #define MEGAMFI_FRAME_SIZE 64 | 81 | #define MEGAMFI_FRAME_SIZE 64 |
82 | 82 | ||
83 | /* | 83 | /* |
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 89c623ebadbc..2d8cdce7b2f5 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | * | 19 | * |
20 | * FILE: megaraid_sas_base.c | 20 | * FILE: megaraid_sas_base.c |
21 | * Version : v00.00.05.34-rc1 | 21 | * Version : v00.00.05.38-rc1 |
22 | * | 22 | * |
23 | * Authors: LSI Corporation | 23 | * Authors: LSI Corporation |
24 | * Sreenivas Bagalkote | 24 | * Sreenivas Bagalkote |
@@ -437,15 +437,18 @@ megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs) | |||
437 | static int | 437 | static int |
438 | megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) | 438 | megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) |
439 | { | 439 | { |
440 | u32 status; | 440 | u32 status, mfiStatus = 0; |
441 | |||
441 | /* | 442 | /* |
442 | * Check if it is our interrupt | 443 | * Check if it is our interrupt |
443 | */ | 444 | */ |
444 | status = readl(®s->outbound_intr_status); | 445 | status = readl(®s->outbound_intr_status); |
445 | 446 | ||
446 | if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) { | 447 | if (status & MFI_REPLY_1078_MESSAGE_INTERRUPT) |
447 | return 0; | 448 | mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE; |
448 | } | 449 | |
450 | if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT) | ||
451 | mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE; | ||
449 | 452 | ||
450 | /* | 453 | /* |
451 | * Clear the interrupt by writing back the same value | 454 | * Clear the interrupt by writing back the same value |
@@ -455,8 +458,9 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) | |||
455 | /* Dummy readl to force pci flush */ | 458 | /* Dummy readl to force pci flush */ |
456 | readl(®s->outbound_doorbell_clear); | 459 | readl(®s->outbound_doorbell_clear); |
457 | 460 | ||
458 | return 1; | 461 | return mfiStatus; |
459 | } | 462 | } |
463 | |||
460 | /** | 464 | /** |
461 | * megasas_fire_cmd_ppc - Sends command to the FW | 465 | * megasas_fire_cmd_ppc - Sends command to the FW |
462 | * @frame_phys_addr : Physical address of cmd | 466 | * @frame_phys_addr : Physical address of cmd |
@@ -477,17 +481,6 @@ megasas_fire_cmd_ppc(struct megasas_instance *instance, | |||
477 | } | 481 | } |
478 | 482 | ||
479 | /** | 483 | /** |
480 | * megasas_adp_reset_ppc - For controller reset | ||
481 | * @regs: MFI register set | ||
482 | */ | ||
483 | static int | ||
484 | megasas_adp_reset_ppc(struct megasas_instance *instance, | ||
485 | struct megasas_register_set __iomem *regs) | ||
486 | { | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | /** | ||
491 | * megasas_check_reset_ppc - For controller reset check | 484 | * megasas_check_reset_ppc - For controller reset check |
492 | * @regs: MFI register set | 485 | * @regs: MFI register set |
493 | */ | 486 | */ |
@@ -495,8 +488,12 @@ static int | |||
495 | megasas_check_reset_ppc(struct megasas_instance *instance, | 488 | megasas_check_reset_ppc(struct megasas_instance *instance, |
496 | struct megasas_register_set __iomem *regs) | 489 | struct megasas_register_set __iomem *regs) |
497 | { | 490 | { |
491 | if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) | ||
492 | return 1; | ||
493 | |||
498 | return 0; | 494 | return 0; |
499 | } | 495 | } |
496 | |||
500 | static struct megasas_instance_template megasas_instance_template_ppc = { | 497 | static struct megasas_instance_template megasas_instance_template_ppc = { |
501 | 498 | ||
502 | .fire_cmd = megasas_fire_cmd_ppc, | 499 | .fire_cmd = megasas_fire_cmd_ppc, |
@@ -504,7 +501,7 @@ static struct megasas_instance_template megasas_instance_template_ppc = { | |||
504 | .disable_intr = megasas_disable_intr_ppc, | 501 | .disable_intr = megasas_disable_intr_ppc, |
505 | .clear_intr = megasas_clear_intr_ppc, | 502 | .clear_intr = megasas_clear_intr_ppc, |
506 | .read_fw_status_reg = megasas_read_fw_status_reg_ppc, | 503 | .read_fw_status_reg = megasas_read_fw_status_reg_ppc, |
507 | .adp_reset = megasas_adp_reset_ppc, | 504 | .adp_reset = megasas_adp_reset_xscale, |
508 | .check_reset = megasas_check_reset_ppc, | 505 | .check_reset = megasas_check_reset_ppc, |
509 | .service_isr = megasas_isr, | 506 | .service_isr = megasas_isr, |
510 | .tasklet = megasas_complete_cmd_dpc, | 507 | .tasklet = megasas_complete_cmd_dpc, |
@@ -620,6 +617,9 @@ static int | |||
620 | megasas_check_reset_skinny(struct megasas_instance *instance, | 617 | megasas_check_reset_skinny(struct megasas_instance *instance, |
621 | struct megasas_register_set __iomem *regs) | 618 | struct megasas_register_set __iomem *regs) |
622 | { | 619 | { |
620 | if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) | ||
621 | return 1; | ||
622 | |||
623 | return 0; | 623 | return 0; |
624 | } | 624 | } |
625 | 625 | ||
@@ -3454,7 +3454,7 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3454 | { | 3454 | { |
3455 | u32 max_sectors_1; | 3455 | u32 max_sectors_1; |
3456 | u32 max_sectors_2; | 3456 | u32 max_sectors_2; |
3457 | u32 tmp_sectors; | 3457 | u32 tmp_sectors, msix_enable; |
3458 | struct megasas_register_set __iomem *reg_set; | 3458 | struct megasas_register_set __iomem *reg_set; |
3459 | struct megasas_ctrl_info *ctrl_info; | 3459 | struct megasas_ctrl_info *ctrl_info; |
3460 | unsigned long bar_list; | 3460 | unsigned long bar_list; |
@@ -3507,6 +3507,13 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3507 | if (megasas_transition_to_ready(instance)) | 3507 | if (megasas_transition_to_ready(instance)) |
3508 | goto fail_ready_state; | 3508 | goto fail_ready_state; |
3509 | 3509 | ||
3510 | /* Check if MSI-X is supported while in ready state */ | ||
3511 | msix_enable = (instance->instancet->read_fw_status_reg(reg_set) & | ||
3512 | 0x4000000) >> 0x1a; | ||
3513 | if (msix_enable && !msix_disable && | ||
3514 | !pci_enable_msix(instance->pdev, &instance->msixentry, 1)) | ||
3515 | instance->msi_flag = 1; | ||
3516 | |||
3510 | /* Get operational params, sge flags, send init cmd to controller */ | 3517 | /* Get operational params, sge flags, send init cmd to controller */ |
3511 | if (instance->instancet->init_adapter(instance)) | 3518 | if (instance->instancet->init_adapter(instance)) |
3512 | goto fail_init_adapter; | 3519 | goto fail_init_adapter; |
@@ -4076,14 +4083,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
4076 | else | 4083 | else |
4077 | INIT_WORK(&instance->work_init, process_fw_state_change_wq); | 4084 | INIT_WORK(&instance->work_init, process_fw_state_change_wq); |
4078 | 4085 | ||
4079 | /* Try to enable MSI-X */ | ||
4080 | if ((instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078R) && | ||
4081 | (instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078DE) && | ||
4082 | (instance->pdev->device != PCI_DEVICE_ID_LSI_VERDE_ZCR) && | ||
4083 | !msix_disable && !pci_enable_msix(instance->pdev, | ||
4084 | &instance->msixentry, 1)) | ||
4085 | instance->msi_flag = 1; | ||
4086 | |||
4087 | /* | 4086 | /* |
4088 | * Initialize MFI Firmware | 4087 | * Initialize MFI Firmware |
4089 | */ | 4088 | */ |
@@ -4116,6 +4115,14 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
4116 | megasas_mgmt_info.max_index++; | 4115 | megasas_mgmt_info.max_index++; |
4117 | 4116 | ||
4118 | /* | 4117 | /* |
4118 | * Register with SCSI mid-layer | ||
4119 | */ | ||
4120 | if (megasas_io_attach(instance)) | ||
4121 | goto fail_io_attach; | ||
4122 | |||
4123 | instance->unload = 0; | ||
4124 | |||
4125 | /* | ||
4119 | * Initiate AEN (Asynchronous Event Notification) | 4126 | * Initiate AEN (Asynchronous Event Notification) |
4120 | */ | 4127 | */ |
4121 | if (megasas_start_aen(instance)) { | 4128 | if (megasas_start_aen(instance)) { |
@@ -4123,13 +4130,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
4123 | goto fail_start_aen; | 4130 | goto fail_start_aen; |
4124 | } | 4131 | } |
4125 | 4132 | ||
4126 | /* | ||
4127 | * Register with SCSI mid-layer | ||
4128 | */ | ||
4129 | if (megasas_io_attach(instance)) | ||
4130 | goto fail_io_attach; | ||
4131 | |||
4132 | instance->unload = 0; | ||
4133 | return 0; | 4133 | return 0; |
4134 | 4134 | ||
4135 | fail_start_aen: | 4135 | fail_start_aen: |
@@ -4332,10 +4332,6 @@ megasas_resume(struct pci_dev *pdev) | |||
4332 | if (megasas_set_dma_mask(pdev)) | 4332 | if (megasas_set_dma_mask(pdev)) |
4333 | goto fail_set_dma_mask; | 4333 | goto fail_set_dma_mask; |
4334 | 4334 | ||
4335 | /* Now re-enable MSI-X */ | ||
4336 | if (instance->msi_flag) | ||
4337 | pci_enable_msix(instance->pdev, &instance->msixentry, 1); | ||
4338 | |||
4339 | /* | 4335 | /* |
4340 | * Initialize MFI Firmware | 4336 | * Initialize MFI Firmware |
4341 | */ | 4337 | */ |
@@ -4348,6 +4344,10 @@ megasas_resume(struct pci_dev *pdev) | |||
4348 | if (megasas_transition_to_ready(instance)) | 4344 | if (megasas_transition_to_ready(instance)) |
4349 | goto fail_ready_state; | 4345 | goto fail_ready_state; |
4350 | 4346 | ||
4347 | /* Now re-enable MSI-X */ | ||
4348 | if (instance->msi_flag) | ||
4349 | pci_enable_msix(instance->pdev, &instance->msixentry, 1); | ||
4350 | |||
4351 | switch (instance->pdev->device) { | 4351 | switch (instance->pdev->device) { |
4352 | case PCI_DEVICE_ID_LSI_FUSION: | 4352 | case PCI_DEVICE_ID_LSI_FUSION: |
4353 | { | 4353 | { |
@@ -4384,12 +4384,6 @@ megasas_resume(struct pci_dev *pdev) | |||
4384 | 4384 | ||
4385 | instance->instancet->enable_intr(instance->reg_set); | 4385 | instance->instancet->enable_intr(instance->reg_set); |
4386 | 4386 | ||
4387 | /* | ||
4388 | * Initiate AEN (Asynchronous Event Notification) | ||
4389 | */ | ||
4390 | if (megasas_start_aen(instance)) | ||
4391 | printk(KERN_ERR "megasas: Start AEN failed\n"); | ||
4392 | |||
4393 | /* Initialize the cmd completion timer */ | 4387 | /* Initialize the cmd completion timer */ |
4394 | if (poll_mode_io) | 4388 | if (poll_mode_io) |
4395 | megasas_start_timer(instance, &instance->io_completion_timer, | 4389 | megasas_start_timer(instance, &instance->io_completion_timer, |
@@ -4397,6 +4391,12 @@ megasas_resume(struct pci_dev *pdev) | |||
4397 | MEGASAS_COMPLETION_TIMER_INTERVAL); | 4391 | MEGASAS_COMPLETION_TIMER_INTERVAL); |
4398 | instance->unload = 0; | 4392 | instance->unload = 0; |
4399 | 4393 | ||
4394 | /* | ||
4395 | * Initiate AEN (Asynchronous Event Notification) | ||
4396 | */ | ||
4397 | if (megasas_start_aen(instance)) | ||
4398 | printk(KERN_ERR "megasas: Start AEN failed\n"); | ||
4399 | |||
4400 | return 0; | 4400 | return 0; |
4401 | 4401 | ||
4402 | fail_irq: | 4402 | fail_irq: |
@@ -4527,6 +4527,11 @@ static void megasas_shutdown(struct pci_dev *pdev) | |||
4527 | instance->unload = 1; | 4527 | instance->unload = 1; |
4528 | megasas_flush_cache(instance); | 4528 | megasas_flush_cache(instance); |
4529 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); | 4529 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); |
4530 | instance->instancet->disable_intr(instance->reg_set); | ||
4531 | free_irq(instance->msi_flag ? instance->msixentry.vector : | ||
4532 | instance->pdev->irq, instance); | ||
4533 | if (instance->msi_flag) | ||
4534 | pci_disable_msix(instance->pdev); | ||
4530 | } | 4535 | } |
4531 | 4536 | ||
4532 | /** | 4537 | /** |
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 145a8cffb1fa..f13e7abd345a 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c | |||
@@ -696,22 +696,6 @@ fail_get_cmd: | |||
696 | } | 696 | } |
697 | 697 | ||
698 | /* | 698 | /* |
699 | * megasas_return_cmd_for_smid - Returns a cmd_fusion for a SMID | ||
700 | * @instance: Adapter soft state | ||
701 | * | ||
702 | */ | ||
703 | void | ||
704 | megasas_return_cmd_for_smid(struct megasas_instance *instance, u16 smid) | ||
705 | { | ||
706 | struct fusion_context *fusion; | ||
707 | struct megasas_cmd_fusion *cmd; | ||
708 | |||
709 | fusion = instance->ctrl_context; | ||
710 | cmd = fusion->cmd_list[smid - 1]; | ||
711 | megasas_return_cmd_fusion(instance, cmd); | ||
712 | } | ||
713 | |||
714 | /* | ||
715 | * megasas_get_ld_map_info - Returns FW's ld_map structure | 699 | * megasas_get_ld_map_info - Returns FW's ld_map structure |
716 | * @instance: Adapter soft state | 700 | * @instance: Adapter soft state |
717 | * @pend: Pend the command or not | 701 | * @pend: Pend the command or not |
@@ -1153,7 +1137,7 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len, | |||
1153 | u64 start_blk = io_info->pdBlock; | 1137 | u64 start_blk = io_info->pdBlock; |
1154 | u8 *cdb = io_request->CDB.CDB32; | 1138 | u8 *cdb = io_request->CDB.CDB32; |
1155 | u32 num_blocks = io_info->numBlocks; | 1139 | u32 num_blocks = io_info->numBlocks; |
1156 | u8 opcode, flagvals, groupnum, control; | 1140 | u8 opcode = 0, flagvals = 0, groupnum = 0, control = 0; |
1157 | 1141 | ||
1158 | /* Check if T10 PI (DIF) is enabled for this LD */ | 1142 | /* Check if T10 PI (DIF) is enabled for this LD */ |
1159 | ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); | 1143 | ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); |
@@ -1235,7 +1219,46 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len, | |||
1235 | cdb[8] = (u8)(num_blocks & 0xff); | 1219 | cdb[8] = (u8)(num_blocks & 0xff); |
1236 | cdb[7] = (u8)((num_blocks >> 8) & 0xff); | 1220 | cdb[7] = (u8)((num_blocks >> 8) & 0xff); |
1237 | 1221 | ||
1222 | io_request->IoFlags = 10; /* Specify 10-byte cdb */ | ||
1238 | cdb_len = 10; | 1223 | cdb_len = 10; |
1224 | } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) { | ||
1225 | /* Convert to 16 byte CDB for large LBA's */ | ||
1226 | switch (cdb_len) { | ||
1227 | case 6: | ||
1228 | opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16; | ||
1229 | control = cdb[5]; | ||
1230 | break; | ||
1231 | case 10: | ||
1232 | opcode = | ||
1233 | cdb[0] == READ_10 ? READ_16 : WRITE_16; | ||
1234 | flagvals = cdb[1]; | ||
1235 | groupnum = cdb[6]; | ||
1236 | control = cdb[9]; | ||
1237 | break; | ||
1238 | case 12: | ||
1239 | opcode = | ||
1240 | cdb[0] == READ_12 ? READ_16 : WRITE_16; | ||
1241 | flagvals = cdb[1]; | ||
1242 | groupnum = cdb[10]; | ||
1243 | control = cdb[11]; | ||
1244 | break; | ||
1245 | } | ||
1246 | |||
1247 | memset(cdb, 0, sizeof(io_request->CDB.CDB32)); | ||
1248 | |||
1249 | cdb[0] = opcode; | ||
1250 | cdb[1] = flagvals; | ||
1251 | cdb[14] = groupnum; | ||
1252 | cdb[15] = control; | ||
1253 | |||
1254 | /* Transfer length */ | ||
1255 | cdb[13] = (u8)(num_blocks & 0xff); | ||
1256 | cdb[12] = (u8)((num_blocks >> 8) & 0xff); | ||
1257 | cdb[11] = (u8)((num_blocks >> 16) & 0xff); | ||
1258 | cdb[10] = (u8)((num_blocks >> 24) & 0xff); | ||
1259 | |||
1260 | io_request->IoFlags = 16; /* Specify 16-byte cdb */ | ||
1261 | cdb_len = 16; | ||
1239 | } | 1262 | } |
1240 | 1263 | ||
1241 | /* Normal case, just load LBA here */ | 1264 | /* Normal case, just load LBA here */ |
@@ -2026,17 +2049,11 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2026 | struct fusion_context *fusion; | 2049 | struct fusion_context *fusion; |
2027 | struct megasas_cmd *cmd_mfi; | 2050 | struct megasas_cmd *cmd_mfi; |
2028 | union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; | 2051 | union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; |
2029 | u32 host_diag, abs_state; | 2052 | u32 host_diag, abs_state, status_reg, reset_adapter; |
2030 | 2053 | ||
2031 | instance = (struct megasas_instance *)shost->hostdata; | 2054 | instance = (struct megasas_instance *)shost->hostdata; |
2032 | fusion = instance->ctrl_context; | 2055 | fusion = instance->ctrl_context; |
2033 | 2056 | ||
2034 | mutex_lock(&instance->reset_mutex); | ||
2035 | set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); | ||
2036 | instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; | ||
2037 | instance->instancet->disable_intr(instance->reg_set); | ||
2038 | msleep(1000); | ||
2039 | |||
2040 | if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { | 2057 | if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { |
2041 | printk(KERN_WARNING "megaraid_sas: Hardware critical error, " | 2058 | printk(KERN_WARNING "megaraid_sas: Hardware critical error, " |
2042 | "returning FAILED.\n"); | 2059 | "returning FAILED.\n"); |
@@ -2044,6 +2061,12 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2044 | goto out; | 2061 | goto out; |
2045 | } | 2062 | } |
2046 | 2063 | ||
2064 | mutex_lock(&instance->reset_mutex); | ||
2065 | set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); | ||
2066 | instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; | ||
2067 | instance->instancet->disable_intr(instance->reg_set); | ||
2068 | msleep(1000); | ||
2069 | |||
2047 | /* First try waiting for commands to complete */ | 2070 | /* First try waiting for commands to complete */ |
2048 | if (megasas_wait_for_outstanding_fusion(instance)) { | 2071 | if (megasas_wait_for_outstanding_fusion(instance)) { |
2049 | printk(KERN_WARNING "megaraid_sas: resetting fusion " | 2072 | printk(KERN_WARNING "megaraid_sas: resetting fusion " |
@@ -2060,7 +2083,12 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2060 | } | 2083 | } |
2061 | } | 2084 | } |
2062 | 2085 | ||
2063 | if (instance->disableOnlineCtrlReset == 1) { | 2086 | status_reg = instance->instancet->read_fw_status_reg( |
2087 | instance->reg_set); | ||
2088 | abs_state = status_reg & MFI_STATE_MASK; | ||
2089 | reset_adapter = status_reg & MFI_RESET_ADAPTER; | ||
2090 | if (instance->disableOnlineCtrlReset || | ||
2091 | (abs_state == MFI_STATE_FAULT && !reset_adapter)) { | ||
2064 | /* Reset not supported, kill adapter */ | 2092 | /* Reset not supported, kill adapter */ |
2065 | printk(KERN_WARNING "megaraid_sas: Reset not supported" | 2093 | printk(KERN_WARNING "megaraid_sas: Reset not supported" |
2066 | ", killing adapter.\n"); | 2094 | ", killing adapter.\n"); |
@@ -2089,6 +2117,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2089 | 2117 | ||
2090 | /* Check that the diag write enable (DRWE) bit is on */ | 2118 | /* Check that the diag write enable (DRWE) bit is on */ |
2091 | host_diag = readl(&instance->reg_set->fusion_host_diag); | 2119 | host_diag = readl(&instance->reg_set->fusion_host_diag); |
2120 | retry = 0; | ||
2092 | while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) { | 2121 | while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) { |
2093 | msleep(100); | 2122 | msleep(100); |
2094 | host_diag = | 2123 | host_diag = |
@@ -2126,7 +2155,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2126 | 2155 | ||
2127 | abs_state = | 2156 | abs_state = |
2128 | instance->instancet->read_fw_status_reg( | 2157 | instance->instancet->read_fw_status_reg( |
2129 | instance->reg_set); | 2158 | instance->reg_set) & MFI_STATE_MASK; |
2130 | retry = 0; | 2159 | retry = 0; |
2131 | 2160 | ||
2132 | while ((abs_state <= MFI_STATE_FW_INIT) && | 2161 | while ((abs_state <= MFI_STATE_FW_INIT) && |
@@ -2134,7 +2163,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2134 | msleep(100); | 2163 | msleep(100); |
2135 | abs_state = | 2164 | abs_state = |
2136 | instance->instancet->read_fw_status_reg( | 2165 | instance->instancet->read_fw_status_reg( |
2137 | instance->reg_set); | 2166 | instance->reg_set) & MFI_STATE_MASK; |
2138 | } | 2167 | } |
2139 | if (abs_state <= MFI_STATE_FW_INIT) { | 2168 | if (abs_state <= MFI_STATE_FW_INIT) { |
2140 | printk(KERN_WARNING "megaraid_sas: firmware " | 2169 | printk(KERN_WARNING "megaraid_sas: firmware " |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 2a3c05f6db8b..dcc289c25459 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h | |||
@@ -69,11 +69,11 @@ | |||
69 | #define MPT2SAS_DRIVER_NAME "mpt2sas" | 69 | #define MPT2SAS_DRIVER_NAME "mpt2sas" |
70 | #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>" | 70 | #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>" |
71 | #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" | 71 | #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" |
72 | #define MPT2SAS_DRIVER_VERSION "08.100.00.01" | 72 | #define MPT2SAS_DRIVER_VERSION "08.100.00.02" |
73 | #define MPT2SAS_MAJOR_VERSION 08 | 73 | #define MPT2SAS_MAJOR_VERSION 08 |
74 | #define MPT2SAS_MINOR_VERSION 100 | 74 | #define MPT2SAS_MINOR_VERSION 100 |
75 | #define MPT2SAS_BUILD_VERSION 00 | 75 | #define MPT2SAS_BUILD_VERSION 00 |
76 | #define MPT2SAS_RELEASE_VERSION 01 | 76 | #define MPT2SAS_RELEASE_VERSION 02 |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * Set MPT2SAS_SG_DEPTH value based on user input. | 79 | * Set MPT2SAS_SG_DEPTH value based on user input. |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index f12e02358d6d..a7dbc6825f5f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -113,6 +113,7 @@ struct sense_info { | |||
113 | }; | 113 | }; |
114 | 114 | ||
115 | 115 | ||
116 | #define MPT2SAS_TURN_ON_FAULT_LED (0xFFFC) | ||
116 | #define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF) | 117 | #define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF) |
117 | 118 | ||
118 | /** | 119 | /** |
@@ -121,6 +122,7 @@ struct sense_info { | |||
121 | * @work: work object (ioc->fault_reset_work_q) | 122 | * @work: work object (ioc->fault_reset_work_q) |
122 | * @cancel_pending_work: flag set during reset handling | 123 | * @cancel_pending_work: flag set during reset handling |
123 | * @ioc: per adapter object | 124 | * @ioc: per adapter object |
125 | * @device_handle: device handle | ||
124 | * @VF_ID: virtual function id | 126 | * @VF_ID: virtual function id |
125 | * @VP_ID: virtual port id | 127 | * @VP_ID: virtual port id |
126 | * @ignore: flag meaning this event has been marked to ignore | 128 | * @ignore: flag meaning this event has been marked to ignore |
@@ -134,6 +136,7 @@ struct fw_event_work { | |||
134 | u8 cancel_pending_work; | 136 | u8 cancel_pending_work; |
135 | struct delayed_work delayed_work; | 137 | struct delayed_work delayed_work; |
136 | struct MPT2SAS_ADAPTER *ioc; | 138 | struct MPT2SAS_ADAPTER *ioc; |
139 | u16 device_handle; | ||
137 | u8 VF_ID; | 140 | u8 VF_ID; |
138 | u8 VP_ID; | 141 | u8 VP_ID; |
139 | u8 ignore; | 142 | u8 ignore; |
@@ -3499,6 +3502,7 @@ _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) | |||
3499 | 3502 | ||
3500 | switch (prot_type) { | 3503 | switch (prot_type) { |
3501 | case SCSI_PROT_DIF_TYPE1: | 3504 | case SCSI_PROT_DIF_TYPE1: |
3505 | case SCSI_PROT_DIF_TYPE2: | ||
3502 | 3506 | ||
3503 | /* | 3507 | /* |
3504 | * enable ref/guard checking | 3508 | * enable ref/guard checking |
@@ -3511,13 +3515,6 @@ _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) | |||
3511 | cpu_to_be32(scsi_get_lba(scmd)); | 3515 | cpu_to_be32(scsi_get_lba(scmd)); |
3512 | break; | 3516 | break; |
3513 | 3517 | ||
3514 | case SCSI_PROT_DIF_TYPE2: | ||
3515 | |||
3516 | eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | | ||
3517 | MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | | ||
3518 | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; | ||
3519 | break; | ||
3520 | |||
3521 | case SCSI_PROT_DIF_TYPE3: | 3518 | case SCSI_PROT_DIF_TYPE3: |
3522 | 3519 | ||
3523 | /* | 3520 | /* |
@@ -4047,17 +4044,75 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
4047 | #endif | 4044 | #endif |
4048 | 4045 | ||
4049 | /** | 4046 | /** |
4050 | * _scsih_smart_predicted_fault - illuminate Fault LED | 4047 | * _scsih_turn_on_fault_led - illuminate Fault LED |
4051 | * @ioc: per adapter object | 4048 | * @ioc: per adapter object |
4052 | * @handle: device handle | 4049 | * @handle: device handle |
4050 | * Context: process | ||
4053 | * | 4051 | * |
4054 | * Return nothing. | 4052 | * Return nothing. |
4055 | */ | 4053 | */ |
4056 | static void | 4054 | static void |
4057 | _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | 4055 | _scsih_turn_on_fault_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) |
4058 | { | 4056 | { |
4059 | Mpi2SepReply_t mpi_reply; | 4057 | Mpi2SepReply_t mpi_reply; |
4060 | Mpi2SepRequest_t mpi_request; | 4058 | Mpi2SepRequest_t mpi_request; |
4059 | |||
4060 | memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t)); | ||
4061 | mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; | ||
4062 | mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS; | ||
4063 | mpi_request.SlotStatus = | ||
4064 | cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); | ||
4065 | mpi_request.DevHandle = cpu_to_le16(handle); | ||
4066 | mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS; | ||
4067 | if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply, | ||
4068 | &mpi_request)) != 0) { | ||
4069 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, | ||
4070 | __FILE__, __LINE__, __func__); | ||
4071 | return; | ||
4072 | } | ||
4073 | |||
4074 | if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) { | ||
4075 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "enclosure_processor: " | ||
4076 | "ioc_status (0x%04x), loginfo(0x%08x)\n", ioc->name, | ||
4077 | le16_to_cpu(mpi_reply.IOCStatus), | ||
4078 | le32_to_cpu(mpi_reply.IOCLogInfo))); | ||
4079 | return; | ||
4080 | } | ||
4081 | } | ||
4082 | |||
4083 | /** | ||
4084 | * _scsih_send_event_to_turn_on_fault_led - fire delayed event | ||
4085 | * @ioc: per adapter object | ||
4086 | * @handle: device handle | ||
4087 | * Context: interrupt. | ||
4088 | * | ||
4089 | * Return nothing. | ||
4090 | */ | ||
4091 | static void | ||
4092 | _scsih_send_event_to_turn_on_fault_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
4093 | { | ||
4094 | struct fw_event_work *fw_event; | ||
4095 | |||
4096 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | ||
4097 | if (!fw_event) | ||
4098 | return; | ||
4099 | fw_event->event = MPT2SAS_TURN_ON_FAULT_LED; | ||
4100 | fw_event->device_handle = handle; | ||
4101 | fw_event->ioc = ioc; | ||
4102 | _scsih_fw_event_add(ioc, fw_event); | ||
4103 | } | ||
4104 | |||
4105 | /** | ||
4106 | * _scsih_smart_predicted_fault - process smart errors | ||
4107 | * @ioc: per adapter object | ||
4108 | * @handle: device handle | ||
4109 | * Context: interrupt. | ||
4110 | * | ||
4111 | * Return nothing. | ||
4112 | */ | ||
4113 | static void | ||
4114 | _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
4115 | { | ||
4061 | struct scsi_target *starget; | 4116 | struct scsi_target *starget; |
4062 | struct MPT2SAS_TARGET *sas_target_priv_data; | 4117 | struct MPT2SAS_TARGET *sas_target_priv_data; |
4063 | Mpi2EventNotificationReply_t *event_reply; | 4118 | Mpi2EventNotificationReply_t *event_reply; |
@@ -4084,30 +4139,8 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
4084 | starget_printk(KERN_WARNING, starget, "predicted fault\n"); | 4139 | starget_printk(KERN_WARNING, starget, "predicted fault\n"); |
4085 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4140 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
4086 | 4141 | ||
4087 | if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) { | 4142 | if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) |
4088 | memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t)); | 4143 | _scsih_send_event_to_turn_on_fault_led(ioc, handle); |
4089 | mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; | ||
4090 | mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS; | ||
4091 | mpi_request.SlotStatus = | ||
4092 | cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); | ||
4093 | mpi_request.DevHandle = cpu_to_le16(handle); | ||
4094 | mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS; | ||
4095 | if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply, | ||
4096 | &mpi_request)) != 0) { | ||
4097 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
4098 | ioc->name, __FILE__, __LINE__, __func__); | ||
4099 | return; | ||
4100 | } | ||
4101 | |||
4102 | if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) { | ||
4103 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
4104 | "enclosure_processor: ioc_status (0x%04x), " | ||
4105 | "loginfo(0x%08x)\n", ioc->name, | ||
4106 | le16_to_cpu(mpi_reply.IOCStatus), | ||
4107 | le32_to_cpu(mpi_reply.IOCLogInfo))); | ||
4108 | return; | ||
4109 | } | ||
4110 | } | ||
4111 | 4144 | ||
4112 | /* insert into event log */ | 4145 | /* insert into event log */ |
4113 | sz = offsetof(Mpi2EventNotificationReply_t, EventData) + | 4146 | sz = offsetof(Mpi2EventNotificationReply_t, EventData) + |
@@ -6753,6 +6786,9 @@ _firmware_event_work(struct work_struct *work) | |||
6753 | } | 6786 | } |
6754 | 6787 | ||
6755 | switch (fw_event->event) { | 6788 | switch (fw_event->event) { |
6789 | case MPT2SAS_TURN_ON_FAULT_LED: | ||
6790 | _scsih_turn_on_fault_led(ioc, fw_event->device_handle); | ||
6791 | break; | ||
6756 | case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: | 6792 | case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: |
6757 | _scsih_sas_topology_change_event(ioc, fw_event); | 6793 | _scsih_sas_topology_change_event(ioc, fw_event); |
6758 | break; | 6794 | break; |
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 58f5be4740e9..de0b1a704fb5 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c | |||
@@ -4698,12 +4698,14 @@ static int __os_scsi_tape_open(struct inode * inode, struct file * filp) | |||
4698 | break; | 4698 | break; |
4699 | 4699 | ||
4700 | if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { | 4700 | if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { |
4701 | int j; | ||
4702 | |||
4701 | STp->pos_unknown = 0; | 4703 | STp->pos_unknown = 0; |
4702 | STp->partition = STp->new_partition = 0; | 4704 | STp->partition = STp->new_partition = 0; |
4703 | if (STp->can_partitions) | 4705 | if (STp->can_partitions) |
4704 | STp->nbr_partitions = 1; /* This guess will be updated later if necessary */ | 4706 | STp->nbr_partitions = 1; /* This guess will be updated later if necessary */ |
4705 | for (i=0; i < ST_NBR_PARTITIONS; i++) { | 4707 | for (j = 0; j < ST_NBR_PARTITIONS; j++) { |
4706 | STps = &(STp->ps[i]); | 4708 | STps = &(STp->ps[j]); |
4707 | STps->rw = ST_IDLE; | 4709 | STps->rw = ST_IDLE; |
4708 | STps->eof = ST_NOEOF; | 4710 | STps->eof = ST_NOEOF; |
4709 | STps->at_sm = 0; | 4711 | STps->at_sm = 0; |
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 7f636b118287..fca6a8953070 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c | |||
@@ -4252,8 +4252,8 @@ static ssize_t pmcraid_show_drv_version( | |||
4252 | char *buf | 4252 | char *buf |
4253 | ) | 4253 | ) |
4254 | { | 4254 | { |
4255 | return snprintf(buf, PAGE_SIZE, "version: %s, build date: %s\n", | 4255 | return snprintf(buf, PAGE_SIZE, "version: %s\n", |
4256 | PMCRAID_DRIVER_VERSION, PMCRAID_DRIVER_DATE); | 4256 | PMCRAID_DRIVER_VERSION); |
4257 | } | 4257 | } |
4258 | 4258 | ||
4259 | static struct device_attribute pmcraid_driver_version_attr = { | 4259 | static struct device_attribute pmcraid_driver_version_attr = { |
@@ -6096,9 +6096,8 @@ static int __init pmcraid_init(void) | |||
6096 | dev_t dev; | 6096 | dev_t dev; |
6097 | int error; | 6097 | int error; |
6098 | 6098 | ||
6099 | pmcraid_info("%s Device Driver version: %s %s\n", | 6099 | pmcraid_info("%s Device Driver version: %s\n", |
6100 | PMCRAID_DRIVER_NAME, | 6100 | PMCRAID_DRIVER_NAME, PMCRAID_DRIVER_VERSION); |
6101 | PMCRAID_DRIVER_VERSION, PMCRAID_DRIVER_DATE); | ||
6102 | 6101 | ||
6103 | error = alloc_chrdev_region(&dev, 0, | 6102 | error = alloc_chrdev_region(&dev, 0, |
6104 | PMCRAID_MAX_ADAPTERS, | 6103 | PMCRAID_MAX_ADAPTERS, |
diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h index 34e4c915002e..f920baf3ff24 100644 --- a/drivers/scsi/pmcraid.h +++ b/drivers/scsi/pmcraid.h | |||
@@ -43,7 +43,6 @@ | |||
43 | #define PMCRAID_DRIVER_NAME "PMC MaxRAID" | 43 | #define PMCRAID_DRIVER_NAME "PMC MaxRAID" |
44 | #define PMCRAID_DEVFILE "pmcsas" | 44 | #define PMCRAID_DEVFILE "pmcsas" |
45 | #define PMCRAID_DRIVER_VERSION "1.0.3" | 45 | #define PMCRAID_DRIVER_VERSION "1.0.3" |
46 | #define PMCRAID_DRIVER_DATE __DATE__ | ||
47 | 46 | ||
48 | #define PMCRAID_FW_VERSION_1 0x002 | 47 | #define PMCRAID_FW_VERSION_1 0x002 |
49 | 48 | ||
diff --git a/drivers/scsi/qla4xxx/Makefile b/drivers/scsi/qla4xxx/Makefile index 0339ff03a535..252523d7847e 100644 --- a/drivers/scsi/qla4xxx/Makefile +++ b/drivers/scsi/qla4xxx/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \ | 1 | qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \ |
2 | ql4_nx.o ql4_nvram.o ql4_dbg.o | 2 | ql4_nx.o ql4_nvram.o ql4_dbg.o ql4_attr.o |
3 | 3 | ||
4 | obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o | 4 | obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o |
5 | 5 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_attr.c b/drivers/scsi/qla4xxx/ql4_attr.c new file mode 100644 index 000000000000..864d018631c0 --- /dev/null +++ b/drivers/scsi/qla4xxx/ql4_attr.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * QLogic iSCSI HBA Driver | ||
3 | * Copyright (c) 2003-2011 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qla4xxx for copyright and licensing details. | ||
6 | */ | ||
7 | |||
8 | #include "ql4_def.h" | ||
9 | #include "ql4_glbl.h" | ||
10 | #include "ql4_dbg.h" | ||
11 | |||
12 | /* Scsi_Host attributes. */ | ||
13 | static ssize_t | ||
14 | qla4xxx_fw_version_show(struct device *dev, | ||
15 | struct device_attribute *attr, char *buf) | ||
16 | { | ||
17 | struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); | ||
18 | |||
19 | if (is_qla8022(ha)) | ||
20 | return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n", | ||
21 | ha->firmware_version[0], | ||
22 | ha->firmware_version[1], | ||
23 | ha->patch_number, ha->build_number); | ||
24 | else | ||
25 | return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d.%02d\n", | ||
26 | ha->firmware_version[0], | ||
27 | ha->firmware_version[1], | ||
28 | ha->patch_number, ha->build_number); | ||
29 | } | ||
30 | |||
31 | static ssize_t | ||
32 | qla4xxx_serial_num_show(struct device *dev, struct device_attribute *attr, | ||
33 | char *buf) | ||
34 | { | ||
35 | struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); | ||
36 | return snprintf(buf, PAGE_SIZE, "%s\n", ha->serial_number); | ||
37 | } | ||
38 | |||
39 | static ssize_t | ||
40 | qla4xxx_iscsi_version_show(struct device *dev, struct device_attribute *attr, | ||
41 | char *buf) | ||
42 | { | ||
43 | struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); | ||
44 | return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->iscsi_major, | ||
45 | ha->iscsi_minor); | ||
46 | } | ||
47 | |||
48 | static ssize_t | ||
49 | qla4xxx_optrom_version_show(struct device *dev, struct device_attribute *attr, | ||
50 | char *buf) | ||
51 | { | ||
52 | struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); | ||
53 | return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d.%02d\n", | ||
54 | ha->bootload_major, ha->bootload_minor, | ||
55 | ha->bootload_patch, ha->bootload_build); | ||
56 | } | ||
57 | |||
58 | static DEVICE_ATTR(fw_version, S_IRUGO, qla4xxx_fw_version_show, NULL); | ||
59 | static DEVICE_ATTR(serial_num, S_IRUGO, qla4xxx_serial_num_show, NULL); | ||
60 | static DEVICE_ATTR(iscsi_version, S_IRUGO, qla4xxx_iscsi_version_show, NULL); | ||
61 | static DEVICE_ATTR(optrom_version, S_IRUGO, qla4xxx_optrom_version_show, NULL); | ||
62 | |||
63 | struct device_attribute *qla4xxx_host_attrs[] = { | ||
64 | &dev_attr_fw_version, | ||
65 | &dev_attr_serial_num, | ||
66 | &dev_attr_iscsi_version, | ||
67 | &dev_attr_optrom_version, | ||
68 | NULL, | ||
69 | }; | ||
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 4757878d59dd..473c5c872b39 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -115,7 +115,7 @@ | |||
115 | #define INVALID_ENTRY 0xFFFF | 115 | #define INVALID_ENTRY 0xFFFF |
116 | #define MAX_CMDS_TO_RISC 1024 | 116 | #define MAX_CMDS_TO_RISC 1024 |
117 | #define MAX_SRBS MAX_CMDS_TO_RISC | 117 | #define MAX_SRBS MAX_CMDS_TO_RISC |
118 | #define MBOX_AEN_REG_COUNT 5 | 118 | #define MBOX_AEN_REG_COUNT 8 |
119 | #define MAX_INIT_RETRIES 5 | 119 | #define MAX_INIT_RETRIES 5 |
120 | 120 | ||
121 | /* | 121 | /* |
@@ -368,7 +368,6 @@ struct scsi_qla_host { | |||
368 | #define AF_INIT_DONE 1 /* 0x00000002 */ | 368 | #define AF_INIT_DONE 1 /* 0x00000002 */ |
369 | #define AF_MBOX_COMMAND 2 /* 0x00000004 */ | 369 | #define AF_MBOX_COMMAND 2 /* 0x00000004 */ |
370 | #define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ | 370 | #define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ |
371 | #define AF_DPC_SCHEDULED 5 /* 0x00000020 */ | ||
372 | #define AF_INTERRUPTS_ON 6 /* 0x00000040 */ | 371 | #define AF_INTERRUPTS_ON 6 /* 0x00000040 */ |
373 | #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ | 372 | #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ |
374 | #define AF_LINK_UP 8 /* 0x00000100 */ | 373 | #define AF_LINK_UP 8 /* 0x00000100 */ |
@@ -584,6 +583,14 @@ struct scsi_qla_host { | |||
584 | uint32_t nx_reset_timeout; | 583 | uint32_t nx_reset_timeout; |
585 | 584 | ||
586 | struct completion mbx_intr_comp; | 585 | struct completion mbx_intr_comp; |
586 | |||
587 | /* --- From About Firmware --- */ | ||
588 | uint16_t iscsi_major; | ||
589 | uint16_t iscsi_minor; | ||
590 | uint16_t bootload_major; | ||
591 | uint16_t bootload_minor; | ||
592 | uint16_t bootload_patch; | ||
593 | uint16_t bootload_build; | ||
587 | }; | 594 | }; |
588 | 595 | ||
589 | static inline int is_ipv4_enabled(struct scsi_qla_host *ha) | 596 | static inline int is_ipv4_enabled(struct scsi_qla_host *ha) |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 31e2bf97198c..01082aa77098 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
@@ -690,6 +690,29 @@ struct mbx_sys_info { | |||
690 | uint8_t reserved[12]; /* 34-3f */ | 690 | uint8_t reserved[12]; /* 34-3f */ |
691 | }; | 691 | }; |
692 | 692 | ||
693 | struct about_fw_info { | ||
694 | uint16_t fw_major; /* 00 - 01 */ | ||
695 | uint16_t fw_minor; /* 02 - 03 */ | ||
696 | uint16_t fw_patch; /* 04 - 05 */ | ||
697 | uint16_t fw_build; /* 06 - 07 */ | ||
698 | uint8_t fw_build_date[16]; /* 08 - 17 ASCII String */ | ||
699 | uint8_t fw_build_time[16]; /* 18 - 27 ASCII String */ | ||
700 | uint8_t fw_build_user[16]; /* 28 - 37 ASCII String */ | ||
701 | uint16_t fw_load_source; /* 38 - 39 */ | ||
702 | /* 1 = Flash Primary, | ||
703 | 2 = Flash Secondary, | ||
704 | 3 = Host Download | ||
705 | */ | ||
706 | uint8_t reserved1[6]; /* 3A - 3F */ | ||
707 | uint16_t iscsi_major; /* 40 - 41 */ | ||
708 | uint16_t iscsi_minor; /* 42 - 43 */ | ||
709 | uint16_t bootload_major; /* 44 - 45 */ | ||
710 | uint16_t bootload_minor; /* 46 - 47 */ | ||
711 | uint16_t bootload_patch; /* 48 - 49 */ | ||
712 | uint16_t bootload_build; /* 4A - 4B */ | ||
713 | uint8_t reserved2[180]; /* 4C - FF */ | ||
714 | }; | ||
715 | |||
693 | struct crash_record { | 716 | struct crash_record { |
694 | uint16_t fw_major_version; /* 00 - 01 */ | 717 | uint16_t fw_major_version; /* 00 - 01 */ |
695 | uint16_t fw_minor_version; /* 02 - 03 */ | 718 | uint16_t fw_minor_version; /* 02 - 03 */ |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index cc53e3fbd78c..a53a256c1f8d 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -61,7 +61,7 @@ struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha); | |||
61 | int qla4xxx_add_sess(struct ddb_entry *); | 61 | int qla4xxx_add_sess(struct ddb_entry *); |
62 | void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry); | 62 | void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry); |
63 | int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host *ha); | 63 | int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host *ha); |
64 | int qla4xxx_get_fw_version(struct scsi_qla_host * ha); | 64 | int qla4xxx_about_firmware(struct scsi_qla_host *ha); |
65 | void qla4xxx_interrupt_service_routine(struct scsi_qla_host *ha, | 65 | void qla4xxx_interrupt_service_routine(struct scsi_qla_host *ha, |
66 | uint32_t intr_status); | 66 | uint32_t intr_status); |
67 | int qla4xxx_init_rings(struct scsi_qla_host *ha); | 67 | int qla4xxx_init_rings(struct scsi_qla_host *ha); |
@@ -139,4 +139,5 @@ extern int ql4xextended_error_logging; | |||
139 | extern int ql4xdontresethba; | 139 | extern int ql4xdontresethba; |
140 | extern int ql4xenablemsix; | 140 | extern int ql4xenablemsix; |
141 | 141 | ||
142 | extern struct device_attribute *qla4xxx_host_attrs[]; | ||
142 | #endif /* _QLA4x_GBL_H */ | 143 | #endif /* _QLA4x_GBL_H */ |
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 48e2241ddaf4..42ed5db2d530 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
@@ -1275,7 +1275,7 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, | |||
1275 | if (ha->isp_ops->start_firmware(ha) == QLA_ERROR) | 1275 | if (ha->isp_ops->start_firmware(ha) == QLA_ERROR) |
1276 | goto exit_init_hba; | 1276 | goto exit_init_hba; |
1277 | 1277 | ||
1278 | if (qla4xxx_get_fw_version(ha) == QLA_ERROR) | 1278 | if (qla4xxx_about_firmware(ha) == QLA_ERROR) |
1279 | goto exit_init_hba; | 1279 | goto exit_init_hba; |
1280 | 1280 | ||
1281 | if (ha->isp_ops->get_sys_info(ha) == QLA_ERROR) | 1281 | if (ha->isp_ops->get_sys_info(ha) == QLA_ERROR) |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 2f40ac761cd4..0e72921c752d 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -25,9 +25,14 @@ static void qla4xxx_copy_sense(struct scsi_qla_host *ha, | |||
25 | 25 | ||
26 | memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | 26 | memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); |
27 | sense_len = le16_to_cpu(sts_entry->senseDataByteCnt); | 27 | sense_len = le16_to_cpu(sts_entry->senseDataByteCnt); |
28 | if (sense_len == 0) | 28 | if (sense_len == 0) { |
29 | DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d:%d: %s:" | ||
30 | " sense len 0\n", ha->host_no, | ||
31 | cmd->device->channel, cmd->device->id, | ||
32 | cmd->device->lun, __func__)); | ||
33 | ha->status_srb = NULL; | ||
29 | return; | 34 | return; |
30 | 35 | } | |
31 | /* Save total available sense length, | 36 | /* Save total available sense length, |
32 | * not to exceed cmd's sense buffer size */ | 37 | * not to exceed cmd's sense buffer size */ |
33 | sense_len = min_t(uint16_t, sense_len, SCSI_SENSE_BUFFERSIZE); | 38 | sense_len = min_t(uint16_t, sense_len, SCSI_SENSE_BUFFERSIZE); |
@@ -541,6 +546,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
541 | case MBOX_ASTS_UNSOLICITED_PDU_RECEIVED: /* Connection mode */ | 546 | case MBOX_ASTS_UNSOLICITED_PDU_RECEIVED: /* Connection mode */ |
542 | case MBOX_ASTS_IPSEC_SYSTEM_FATAL_ERROR: | 547 | case MBOX_ASTS_IPSEC_SYSTEM_FATAL_ERROR: |
543 | case MBOX_ASTS_SUBNET_STATE_CHANGE: | 548 | case MBOX_ASTS_SUBNET_STATE_CHANGE: |
549 | case MBOX_ASTS_DUPLICATE_IP: | ||
544 | /* No action */ | 550 | /* No action */ |
545 | DEBUG2(printk("scsi%ld: AEN %04x\n", ha->host_no, | 551 | DEBUG2(printk("scsi%ld: AEN %04x\n", ha->host_no, |
546 | mbox_status)); | 552 | mbox_status)); |
@@ -593,11 +599,13 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
593 | mbox_sts[i]; | 599 | mbox_sts[i]; |
594 | 600 | ||
595 | /* print debug message */ | 601 | /* print debug message */ |
596 | DEBUG2(printk("scsi%ld: AEN[%d] %04x queued" | 602 | DEBUG2(printk("scsi%ld: AEN[%d] %04x queued " |
597 | " mb1:0x%x mb2:0x%x mb3:0x%x mb4:0x%x\n", | 603 | "mb1:0x%x mb2:0x%x mb3:0x%x " |
598 | ha->host_no, ha->aen_in, mbox_sts[0], | 604 | "mb4:0x%x mb5:0x%x\n", |
599 | mbox_sts[1], mbox_sts[2], mbox_sts[3], | 605 | ha->host_no, ha->aen_in, |
600 | mbox_sts[4])); | 606 | mbox_sts[0], mbox_sts[1], |
607 | mbox_sts[2], mbox_sts[3], | ||
608 | mbox_sts[4], mbox_sts[5])); | ||
601 | 609 | ||
602 | /* advance pointer */ | 610 | /* advance pointer */ |
603 | ha->aen_in++; | 611 | ha->aen_in++; |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index d78b58dc5011..fce8289e9752 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -86,22 +86,8 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
86 | msleep(10); | 86 | msleep(10); |
87 | } | 87 | } |
88 | 88 | ||
89 | /* To prevent overwriting mailbox registers for a command that has | ||
90 | * not yet been serviced, check to see if an active command | ||
91 | * (AEN, IOCB, etc.) is interrupting, then service it. | ||
92 | * ----------------------------------------------------------------- | ||
93 | */ | ||
94 | spin_lock_irqsave(&ha->hardware_lock, flags); | 89 | spin_lock_irqsave(&ha->hardware_lock, flags); |
95 | 90 | ||
96 | if (!is_qla8022(ha)) { | ||
97 | intr_status = readl(&ha->reg->ctrl_status); | ||
98 | if (intr_status & CSR_SCSI_PROCESSOR_INTR) { | ||
99 | /* Service existing interrupt */ | ||
100 | ha->isp_ops->interrupt_service_routine(ha, intr_status); | ||
101 | clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | ha->mbox_status_count = outCount; | 91 | ha->mbox_status_count = outCount; |
106 | for (i = 0; i < outCount; i++) | 92 | for (i = 0; i < outCount; i++) |
107 | ha->mbox_status[i] = 0; | 93 | ha->mbox_status[i] = 0; |
@@ -1057,38 +1043,65 @@ int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr, | |||
1057 | } | 1043 | } |
1058 | 1044 | ||
1059 | /** | 1045 | /** |
1060 | * qla4xxx_get_fw_version - gets firmware version | 1046 | * qla4xxx_about_firmware - gets FW, iscsi draft and boot loader version |
1061 | * @ha: Pointer to host adapter structure. | 1047 | * @ha: Pointer to host adapter structure. |
1062 | * | 1048 | * |
1063 | * Retrieves the firmware version on HBA. In QLA4010, mailboxes 2 & 3 may | 1049 | * Retrieves the FW version, iSCSI draft version & bootloader version of HBA. |
1064 | * hold an address for data. Make sure that we write 0 to those mailboxes, | 1050 | * Mailboxes 2 & 3 may hold an address for data. Make sure that we write 0 to |
1065 | * if unused. | 1051 | * those mailboxes, if unused. |
1066 | **/ | 1052 | **/ |
1067 | int qla4xxx_get_fw_version(struct scsi_qla_host * ha) | 1053 | int qla4xxx_about_firmware(struct scsi_qla_host *ha) |
1068 | { | 1054 | { |
1055 | struct about_fw_info *about_fw = NULL; | ||
1056 | dma_addr_t about_fw_dma; | ||
1069 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | 1057 | uint32_t mbox_cmd[MBOX_REG_COUNT]; |
1070 | uint32_t mbox_sts[MBOX_REG_COUNT]; | 1058 | uint32_t mbox_sts[MBOX_REG_COUNT]; |
1059 | int status = QLA_ERROR; | ||
1060 | |||
1061 | about_fw = dma_alloc_coherent(&ha->pdev->dev, | ||
1062 | sizeof(struct about_fw_info), | ||
1063 | &about_fw_dma, GFP_KERNEL); | ||
1064 | if (!about_fw) { | ||
1065 | DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory " | ||
1066 | "for about_fw\n", __func__)); | ||
1067 | return status; | ||
1068 | } | ||
1071 | 1069 | ||
1072 | /* Get firmware version. */ | 1070 | memset(about_fw, 0, sizeof(struct about_fw_info)); |
1073 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | 1071 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); |
1074 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | 1072 | memset(&mbox_sts, 0, sizeof(mbox_sts)); |
1075 | 1073 | ||
1076 | mbox_cmd[0] = MBOX_CMD_ABOUT_FW; | 1074 | mbox_cmd[0] = MBOX_CMD_ABOUT_FW; |
1077 | 1075 | mbox_cmd[2] = LSDW(about_fw_dma); | |
1078 | if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != | 1076 | mbox_cmd[3] = MSDW(about_fw_dma); |
1079 | QLA_SUCCESS) { | 1077 | mbox_cmd[4] = sizeof(struct about_fw_info); |
1080 | DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ " | 1078 | |
1081 | "status %04X\n", ha->host_no, __func__, mbox_sts[0])); | 1079 | status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, |
1082 | return QLA_ERROR; | 1080 | &mbox_cmd[0], &mbox_sts[0]); |
1081 | if (status != QLA_SUCCESS) { | ||
1082 | DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_ABOUT_FW " | ||
1083 | "failed w/ status %04X\n", __func__, | ||
1084 | mbox_sts[0])); | ||
1085 | goto exit_about_fw; | ||
1083 | } | 1086 | } |
1084 | 1087 | ||
1085 | /* Save firmware version information. */ | 1088 | /* Save version information. */ |
1086 | ha->firmware_version[0] = mbox_sts[1]; | 1089 | ha->firmware_version[0] = le16_to_cpu(about_fw->fw_major); |
1087 | ha->firmware_version[1] = mbox_sts[2]; | 1090 | ha->firmware_version[1] = le16_to_cpu(about_fw->fw_minor); |
1088 | ha->patch_number = mbox_sts[3]; | 1091 | ha->patch_number = le16_to_cpu(about_fw->fw_patch); |
1089 | ha->build_number = mbox_sts[4]; | 1092 | ha->build_number = le16_to_cpu(about_fw->fw_build); |
1093 | ha->iscsi_major = le16_to_cpu(about_fw->iscsi_major); | ||
1094 | ha->iscsi_minor = le16_to_cpu(about_fw->iscsi_minor); | ||
1095 | ha->bootload_major = le16_to_cpu(about_fw->bootload_major); | ||
1096 | ha->bootload_minor = le16_to_cpu(about_fw->bootload_minor); | ||
1097 | ha->bootload_patch = le16_to_cpu(about_fw->bootload_patch); | ||
1098 | ha->bootload_build = le16_to_cpu(about_fw->bootload_build); | ||
1099 | status = QLA_SUCCESS; | ||
1090 | 1100 | ||
1091 | return QLA_SUCCESS; | 1101 | exit_about_fw: |
1102 | dma_free_coherent(&ha->pdev->dev, sizeof(struct about_fw_info), | ||
1103 | about_fw, about_fw_dma); | ||
1104 | return status; | ||
1092 | } | 1105 | } |
1093 | 1106 | ||
1094 | static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, | 1107 | static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 03e522b2fe0b..fdfe27b38698 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
@@ -964,12 +964,26 @@ qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) | |||
964 | /* Halt all the indiviual PEGs and other blocks of the ISP */ | 964 | /* Halt all the indiviual PEGs and other blocks of the ISP */ |
965 | qla4_8xxx_rom_lock(ha); | 965 | qla4_8xxx_rom_lock(ha); |
966 | 966 | ||
967 | /* mask all niu interrupts */ | 967 | /* disable all I2Q */ |
968 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_I2Q + 0x10, 0x0); | ||
969 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_I2Q + 0x14, 0x0); | ||
970 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_I2Q + 0x18, 0x0); | ||
971 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_I2Q + 0x1c, 0x0); | ||
972 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_I2Q + 0x20, 0x0); | ||
973 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_I2Q + 0x24, 0x0); | ||
974 | |||
975 | /* disable all niu interrupts */ | ||
968 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff); | 976 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff); |
969 | /* disable xge rx/tx */ | 977 | /* disable xge rx/tx */ |
970 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00); | 978 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00); |
971 | /* disable xg1 rx/tx */ | 979 | /* disable xg1 rx/tx */ |
972 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00); | 980 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00); |
981 | /* disable sideband mac */ | ||
982 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x90000, 0x00); | ||
983 | /* disable ap0 mac */ | ||
984 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0xa0000, 0x00); | ||
985 | /* disable ap1 mac */ | ||
986 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0xb0000, 0x00); | ||
973 | 987 | ||
974 | /* halt sre */ | 988 | /* halt sre */ |
975 | val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000); | 989 | val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000); |
@@ -984,6 +998,7 @@ qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) | |||
984 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0); | 998 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0); |
985 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0); | 999 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0); |
986 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0); | 1000 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0); |
1001 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x200, 0x0); | ||
987 | 1002 | ||
988 | /* halt pegs */ | 1003 | /* halt pegs */ |
989 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1); | 1004 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1); |
@@ -991,9 +1006,9 @@ qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) | |||
991 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1); | 1006 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1); |
992 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1); | 1007 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1); |
993 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1); | 1008 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1); |
1009 | msleep(5); | ||
994 | 1010 | ||
995 | /* big hammer */ | 1011 | /* big hammer */ |
996 | msleep(1000); | ||
997 | if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) | 1012 | if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) |
998 | /* don't reset CAM block on reset */ | 1013 | /* don't reset CAM block on reset */ |
999 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff); | 1014 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff); |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index c22f2a764d9d..f2364ec59f03 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -124,6 +124,7 @@ static struct scsi_host_template qla4xxx_driver_template = { | |||
124 | .sg_tablesize = SG_ALL, | 124 | .sg_tablesize = SG_ALL, |
125 | 125 | ||
126 | .max_sectors = 0xFFFF, | 126 | .max_sectors = 0xFFFF, |
127 | .shost_attrs = qla4xxx_host_attrs, | ||
127 | }; | 128 | }; |
128 | 129 | ||
129 | static struct iscsi_transport qla4xxx_iscsi_transport = { | 130 | static struct iscsi_transport qla4xxx_iscsi_transport = { |
@@ -412,8 +413,7 @@ void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha) | |||
412 | 413 | ||
413 | static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, | 414 | static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, |
414 | struct ddb_entry *ddb_entry, | 415 | struct ddb_entry *ddb_entry, |
415 | struct scsi_cmnd *cmd, | 416 | struct scsi_cmnd *cmd) |
416 | void (*done)(struct scsi_cmnd *)) | ||
417 | { | 417 | { |
418 | struct srb *srb; | 418 | struct srb *srb; |
419 | 419 | ||
@@ -427,7 +427,6 @@ static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, | |||
427 | srb->cmd = cmd; | 427 | srb->cmd = cmd; |
428 | srb->flags = 0; | 428 | srb->flags = 0; |
429 | CMD_SP(cmd) = (void *)srb; | 429 | CMD_SP(cmd) = (void *)srb; |
430 | cmd->scsi_done = done; | ||
431 | 430 | ||
432 | return srb; | 431 | return srb; |
433 | } | 432 | } |
@@ -458,9 +457,8 @@ void qla4xxx_srb_compl(struct kref *ref) | |||
458 | 457 | ||
459 | /** | 458 | /** |
460 | * qla4xxx_queuecommand - scsi layer issues scsi command to driver. | 459 | * qla4xxx_queuecommand - scsi layer issues scsi command to driver. |
460 | * @host: scsi host | ||
461 | * @cmd: Pointer to Linux's SCSI command structure | 461 | * @cmd: Pointer to Linux's SCSI command structure |
462 | * @done_fn: Function that the driver calls to notify the SCSI mid-layer | ||
463 | * that the command has been processed. | ||
464 | * | 462 | * |
465 | * Remarks: | 463 | * Remarks: |
466 | * This routine is invoked by Linux to send a SCSI command to the driver. | 464 | * This routine is invoked by Linux to send a SCSI command to the driver. |
@@ -470,10 +468,9 @@ void qla4xxx_srb_compl(struct kref *ref) | |||
470 | * completion handling). Unfortunely, it sometimes calls the scheduler | 468 | * completion handling). Unfortunely, it sometimes calls the scheduler |
471 | * in interrupt context which is a big NO! NO!. | 469 | * in interrupt context which is a big NO! NO!. |
472 | **/ | 470 | **/ |
473 | static int qla4xxx_queuecommand_lck(struct scsi_cmnd *cmd, | 471 | static int qla4xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) |
474 | void (*done)(struct scsi_cmnd *)) | ||
475 | { | 472 | { |
476 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); | 473 | struct scsi_qla_host *ha = to_qla_host(host); |
477 | struct ddb_entry *ddb_entry = cmd->device->hostdata; | 474 | struct ddb_entry *ddb_entry = cmd->device->hostdata; |
478 | struct iscsi_cls_session *sess = ddb_entry->sess; | 475 | struct iscsi_cls_session *sess = ddb_entry->sess; |
479 | struct srb *srb; | 476 | struct srb *srb; |
@@ -515,37 +512,29 @@ static int qla4xxx_queuecommand_lck(struct scsi_cmnd *cmd, | |||
515 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) | 512 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) |
516 | goto qc_host_busy; | 513 | goto qc_host_busy; |
517 | 514 | ||
518 | spin_unlock_irq(ha->host->host_lock); | 515 | srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd); |
519 | |||
520 | srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done); | ||
521 | if (!srb) | 516 | if (!srb) |
522 | goto qc_host_busy_lock; | 517 | goto qc_host_busy; |
523 | 518 | ||
524 | rval = qla4xxx_send_command_to_isp(ha, srb); | 519 | rval = qla4xxx_send_command_to_isp(ha, srb); |
525 | if (rval != QLA_SUCCESS) | 520 | if (rval != QLA_SUCCESS) |
526 | goto qc_host_busy_free_sp; | 521 | goto qc_host_busy_free_sp; |
527 | 522 | ||
528 | spin_lock_irq(ha->host->host_lock); | ||
529 | return 0; | 523 | return 0; |
530 | 524 | ||
531 | qc_host_busy_free_sp: | 525 | qc_host_busy_free_sp: |
532 | qla4xxx_srb_free_dma(ha, srb); | 526 | qla4xxx_srb_free_dma(ha, srb); |
533 | mempool_free(srb, ha->srb_mempool); | 527 | mempool_free(srb, ha->srb_mempool); |
534 | 528 | ||
535 | qc_host_busy_lock: | ||
536 | spin_lock_irq(ha->host->host_lock); | ||
537 | |||
538 | qc_host_busy: | 529 | qc_host_busy: |
539 | return SCSI_MLQUEUE_HOST_BUSY; | 530 | return SCSI_MLQUEUE_HOST_BUSY; |
540 | 531 | ||
541 | qc_fail_command: | 532 | qc_fail_command: |
542 | done(cmd); | 533 | cmd->scsi_done(cmd); |
543 | 534 | ||
544 | return 0; | 535 | return 0; |
545 | } | 536 | } |
546 | 537 | ||
547 | static DEF_SCSI_QCMD(qla4xxx_queuecommand) | ||
548 | |||
549 | /** | 538 | /** |
550 | * qla4xxx_mem_free - frees memory allocated to adapter | 539 | * qla4xxx_mem_free - frees memory allocated to adapter |
551 | * @ha: Pointer to host adapter structure. | 540 | * @ha: Pointer to host adapter structure. |
@@ -679,7 +668,27 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
679 | if (ha->seconds_since_last_heartbeat == 2) { | 668 | if (ha->seconds_since_last_heartbeat == 2) { |
680 | ha->seconds_since_last_heartbeat = 0; | 669 | ha->seconds_since_last_heartbeat = 0; |
681 | halt_status = qla4_8xxx_rd_32(ha, | 670 | halt_status = qla4_8xxx_rd_32(ha, |
682 | QLA82XX_PEG_HALT_STATUS1); | 671 | QLA82XX_PEG_HALT_STATUS1); |
672 | |||
673 | ql4_printk(KERN_INFO, ha, | ||
674 | "scsi(%ld): %s, Dumping hw/fw registers:\n " | ||
675 | " PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2:" | ||
676 | " 0x%x,\n PEG_NET_0_PC: 0x%x, PEG_NET_1_PC:" | ||
677 | " 0x%x,\n PEG_NET_2_PC: 0x%x, PEG_NET_3_PC:" | ||
678 | " 0x%x,\n PEG_NET_4_PC: 0x%x\n", | ||
679 | ha->host_no, __func__, halt_status, | ||
680 | qla4_8xxx_rd_32(ha, | ||
681 | QLA82XX_PEG_HALT_STATUS2), | ||
682 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_0 + | ||
683 | 0x3c), | ||
684 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_1 + | ||
685 | 0x3c), | ||
686 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_2 + | ||
687 | 0x3c), | ||
688 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_3 + | ||
689 | 0x3c), | ||
690 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_4 + | ||
691 | 0x3c)); | ||
683 | 692 | ||
684 | /* Since we cannot change dev_state in interrupt | 693 | /* Since we cannot change dev_state in interrupt |
685 | * context, set appropriate DPC flag then wakeup | 694 | * context, set appropriate DPC flag then wakeup |
@@ -715,7 +724,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | |||
715 | /* don't poll if reset is going on */ | 724 | /* don't poll if reset is going on */ |
716 | if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || | 725 | if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || |
717 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 726 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || |
718 | test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags))) { | 727 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) { |
719 | if (dev_state == QLA82XX_DEV_NEED_RESET && | 728 | if (dev_state == QLA82XX_DEV_NEED_RESET && |
720 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { | 729 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { |
721 | if (!ql4xdontresethba) { | 730 | if (!ql4xdontresethba) { |
@@ -839,7 +848,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
839 | } | 848 | } |
840 | 849 | ||
841 | /* Wakeup the dpc routine for this adapter, if needed. */ | 850 | /* Wakeup the dpc routine for this adapter, if needed. */ |
842 | if ((start_dpc || | 851 | if (start_dpc || |
843 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 852 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || |
844 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || | 853 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || |
845 | test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || | 854 | test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || |
@@ -849,9 +858,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
849 | test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) || | 858 | test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) || |
850 | test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || | 859 | test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || |
851 | test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || | 860 | test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || |
852 | test_bit(DPC_AEN, &ha->dpc_flags)) && | 861 | test_bit(DPC_AEN, &ha->dpc_flags)) { |
853 | !test_bit(AF_DPC_SCHEDULED, &ha->flags) && | ||
854 | ha->dpc_thread) { | ||
855 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" | 862 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" |
856 | " - dpc flags = 0x%lx\n", | 863 | " - dpc flags = 0x%lx\n", |
857 | ha->host_no, __func__, ha->dpc_flags)); | 864 | ha->host_no, __func__, ha->dpc_flags)); |
@@ -1241,11 +1248,8 @@ static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha) | |||
1241 | 1248 | ||
1242 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha) | 1249 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha) |
1243 | { | 1250 | { |
1244 | if (ha->dpc_thread && | 1251 | if (ha->dpc_thread) |
1245 | !test_bit(AF_DPC_SCHEDULED, &ha->flags)) { | ||
1246 | set_bit(AF_DPC_SCHEDULED, &ha->flags); | ||
1247 | queue_work(ha->dpc_thread, &ha->dpc_work); | 1252 | queue_work(ha->dpc_thread, &ha->dpc_work); |
1248 | } | ||
1249 | } | 1253 | } |
1250 | 1254 | ||
1251 | /** | 1255 | /** |
@@ -1272,12 +1276,12 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1272 | 1276 | ||
1273 | /* Initialization not yet finished. Don't do anything yet. */ | 1277 | /* Initialization not yet finished. Don't do anything yet. */ |
1274 | if (!test_bit(AF_INIT_DONE, &ha->flags)) | 1278 | if (!test_bit(AF_INIT_DONE, &ha->flags)) |
1275 | goto do_dpc_exit; | 1279 | return; |
1276 | 1280 | ||
1277 | if (test_bit(AF_EEH_BUSY, &ha->flags)) { | 1281 | if (test_bit(AF_EEH_BUSY, &ha->flags)) { |
1278 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n", | 1282 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n", |
1279 | ha->host_no, __func__, ha->flags)); | 1283 | ha->host_no, __func__, ha->flags)); |
1280 | goto do_dpc_exit; | 1284 | return; |
1281 | } | 1285 | } |
1282 | 1286 | ||
1283 | if (is_qla8022(ha)) { | 1287 | if (is_qla8022(ha)) { |
@@ -1384,8 +1388,6 @@ dpc_post_reset_ha: | |||
1384 | } | 1388 | } |
1385 | } | 1389 | } |
1386 | 1390 | ||
1387 | do_dpc_exit: | ||
1388 | clear_bit(AF_DPC_SCHEDULED, &ha->flags); | ||
1389 | } | 1391 | } |
1390 | 1392 | ||
1391 | /** | 1393 | /** |
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 603155769407..610492877253 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h | |||
@@ -5,4 +5,4 @@ | |||
5 | * See LICENSE.qla4xxx for copyright and licensing details. | 5 | * See LICENSE.qla4xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k6" | 8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k7" |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index abea2cf05c2e..a4b9cdbaaa0b 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -50,6 +50,8 @@ | |||
50 | #define BUS_RESET_SETTLE_TIME (10) | 50 | #define BUS_RESET_SETTLE_TIME (10) |
51 | #define HOST_RESET_SETTLE_TIME (10) | 51 | #define HOST_RESET_SETTLE_TIME (10) |
52 | 52 | ||
53 | static int scsi_eh_try_stu(struct scsi_cmnd *scmd); | ||
54 | |||
53 | /* called with shost->host_lock held */ | 55 | /* called with shost->host_lock held */ |
54 | void scsi_eh_wakeup(struct Scsi_Host *shost) | 56 | void scsi_eh_wakeup(struct Scsi_Host *shost) |
55 | { | 57 | { |
@@ -947,6 +949,48 @@ retry_tur: | |||
947 | } | 949 | } |
948 | 950 | ||
949 | /** | 951 | /** |
952 | * scsi_eh_test_devices - check if devices are responding from error recovery. | ||
953 | * @cmd_list: scsi commands in error recovery. | ||
954 | * @work_q: queue for commands which still need more error recovery | ||
955 | * @done_q: queue for commands which are finished | ||
956 | * @try_stu: boolean on if a STU command should be tried in addition to TUR. | ||
957 | * | ||
958 | * Decription: | ||
959 | * Tests if devices are in a working state. Commands to devices now in | ||
960 | * a working state are sent to the done_q while commands to devices which | ||
961 | * are still failing to respond are returned to the work_q for more | ||
962 | * processing. | ||
963 | **/ | ||
964 | static int scsi_eh_test_devices(struct list_head *cmd_list, | ||
965 | struct list_head *work_q, | ||
966 | struct list_head *done_q, int try_stu) | ||
967 | { | ||
968 | struct scsi_cmnd *scmd, *next; | ||
969 | struct scsi_device *sdev; | ||
970 | int finish_cmds; | ||
971 | |||
972 | while (!list_empty(cmd_list)) { | ||
973 | scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry); | ||
974 | sdev = scmd->device; | ||
975 | |||
976 | finish_cmds = !scsi_device_online(scmd->device) || | ||
977 | (try_stu && !scsi_eh_try_stu(scmd) && | ||
978 | !scsi_eh_tur(scmd)) || | ||
979 | !scsi_eh_tur(scmd); | ||
980 | |||
981 | list_for_each_entry_safe(scmd, next, cmd_list, eh_entry) | ||
982 | if (scmd->device == sdev) { | ||
983 | if (finish_cmds) | ||
984 | scsi_eh_finish_cmd(scmd, done_q); | ||
985 | else | ||
986 | list_move_tail(&scmd->eh_entry, work_q); | ||
987 | } | ||
988 | } | ||
989 | return list_empty(work_q); | ||
990 | } | ||
991 | |||
992 | |||
993 | /** | ||
950 | * scsi_eh_abort_cmds - abort pending commands. | 994 | * scsi_eh_abort_cmds - abort pending commands. |
951 | * @work_q: &list_head for pending commands. | 995 | * @work_q: &list_head for pending commands. |
952 | * @done_q: &list_head for processed commands. | 996 | * @done_q: &list_head for processed commands. |
@@ -962,6 +1006,7 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, | |||
962 | struct list_head *done_q) | 1006 | struct list_head *done_q) |
963 | { | 1007 | { |
964 | struct scsi_cmnd *scmd, *next; | 1008 | struct scsi_cmnd *scmd, *next; |
1009 | LIST_HEAD(check_list); | ||
965 | int rtn; | 1010 | int rtn; |
966 | 1011 | ||
967 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { | 1012 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { |
@@ -973,11 +1018,10 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, | |||
973 | rtn = scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd); | 1018 | rtn = scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd); |
974 | if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { | 1019 | if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { |
975 | scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD; | 1020 | scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD; |
976 | if (!scsi_device_online(scmd->device) || | 1021 | if (rtn == FAST_IO_FAIL) |
977 | rtn == FAST_IO_FAIL || | ||
978 | !scsi_eh_tur(scmd)) { | ||
979 | scsi_eh_finish_cmd(scmd, done_q); | 1022 | scsi_eh_finish_cmd(scmd, done_q); |
980 | } | 1023 | else |
1024 | list_move_tail(&scmd->eh_entry, &check_list); | ||
981 | } else | 1025 | } else |
982 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting" | 1026 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting" |
983 | " cmd failed:" | 1027 | " cmd failed:" |
@@ -986,7 +1030,7 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, | |||
986 | scmd)); | 1030 | scmd)); |
987 | } | 1031 | } |
988 | 1032 | ||
989 | return list_empty(work_q); | 1033 | return scsi_eh_test_devices(&check_list, work_q, done_q, 0); |
990 | } | 1034 | } |
991 | 1035 | ||
992 | /** | 1036 | /** |
@@ -1137,6 +1181,7 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, | |||
1137 | struct list_head *done_q) | 1181 | struct list_head *done_q) |
1138 | { | 1182 | { |
1139 | LIST_HEAD(tmp_list); | 1183 | LIST_HEAD(tmp_list); |
1184 | LIST_HEAD(check_list); | ||
1140 | 1185 | ||
1141 | list_splice_init(work_q, &tmp_list); | 1186 | list_splice_init(work_q, &tmp_list); |
1142 | 1187 | ||
@@ -1161,9 +1206,9 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, | |||
1161 | if (scmd_id(scmd) != id) | 1206 | if (scmd_id(scmd) != id) |
1162 | continue; | 1207 | continue; |
1163 | 1208 | ||
1164 | if ((rtn == SUCCESS || rtn == FAST_IO_FAIL) | 1209 | if (rtn == SUCCESS) |
1165 | && (!scsi_device_online(scmd->device) || | 1210 | list_move_tail(&scmd->eh_entry, &check_list); |
1166 | rtn == FAST_IO_FAIL || !scsi_eh_tur(scmd))) | 1211 | else if (rtn == FAST_IO_FAIL) |
1167 | scsi_eh_finish_cmd(scmd, done_q); | 1212 | scsi_eh_finish_cmd(scmd, done_q); |
1168 | else | 1213 | else |
1169 | /* push back on work queue for further processing */ | 1214 | /* push back on work queue for further processing */ |
@@ -1171,7 +1216,7 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, | |||
1171 | } | 1216 | } |
1172 | } | 1217 | } |
1173 | 1218 | ||
1174 | return list_empty(work_q); | 1219 | return scsi_eh_test_devices(&check_list, work_q, done_q, 0); |
1175 | } | 1220 | } |
1176 | 1221 | ||
1177 | /** | 1222 | /** |
@@ -1185,6 +1230,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, | |||
1185 | struct list_head *done_q) | 1230 | struct list_head *done_q) |
1186 | { | 1231 | { |
1187 | struct scsi_cmnd *scmd, *chan_scmd, *next; | 1232 | struct scsi_cmnd *scmd, *chan_scmd, *next; |
1233 | LIST_HEAD(check_list); | ||
1188 | unsigned int channel; | 1234 | unsigned int channel; |
1189 | int rtn; | 1235 | int rtn; |
1190 | 1236 | ||
@@ -1216,12 +1262,14 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, | |||
1216 | rtn = scsi_try_bus_reset(chan_scmd); | 1262 | rtn = scsi_try_bus_reset(chan_scmd); |
1217 | if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { | 1263 | if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { |
1218 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { | 1264 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { |
1219 | if (channel == scmd_channel(scmd)) | 1265 | if (channel == scmd_channel(scmd)) { |
1220 | if (!scsi_device_online(scmd->device) || | 1266 | if (rtn == FAST_IO_FAIL) |
1221 | rtn == FAST_IO_FAIL || | ||
1222 | !scsi_eh_tur(scmd)) | ||
1223 | scsi_eh_finish_cmd(scmd, | 1267 | scsi_eh_finish_cmd(scmd, |
1224 | done_q); | 1268 | done_q); |
1269 | else | ||
1270 | list_move_tail(&scmd->eh_entry, | ||
1271 | &check_list); | ||
1272 | } | ||
1225 | } | 1273 | } |
1226 | } else { | 1274 | } else { |
1227 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: BRST" | 1275 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: BRST" |
@@ -1230,7 +1278,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, | |||
1230 | channel)); | 1278 | channel)); |
1231 | } | 1279 | } |
1232 | } | 1280 | } |
1233 | return list_empty(work_q); | 1281 | return scsi_eh_test_devices(&check_list, work_q, done_q, 0); |
1234 | } | 1282 | } |
1235 | 1283 | ||
1236 | /** | 1284 | /** |
@@ -1242,6 +1290,7 @@ static int scsi_eh_host_reset(struct list_head *work_q, | |||
1242 | struct list_head *done_q) | 1290 | struct list_head *done_q) |
1243 | { | 1291 | { |
1244 | struct scsi_cmnd *scmd, *next; | 1292 | struct scsi_cmnd *scmd, *next; |
1293 | LIST_HEAD(check_list); | ||
1245 | int rtn; | 1294 | int rtn; |
1246 | 1295 | ||
1247 | if (!list_empty(work_q)) { | 1296 | if (!list_empty(work_q)) { |
@@ -1252,12 +1301,10 @@ static int scsi_eh_host_reset(struct list_head *work_q, | |||
1252 | , current->comm)); | 1301 | , current->comm)); |
1253 | 1302 | ||
1254 | rtn = scsi_try_host_reset(scmd); | 1303 | rtn = scsi_try_host_reset(scmd); |
1255 | if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { | 1304 | if (rtn == SUCCESS) { |
1305 | list_splice_init(work_q, &check_list); | ||
1306 | } else if (rtn == FAST_IO_FAIL) { | ||
1256 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { | 1307 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { |
1257 | if (!scsi_device_online(scmd->device) || | ||
1258 | rtn == FAST_IO_FAIL || | ||
1259 | (!scsi_eh_try_stu(scmd) && !scsi_eh_tur(scmd)) || | ||
1260 | !scsi_eh_tur(scmd)) | ||
1261 | scsi_eh_finish_cmd(scmd, done_q); | 1308 | scsi_eh_finish_cmd(scmd, done_q); |
1262 | } | 1309 | } |
1263 | } else { | 1310 | } else { |
@@ -1266,7 +1313,7 @@ static int scsi_eh_host_reset(struct list_head *work_q, | |||
1266 | current->comm)); | 1313 | current->comm)); |
1267 | } | 1314 | } |
1268 | } | 1315 | } |
1269 | return list_empty(work_q); | 1316 | return scsi_eh_test_devices(&check_list, work_q, done_q, 1); |
1270 | } | 1317 | } |
1271 | 1318 | ||
1272 | /** | 1319 | /** |
diff --git a/drivers/scsi/scsi_trace.c b/drivers/scsi/scsi_trace.c index b587289cfacb..2bea4f0b684a 100644 --- a/drivers/scsi/scsi_trace.c +++ b/drivers/scsi/scsi_trace.c | |||
@@ -59,6 +59,10 @@ scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len) | |||
59 | trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", | 59 | trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", |
60 | (unsigned long long)lba, (unsigned long long)txlen, | 60 | (unsigned long long)lba, (unsigned long long)txlen, |
61 | cdb[1] >> 5); | 61 | cdb[1] >> 5); |
62 | |||
63 | if (cdb[0] == WRITE_SAME) | ||
64 | trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1); | ||
65 | |||
62 | trace_seq_putc(p, 0); | 66 | trace_seq_putc(p, 0); |
63 | 67 | ||
64 | return ret; | 68 | return ret; |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index bd0806e64e85..953773cb26d9 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -490,7 +490,8 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) | |||
490 | unsigned int max_blocks = 0; | 490 | unsigned int max_blocks = 0; |
491 | 491 | ||
492 | q->limits.discard_zeroes_data = sdkp->lbprz; | 492 | q->limits.discard_zeroes_data = sdkp->lbprz; |
493 | q->limits.discard_alignment = sdkp->unmap_alignment; | 493 | q->limits.discard_alignment = sdkp->unmap_alignment * |
494 | logical_block_size; | ||
494 | q->limits.discard_granularity = | 495 | q->limits.discard_granularity = |
495 | max(sdkp->physical_block_size, | 496 | max(sdkp->physical_block_size, |
496 | sdkp->unmap_granularity * logical_block_size); | 497 | sdkp->unmap_granularity * logical_block_size); |
@@ -2021,16 +2022,26 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
2021 | 2022 | ||
2022 | int dbd; | 2023 | int dbd; |
2023 | int modepage; | 2024 | int modepage; |
2025 | int first_len; | ||
2024 | struct scsi_mode_data data; | 2026 | struct scsi_mode_data data; |
2025 | struct scsi_sense_hdr sshdr; | 2027 | struct scsi_sense_hdr sshdr; |
2026 | int old_wce = sdkp->WCE; | 2028 | int old_wce = sdkp->WCE; |
2027 | int old_rcd = sdkp->RCD; | 2029 | int old_rcd = sdkp->RCD; |
2028 | int old_dpofua = sdkp->DPOFUA; | 2030 | int old_dpofua = sdkp->DPOFUA; |
2029 | 2031 | ||
2030 | if (sdp->skip_ms_page_8) | 2032 | first_len = 4; |
2031 | goto defaults; | 2033 | if (sdp->skip_ms_page_8) { |
2032 | 2034 | if (sdp->type == TYPE_RBC) | |
2033 | if (sdp->type == TYPE_RBC) { | 2035 | goto defaults; |
2036 | else { | ||
2037 | if (sdp->skip_ms_page_3f) | ||
2038 | goto defaults; | ||
2039 | modepage = 0x3F; | ||
2040 | if (sdp->use_192_bytes_for_3f) | ||
2041 | first_len = 192; | ||
2042 | dbd = 0; | ||
2043 | } | ||
2044 | } else if (sdp->type == TYPE_RBC) { | ||
2034 | modepage = 6; | 2045 | modepage = 6; |
2035 | dbd = 8; | 2046 | dbd = 8; |
2036 | } else { | 2047 | } else { |
@@ -2039,13 +2050,15 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
2039 | } | 2050 | } |
2040 | 2051 | ||
2041 | /* cautiously ask */ | 2052 | /* cautiously ask */ |
2042 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, 4, &data, &sshdr); | 2053 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, first_len, |
2054 | &data, &sshdr); | ||
2043 | 2055 | ||
2044 | if (!scsi_status_is_good(res)) | 2056 | if (!scsi_status_is_good(res)) |
2045 | goto bad_sense; | 2057 | goto bad_sense; |
2046 | 2058 | ||
2047 | if (!data.header_length) { | 2059 | if (!data.header_length) { |
2048 | modepage = 6; | 2060 | modepage = 6; |
2061 | first_len = 0; | ||
2049 | sd_printk(KERN_ERR, sdkp, "Missing header in MODE_SENSE response\n"); | 2062 | sd_printk(KERN_ERR, sdkp, "Missing header in MODE_SENSE response\n"); |
2050 | } | 2063 | } |
2051 | 2064 | ||
@@ -2058,30 +2071,61 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
2058 | */ | 2071 | */ |
2059 | if (len < 3) | 2072 | if (len < 3) |
2060 | goto bad_sense; | 2073 | goto bad_sense; |
2061 | if (len > 20) | 2074 | else if (len > SD_BUF_SIZE) { |
2062 | len = 20; | 2075 | sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter " |
2063 | 2076 | "data from %d to %d bytes\n", len, SD_BUF_SIZE); | |
2064 | /* Take headers and block descriptors into account */ | 2077 | len = SD_BUF_SIZE; |
2065 | len += data.header_length + data.block_descriptor_length; | 2078 | } |
2066 | if (len > SD_BUF_SIZE) | 2079 | if (modepage == 0x3F && sdp->use_192_bytes_for_3f) |
2067 | goto bad_sense; | 2080 | len = 192; |
2068 | 2081 | ||
2069 | /* Get the data */ | 2082 | /* Get the data */ |
2070 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); | 2083 | if (len > first_len) |
2084 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, | ||
2085 | &data, &sshdr); | ||
2071 | 2086 | ||
2072 | if (scsi_status_is_good(res)) { | 2087 | if (scsi_status_is_good(res)) { |
2073 | int offset = data.header_length + data.block_descriptor_length; | 2088 | int offset = data.header_length + data.block_descriptor_length; |
2074 | 2089 | ||
2075 | if (offset >= SD_BUF_SIZE - 2) { | 2090 | while (offset < len) { |
2076 | sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n"); | 2091 | u8 page_code = buffer[offset] & 0x3F; |
2077 | goto defaults; | 2092 | u8 spf = buffer[offset] & 0x40; |
2093 | |||
2094 | if (page_code == 8 || page_code == 6) { | ||
2095 | /* We're interested only in the first 3 bytes. | ||
2096 | */ | ||
2097 | if (len - offset <= 2) { | ||
2098 | sd_printk(KERN_ERR, sdkp, "Incomplete " | ||
2099 | "mode parameter data\n"); | ||
2100 | goto defaults; | ||
2101 | } else { | ||
2102 | modepage = page_code; | ||
2103 | goto Page_found; | ||
2104 | } | ||
2105 | } else { | ||
2106 | /* Go to the next page */ | ||
2107 | if (spf && len - offset > 3) | ||
2108 | offset += 4 + (buffer[offset+2] << 8) + | ||
2109 | buffer[offset+3]; | ||
2110 | else if (!spf && len - offset > 1) | ||
2111 | offset += 2 + buffer[offset+1]; | ||
2112 | else { | ||
2113 | sd_printk(KERN_ERR, sdkp, "Incomplete " | ||
2114 | "mode parameter data\n"); | ||
2115 | goto defaults; | ||
2116 | } | ||
2117 | } | ||
2078 | } | 2118 | } |
2079 | 2119 | ||
2080 | if ((buffer[offset] & 0x3f) != modepage) { | 2120 | if (modepage == 0x3F) { |
2121 | sd_printk(KERN_ERR, sdkp, "No Caching mode page " | ||
2122 | "present\n"); | ||
2123 | goto defaults; | ||
2124 | } else if ((buffer[offset] & 0x3f) != modepage) { | ||
2081 | sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); | 2125 | sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); |
2082 | goto defaults; | 2126 | goto defaults; |
2083 | } | 2127 | } |
2084 | 2128 | Page_found: | |
2085 | if (modepage == 8) { | 2129 | if (modepage == 8) { |
2086 | sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); | 2130 | sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); |
2087 | sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); | 2131 | sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); |
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index 9f4b58b7daad..7e22b737dfd8 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c | |||
@@ -307,7 +307,7 @@ static inline int find_and_clear_bit_16(unsigned long *field) | |||
307 | "0: bsfw %1,%w0\n\t" | 307 | "0: bsfw %1,%w0\n\t" |
308 | "btr %0,%1\n\t" | 308 | "btr %0,%1\n\t" |
309 | "jnc 0b" | 309 | "jnc 0b" |
310 | : "=&r" (rv), "=m" (*field) :); | 310 | : "=&r" (rv), "+m" (*field) :); |
311 | 311 | ||
312 | return rv; | 312 | return rv; |
313 | } | 313 | } |
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index 97ae716134d0..c0ee4ea28a19 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c | |||
@@ -2051,8 +2051,7 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs, | |||
2051 | for (i = 0; i < MAX_SETUP_ARGS; i++) | 2051 | for (i = 0; i < MAX_SETUP_ARGS; i++) |
2052 | printk("%s,", setup_args[i]); | 2052 | printk("%s,", setup_args[i]); |
2053 | printk("\n"); | 2053 | printk("\n"); |
2054 | printk(" Version %s - %s, Compiled %s at %s\n", | 2054 | printk(" Version %s - %s\n", WD33C93_VERSION, WD33C93_DATE); |
2055 | WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__); | ||
2056 | } | 2055 | } |
2057 | 2056 | ||
2058 | int | 2057 | int |
@@ -2132,8 +2131,8 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off | |||
2132 | bp = buf; | 2131 | bp = buf; |
2133 | *bp = '\0'; | 2132 | *bp = '\0'; |
2134 | if (hd->proc & PR_VERSION) { | 2133 | if (hd->proc & PR_VERSION) { |
2135 | sprintf(tbuf, "\nVersion %s - %s. Compiled %s %s", | 2134 | sprintf(tbuf, "\nVersion %s - %s.", |
2136 | WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__); | 2135 | WD33C93_VERSION, WD33C93_DATE); |
2137 | strcat(bp, tbuf); | 2136 | strcat(bp, tbuf); |
2138 | } | 2137 | } |
2139 | if (hd->proc & PR_INFO) { | 2138 | if (hd->proc & PR_INFO) { |
diff --git a/drivers/staging/generic_serial/rio/rioinit.c b/drivers/staging/generic_serial/rio/rioinit.c index 24a282bb89d4..fb62b383f1de 100644 --- a/drivers/staging/generic_serial/rio/rioinit.c +++ b/drivers/staging/generic_serial/rio/rioinit.c | |||
@@ -381,7 +381,7 @@ struct rioVersion *RIOVersid(void) | |||
381 | { | 381 | { |
382 | strlcpy(stVersion.version, "RIO driver for linux V1.0", | 382 | strlcpy(stVersion.version, "RIO driver for linux V1.0", |
383 | sizeof(stVersion.version)); | 383 | sizeof(stVersion.version)); |
384 | strlcpy(stVersion.buildDate, __DATE__, | 384 | strlcpy(stVersion.buildDate, "Aug 15 2010", |
385 | sizeof(stVersion.buildDate)); | 385 | sizeof(stVersion.buildDate)); |
386 | 386 | ||
387 | return &stVersion; | 387 | return &stVersion; |
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index aed4e464d31c..dee2a2c909f5 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <scsi/scsi_host.h> | 31 | #include <scsi/scsi_host.h> |
32 | #include <scsi/scsi_device.h> | 32 | #include <scsi/scsi_device.h> |
33 | #include <scsi/scsi_cmnd.h> | 33 | #include <scsi/scsi_cmnd.h> |
34 | #include <scsi/libsas.h> /* For TASK_ATTR_* */ | 34 | #include <scsi/scsi_tcq.h> |
35 | 35 | ||
36 | #include <target/target_core_base.h> | 36 | #include <target/target_core_base.h> |
37 | #include <target/target_core_transport.h> | 37 | #include <target/target_core_transport.h> |
@@ -95,17 +95,17 @@ static struct se_cmd *tcm_loop_allocate_core_cmd( | |||
95 | if (sc->device->tagged_supported) { | 95 | if (sc->device->tagged_supported) { |
96 | switch (sc->tag) { | 96 | switch (sc->tag) { |
97 | case HEAD_OF_QUEUE_TAG: | 97 | case HEAD_OF_QUEUE_TAG: |
98 | sam_task_attr = TASK_ATTR_HOQ; | 98 | sam_task_attr = MSG_HEAD_TAG; |
99 | break; | 99 | break; |
100 | case ORDERED_QUEUE_TAG: | 100 | case ORDERED_QUEUE_TAG: |
101 | sam_task_attr = TASK_ATTR_ORDERED; | 101 | sam_task_attr = MSG_ORDERED_TAG; |
102 | break; | 102 | break; |
103 | default: | 103 | default: |
104 | sam_task_attr = TASK_ATTR_SIMPLE; | 104 | sam_task_attr = MSG_SIMPLE_TAG; |
105 | break; | 105 | break; |
106 | } | 106 | } |
107 | } else | 107 | } else |
108 | sam_task_attr = TASK_ATTR_SIMPLE; | 108 | sam_task_attr = MSG_SIMPLE_TAG; |
109 | 109 | ||
110 | /* | 110 | /* |
111 | * Initialize struct se_cmd descriptor from target_core_mod infrastructure | 111 | * Initialize struct se_cmd descriptor from target_core_mod infrastructure |
@@ -379,7 +379,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc) | |||
379 | * Initialize struct se_cmd descriptor from target_core_mod infrastructure | 379 | * Initialize struct se_cmd descriptor from target_core_mod infrastructure |
380 | */ | 380 | */ |
381 | transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 0, | 381 | transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 0, |
382 | DMA_NONE, TASK_ATTR_SIMPLE, | 382 | DMA_NONE, MSG_SIMPLE_TAG, |
383 | &tl_cmd->tl_sense_buf[0]); | 383 | &tl_cmd->tl_sense_buf[0]); |
384 | /* | 384 | /* |
385 | * Allocate the LUN_RESET TMR | 385 | * Allocate the LUN_RESET TMR |
@@ -939,18 +939,6 @@ static u16 tcm_loop_get_fabric_sense_len(void) | |||
939 | return 0; | 939 | return 0; |
940 | } | 940 | } |
941 | 941 | ||
942 | static u64 tcm_loop_pack_lun(unsigned int lun) | ||
943 | { | ||
944 | u64 result; | ||
945 | |||
946 | /* LSB of lun into byte 1 big-endian */ | ||
947 | result = ((lun & 0xff) << 8); | ||
948 | /* use flat space addressing method */ | ||
949 | result |= 0x40 | ((lun >> 8) & 0x3f); | ||
950 | |||
951 | return cpu_to_le64(result); | ||
952 | } | ||
953 | |||
954 | static char *tcm_loop_dump_proto_id(struct tcm_loop_hba *tl_hba) | 942 | static char *tcm_loop_dump_proto_id(struct tcm_loop_hba *tl_hba) |
955 | { | 943 | { |
956 | switch (tl_hba->tl_proto_id) { | 944 | switch (tl_hba->tl_proto_id) { |
@@ -1481,7 +1469,6 @@ static int tcm_loop_register_configfs(void) | |||
1481 | fabric->tf_ops.set_fabric_sense_len = &tcm_loop_set_fabric_sense_len; | 1469 | fabric->tf_ops.set_fabric_sense_len = &tcm_loop_set_fabric_sense_len; |
1482 | fabric->tf_ops.get_fabric_sense_len = &tcm_loop_get_fabric_sense_len; | 1470 | fabric->tf_ops.get_fabric_sense_len = &tcm_loop_get_fabric_sense_len; |
1483 | fabric->tf_ops.is_state_remove = &tcm_loop_is_state_remove; | 1471 | fabric->tf_ops.is_state_remove = &tcm_loop_is_state_remove; |
1484 | fabric->tf_ops.pack_lun = &tcm_loop_pack_lun; | ||
1485 | 1472 | ||
1486 | tf_cg = &fabric->tf_group; | 1473 | tf_cg = &fabric->tf_group; |
1487 | /* | 1474 | /* |
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index a5f44a6e6e1d..ee6fad979b50 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c | |||
@@ -497,10 +497,6 @@ static int target_fabric_tf_ops_check( | |||
497 | printk(KERN_ERR "Missing tfo->is_state_remove()\n"); | 497 | printk(KERN_ERR "Missing tfo->is_state_remove()\n"); |
498 | return -EINVAL; | 498 | return -EINVAL; |
499 | } | 499 | } |
500 | if (!(tfo->pack_lun)) { | ||
501 | printk(KERN_ERR "Missing tfo->pack_lun()\n"); | ||
502 | return -EINVAL; | ||
503 | } | ||
504 | /* | 500 | /* |
505 | * We at least require tfo->fabric_make_wwn(), tfo->fabric_drop_wwn() | 501 | * We at least require tfo->fabric_make_wwn(), tfo->fabric_drop_wwn() |
506 | * tfo->fabric_make_tpg() and tfo->fabric_drop_tpg() in | 502 | * tfo->fabric_make_tpg() and tfo->fabric_drop_tpg() in |
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index d25e20829012..8407f9ca2b31 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <net/sock.h> | 38 | #include <net/sock.h> |
39 | #include <net/tcp.h> | 39 | #include <net/tcp.h> |
40 | #include <scsi/scsi.h> | 40 | #include <scsi/scsi.h> |
41 | #include <scsi/scsi_device.h> | ||
41 | 42 | ||
42 | #include <target/target_core_base.h> | 43 | #include <target/target_core_base.h> |
43 | #include <target/target_core_device.h> | 44 | #include <target/target_core_device.h> |
@@ -150,13 +151,13 @@ out: | |||
150 | 151 | ||
151 | { | 152 | { |
152 | struct se_device *dev = se_lun->lun_se_dev; | 153 | struct se_device *dev = se_lun->lun_se_dev; |
153 | spin_lock(&dev->stats_lock); | 154 | spin_lock_irq(&dev->stats_lock); |
154 | dev->num_cmds++; | 155 | dev->num_cmds++; |
155 | if (se_cmd->data_direction == DMA_TO_DEVICE) | 156 | if (se_cmd->data_direction == DMA_TO_DEVICE) |
156 | dev->write_bytes += se_cmd->data_length; | 157 | dev->write_bytes += se_cmd->data_length; |
157 | else if (se_cmd->data_direction == DMA_FROM_DEVICE) | 158 | else if (se_cmd->data_direction == DMA_FROM_DEVICE) |
158 | dev->read_bytes += se_cmd->data_length; | 159 | dev->read_bytes += se_cmd->data_length; |
159 | spin_unlock(&dev->stats_lock); | 160 | spin_unlock_irq(&dev->stats_lock); |
160 | } | 161 | } |
161 | 162 | ||
162 | /* | 163 | /* |
@@ -658,8 +659,7 @@ int transport_core_report_lun_response(struct se_cmd *se_cmd) | |||
658 | struct se_session *se_sess = SE_SESS(se_cmd); | 659 | struct se_session *se_sess = SE_SESS(se_cmd); |
659 | struct se_task *se_task; | 660 | struct se_task *se_task; |
660 | unsigned char *buf = (unsigned char *)T_TASK(se_cmd)->t_task_buf; | 661 | unsigned char *buf = (unsigned char *)T_TASK(se_cmd)->t_task_buf; |
661 | u32 cdb_offset = 0, lun_count = 0, offset = 8; | 662 | u32 cdb_offset = 0, lun_count = 0, offset = 8, i; |
662 | u64 i, lun; | ||
663 | 663 | ||
664 | list_for_each_entry(se_task, &T_TASK(se_cmd)->t_task_list, t_list) | 664 | list_for_each_entry(se_task, &T_TASK(se_cmd)->t_task_list, t_list) |
665 | break; | 665 | break; |
@@ -675,15 +675,7 @@ int transport_core_report_lun_response(struct se_cmd *se_cmd) | |||
675 | * a $FABRIC_MOD. In that case, report LUN=0 only. | 675 | * a $FABRIC_MOD. In that case, report LUN=0 only. |
676 | */ | 676 | */ |
677 | if (!(se_sess)) { | 677 | if (!(se_sess)) { |
678 | lun = 0; | 678 | int_to_scsilun(0, (struct scsi_lun *)&buf[offset]); |
679 | buf[offset++] = ((lun >> 56) & 0xff); | ||
680 | buf[offset++] = ((lun >> 48) & 0xff); | ||
681 | buf[offset++] = ((lun >> 40) & 0xff); | ||
682 | buf[offset++] = ((lun >> 32) & 0xff); | ||
683 | buf[offset++] = ((lun >> 24) & 0xff); | ||
684 | buf[offset++] = ((lun >> 16) & 0xff); | ||
685 | buf[offset++] = ((lun >> 8) & 0xff); | ||
686 | buf[offset++] = (lun & 0xff); | ||
687 | lun_count = 1; | 679 | lun_count = 1; |
688 | goto done; | 680 | goto done; |
689 | } | 681 | } |
@@ -703,15 +695,8 @@ int transport_core_report_lun_response(struct se_cmd *se_cmd) | |||
703 | if ((cdb_offset + 8) >= se_cmd->data_length) | 695 | if ((cdb_offset + 8) >= se_cmd->data_length) |
704 | continue; | 696 | continue; |
705 | 697 | ||
706 | lun = cpu_to_be64(CMD_TFO(se_cmd)->pack_lun(deve->mapped_lun)); | 698 | int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]); |
707 | buf[offset++] = ((lun >> 56) & 0xff); | 699 | offset += 8; |
708 | buf[offset++] = ((lun >> 48) & 0xff); | ||
709 | buf[offset++] = ((lun >> 40) & 0xff); | ||
710 | buf[offset++] = ((lun >> 32) & 0xff); | ||
711 | buf[offset++] = ((lun >> 24) & 0xff); | ||
712 | buf[offset++] = ((lun >> 16) & 0xff); | ||
713 | buf[offset++] = ((lun >> 8) & 0xff); | ||
714 | buf[offset++] = (lun & 0xff); | ||
715 | cdb_offset += 8; | 700 | cdb_offset += 8; |
716 | } | 701 | } |
717 | spin_unlock_irq(&SE_NODE_ACL(se_sess)->device_list_lock); | 702 | spin_unlock_irq(&SE_NODE_ACL(se_sess)->device_list_lock); |
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 7ff6a35f26ac..331d423fd0e0 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c | |||
@@ -41,7 +41,7 @@ | |||
41 | #include <scsi/scsi_device.h> | 41 | #include <scsi/scsi_device.h> |
42 | #include <scsi/scsi_cmnd.h> | 42 | #include <scsi/scsi_cmnd.h> |
43 | #include <scsi/scsi_host.h> | 43 | #include <scsi/scsi_host.h> |
44 | #include <scsi/libsas.h> /* For TASK_ATTR_* */ | 44 | #include <scsi/scsi_tcq.h> |
45 | 45 | ||
46 | #include <target/target_core_base.h> | 46 | #include <target/target_core_base.h> |
47 | #include <target/target_core_device.h> | 47 | #include <target/target_core_device.h> |
@@ -911,7 +911,7 @@ static int pscsi_do_task(struct se_task *task) | |||
911 | * descriptor | 911 | * descriptor |
912 | */ | 912 | */ |
913 | blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, pt->pscsi_req, | 913 | blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, pt->pscsi_req, |
914 | (task->task_se_cmd->sam_task_attr == TASK_ATTR_HOQ), | 914 | (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG), |
915 | pscsi_req_done); | 915 | pscsi_req_done); |
916 | 916 | ||
917 | return PYX_TRANSPORT_SENT_TO_TRANSPORT; | 917 | return PYX_TRANSPORT_SENT_TO_TRANSPORT; |
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 4a109835e420..59b8b9c5ad72 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c | |||
@@ -55,7 +55,8 @@ struct se_tmr_req *core_tmr_alloc_req( | |||
55 | { | 55 | { |
56 | struct se_tmr_req *tmr; | 56 | struct se_tmr_req *tmr; |
57 | 57 | ||
58 | tmr = kmem_cache_zalloc(se_tmr_req_cache, GFP_KERNEL); | 58 | tmr = kmem_cache_zalloc(se_tmr_req_cache, (in_interrupt()) ? |
59 | GFP_ATOMIC : GFP_KERNEL); | ||
59 | if (!(tmr)) { | 60 | if (!(tmr)) { |
60 | printk(KERN_ERR "Unable to allocate struct se_tmr_req\n"); | 61 | printk(KERN_ERR "Unable to allocate struct se_tmr_req\n"); |
61 | return ERR_PTR(-ENOMEM); | 62 | return ERR_PTR(-ENOMEM); |
@@ -398,9 +399,9 @@ int core_tmr_lun_reset( | |||
398 | printk(KERN_INFO "LUN_RESET: SCSI-2 Released reservation\n"); | 399 | printk(KERN_INFO "LUN_RESET: SCSI-2 Released reservation\n"); |
399 | } | 400 | } |
400 | 401 | ||
401 | spin_lock(&dev->stats_lock); | 402 | spin_lock_irq(&dev->stats_lock); |
402 | dev->num_resets++; | 403 | dev->num_resets++; |
403 | spin_unlock(&dev->stats_lock); | 404 | spin_unlock_irq(&dev->stats_lock); |
404 | 405 | ||
405 | DEBUG_LR("LUN_RESET: %s for [%s] Complete\n", | 406 | DEBUG_LR("LUN_RESET: %s for [%s] Complete\n", |
406 | (preempt_and_abort_list) ? "Preempt" : "TMR", | 407 | (preempt_and_abort_list) ? "Preempt" : "TMR", |
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index b9d3501bdd91..4dafeb8b5638 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include <net/tcp.h> | 42 | #include <net/tcp.h> |
43 | #include <scsi/scsi.h> | 43 | #include <scsi/scsi.h> |
44 | #include <scsi/scsi_cmnd.h> | 44 | #include <scsi/scsi_cmnd.h> |
45 | #include <scsi/libsas.h> /* For TASK_ATTR_* */ | 45 | #include <scsi/scsi_tcq.h> |
46 | 46 | ||
47 | #include <target/target_core_base.h> | 47 | #include <target/target_core_base.h> |
48 | #include <target/target_core_device.h> | 48 | #include <target/target_core_device.h> |
@@ -762,7 +762,6 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) | |||
762 | transport_all_task_dev_remove_state(cmd); | 762 | transport_all_task_dev_remove_state(cmd); |
763 | spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags); | 763 | spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags); |
764 | 764 | ||
765 | transport_free_dev_tasks(cmd); | ||
766 | 765 | ||
767 | check_lun: | 766 | check_lun: |
768 | spin_lock_irqsave(&lun->lun_cmd_lock, flags); | 767 | spin_lock_irqsave(&lun->lun_cmd_lock, flags); |
@@ -1075,7 +1074,7 @@ static inline int transport_add_task_check_sam_attr( | |||
1075 | * head of the struct se_device->execute_task_list, and task_prev | 1074 | * head of the struct se_device->execute_task_list, and task_prev |
1076 | * after that for each subsequent task | 1075 | * after that for each subsequent task |
1077 | */ | 1076 | */ |
1078 | if (task->task_se_cmd->sam_task_attr == TASK_ATTR_HOQ) { | 1077 | if (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG) { |
1079 | list_add(&task->t_execute_list, | 1078 | list_add(&task->t_execute_list, |
1080 | (task_prev != NULL) ? | 1079 | (task_prev != NULL) ? |
1081 | &task_prev->t_execute_list : | 1080 | &task_prev->t_execute_list : |
@@ -1195,6 +1194,7 @@ transport_get_task_from_execute_queue(struct se_device *dev) | |||
1195 | break; | 1194 | break; |
1196 | 1195 | ||
1197 | list_del(&task->t_execute_list); | 1196 | list_del(&task->t_execute_list); |
1197 | atomic_set(&task->task_execute_queue, 0); | ||
1198 | atomic_dec(&dev->execute_tasks); | 1198 | atomic_dec(&dev->execute_tasks); |
1199 | 1199 | ||
1200 | return task; | 1200 | return task; |
@@ -1210,8 +1210,14 @@ void transport_remove_task_from_execute_queue( | |||
1210 | { | 1210 | { |
1211 | unsigned long flags; | 1211 | unsigned long flags; |
1212 | 1212 | ||
1213 | if (atomic_read(&task->task_execute_queue) == 0) { | ||
1214 | dump_stack(); | ||
1215 | return; | ||
1216 | } | ||
1217 | |||
1213 | spin_lock_irqsave(&dev->execute_task_lock, flags); | 1218 | spin_lock_irqsave(&dev->execute_task_lock, flags); |
1214 | list_del(&task->t_execute_list); | 1219 | list_del(&task->t_execute_list); |
1220 | atomic_set(&task->task_execute_queue, 0); | ||
1215 | atomic_dec(&dev->execute_tasks); | 1221 | atomic_dec(&dev->execute_tasks); |
1216 | spin_unlock_irqrestore(&dev->execute_task_lock, flags); | 1222 | spin_unlock_irqrestore(&dev->execute_task_lock, flags); |
1217 | } | 1223 | } |
@@ -1867,7 +1873,7 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd) | |||
1867 | if (SE_DEV(cmd)->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) | 1873 | if (SE_DEV(cmd)->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) |
1868 | return 0; | 1874 | return 0; |
1869 | 1875 | ||
1870 | if (cmd->sam_task_attr == TASK_ATTR_ACA) { | 1876 | if (cmd->sam_task_attr == MSG_ACA_TAG) { |
1871 | DEBUG_STA("SAM Task Attribute ACA" | 1877 | DEBUG_STA("SAM Task Attribute ACA" |
1872 | " emulation is not supported\n"); | 1878 | " emulation is not supported\n"); |
1873 | return -1; | 1879 | return -1; |
@@ -2058,6 +2064,13 @@ int transport_generic_handle_tmr( | |||
2058 | } | 2064 | } |
2059 | EXPORT_SYMBOL(transport_generic_handle_tmr); | 2065 | EXPORT_SYMBOL(transport_generic_handle_tmr); |
2060 | 2066 | ||
2067 | void transport_generic_free_cmd_intr( | ||
2068 | struct se_cmd *cmd) | ||
2069 | { | ||
2070 | transport_add_cmd_to_queue(cmd, TRANSPORT_FREE_CMD_INTR); | ||
2071 | } | ||
2072 | EXPORT_SYMBOL(transport_generic_free_cmd_intr); | ||
2073 | |||
2061 | static int transport_stop_tasks_for_cmd(struct se_cmd *cmd) | 2074 | static int transport_stop_tasks_for_cmd(struct se_cmd *cmd) |
2062 | { | 2075 | { |
2063 | struct se_task *task, *task_tmp; | 2076 | struct se_task *task, *task_tmp; |
@@ -2504,7 +2517,7 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd) | |||
2504 | * Check for the existence of HEAD_OF_QUEUE, and if true return 1 | 2517 | * Check for the existence of HEAD_OF_QUEUE, and if true return 1 |
2505 | * to allow the passed struct se_cmd list of tasks to the front of the list. | 2518 | * to allow the passed struct se_cmd list of tasks to the front of the list. |
2506 | */ | 2519 | */ |
2507 | if (cmd->sam_task_attr == TASK_ATTR_HOQ) { | 2520 | if (cmd->sam_task_attr == MSG_HEAD_TAG) { |
2508 | atomic_inc(&SE_DEV(cmd)->dev_hoq_count); | 2521 | atomic_inc(&SE_DEV(cmd)->dev_hoq_count); |
2509 | smp_mb__after_atomic_inc(); | 2522 | smp_mb__after_atomic_inc(); |
2510 | DEBUG_STA("Added HEAD_OF_QUEUE for CDB:" | 2523 | DEBUG_STA("Added HEAD_OF_QUEUE for CDB:" |
@@ -2512,7 +2525,7 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd) | |||
2512 | T_TASK(cmd)->t_task_cdb[0], | 2525 | T_TASK(cmd)->t_task_cdb[0], |
2513 | cmd->se_ordered_id); | 2526 | cmd->se_ordered_id); |
2514 | return 1; | 2527 | return 1; |
2515 | } else if (cmd->sam_task_attr == TASK_ATTR_ORDERED) { | 2528 | } else if (cmd->sam_task_attr == MSG_ORDERED_TAG) { |
2516 | spin_lock(&SE_DEV(cmd)->ordered_cmd_lock); | 2529 | spin_lock(&SE_DEV(cmd)->ordered_cmd_lock); |
2517 | list_add_tail(&cmd->se_ordered_list, | 2530 | list_add_tail(&cmd->se_ordered_list, |
2518 | &SE_DEV(cmd)->ordered_cmd_list); | 2531 | &SE_DEV(cmd)->ordered_cmd_list); |
@@ -3411,7 +3424,7 @@ static int transport_generic_cmd_sequencer( | |||
3411 | * See spc4r17 section 5.3 | 3424 | * See spc4r17 section 5.3 |
3412 | */ | 3425 | */ |
3413 | if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) | 3426 | if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) |
3414 | cmd->sam_task_attr = TASK_ATTR_HOQ; | 3427 | cmd->sam_task_attr = MSG_HEAD_TAG; |
3415 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB; | 3428 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB; |
3416 | break; | 3429 | break; |
3417 | case READ_BUFFER: | 3430 | case READ_BUFFER: |
@@ -3619,7 +3632,7 @@ static int transport_generic_cmd_sequencer( | |||
3619 | * See spc4r17 section 5.3 | 3632 | * See spc4r17 section 5.3 |
3620 | */ | 3633 | */ |
3621 | if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) | 3634 | if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) |
3622 | cmd->sam_task_attr = TASK_ATTR_HOQ; | 3635 | cmd->sam_task_attr = MSG_HEAD_TAG; |
3623 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB; | 3636 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB; |
3624 | break; | 3637 | break; |
3625 | default: | 3638 | default: |
@@ -3777,21 +3790,21 @@ static void transport_complete_task_attr(struct se_cmd *cmd) | |||
3777 | struct se_cmd *cmd_p, *cmd_tmp; | 3790 | struct se_cmd *cmd_p, *cmd_tmp; |
3778 | int new_active_tasks = 0; | 3791 | int new_active_tasks = 0; |
3779 | 3792 | ||
3780 | if (cmd->sam_task_attr == TASK_ATTR_SIMPLE) { | 3793 | if (cmd->sam_task_attr == MSG_SIMPLE_TAG) { |
3781 | atomic_dec(&dev->simple_cmds); | 3794 | atomic_dec(&dev->simple_cmds); |
3782 | smp_mb__after_atomic_dec(); | 3795 | smp_mb__after_atomic_dec(); |
3783 | dev->dev_cur_ordered_id++; | 3796 | dev->dev_cur_ordered_id++; |
3784 | DEBUG_STA("Incremented dev->dev_cur_ordered_id: %u for" | 3797 | DEBUG_STA("Incremented dev->dev_cur_ordered_id: %u for" |
3785 | " SIMPLE: %u\n", dev->dev_cur_ordered_id, | 3798 | " SIMPLE: %u\n", dev->dev_cur_ordered_id, |
3786 | cmd->se_ordered_id); | 3799 | cmd->se_ordered_id); |
3787 | } else if (cmd->sam_task_attr == TASK_ATTR_HOQ) { | 3800 | } else if (cmd->sam_task_attr == MSG_HEAD_TAG) { |
3788 | atomic_dec(&dev->dev_hoq_count); | 3801 | atomic_dec(&dev->dev_hoq_count); |
3789 | smp_mb__after_atomic_dec(); | 3802 | smp_mb__after_atomic_dec(); |
3790 | dev->dev_cur_ordered_id++; | 3803 | dev->dev_cur_ordered_id++; |
3791 | DEBUG_STA("Incremented dev_cur_ordered_id: %u for" | 3804 | DEBUG_STA("Incremented dev_cur_ordered_id: %u for" |
3792 | " HEAD_OF_QUEUE: %u\n", dev->dev_cur_ordered_id, | 3805 | " HEAD_OF_QUEUE: %u\n", dev->dev_cur_ordered_id, |
3793 | cmd->se_ordered_id); | 3806 | cmd->se_ordered_id); |
3794 | } else if (cmd->sam_task_attr == TASK_ATTR_ORDERED) { | 3807 | } else if (cmd->sam_task_attr == MSG_ORDERED_TAG) { |
3795 | spin_lock(&dev->ordered_cmd_lock); | 3808 | spin_lock(&dev->ordered_cmd_lock); |
3796 | list_del(&cmd->se_ordered_list); | 3809 | list_del(&cmd->se_ordered_list); |
3797 | atomic_dec(&dev->dev_ordered_sync); | 3810 | atomic_dec(&dev->dev_ordered_sync); |
@@ -3824,7 +3837,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd) | |||
3824 | new_active_tasks++; | 3837 | new_active_tasks++; |
3825 | 3838 | ||
3826 | spin_lock(&dev->delayed_cmd_lock); | 3839 | spin_lock(&dev->delayed_cmd_lock); |
3827 | if (cmd_p->sam_task_attr == TASK_ATTR_ORDERED) | 3840 | if (cmd_p->sam_task_attr == MSG_ORDERED_TAG) |
3828 | break; | 3841 | break; |
3829 | } | 3842 | } |
3830 | spin_unlock(&dev->delayed_cmd_lock); | 3843 | spin_unlock(&dev->delayed_cmd_lock); |
@@ -4776,18 +4789,20 @@ void transport_do_task_sg_chain(struct se_cmd *cmd) | |||
4776 | sg_end_cur->page_link &= ~0x02; | 4789 | sg_end_cur->page_link &= ~0x02; |
4777 | 4790 | ||
4778 | sg_chain(sg_head, task_sg_num, sg_head_cur); | 4791 | sg_chain(sg_head, task_sg_num, sg_head_cur); |
4779 | sg_count += (task->task_sg_num + 1); | ||
4780 | } else | ||
4781 | sg_count += task->task_sg_num; | 4792 | sg_count += task->task_sg_num; |
4793 | task_sg_num = (task->task_sg_num + 1); | ||
4794 | } else { | ||
4795 | sg_chain(sg_head, task_sg_num, sg_head_cur); | ||
4796 | sg_count += task->task_sg_num; | ||
4797 | task_sg_num = task->task_sg_num; | ||
4798 | } | ||
4782 | 4799 | ||
4783 | sg_head = sg_head_cur; | 4800 | sg_head = sg_head_cur; |
4784 | sg_link = sg_link_cur; | 4801 | sg_link = sg_link_cur; |
4785 | task_sg_num = task->task_sg_num; | ||
4786 | continue; | 4802 | continue; |
4787 | } | 4803 | } |
4788 | sg_head = sg_first = &task->task_sg[0]; | 4804 | sg_head = sg_first = &task->task_sg[0]; |
4789 | sg_link = &task->task_sg[task->task_sg_num]; | 4805 | sg_link = &task->task_sg[task->task_sg_num]; |
4790 | task_sg_num = task->task_sg_num; | ||
4791 | /* | 4806 | /* |
4792 | * Check for single task.. | 4807 | * Check for single task.. |
4793 | */ | 4808 | */ |
@@ -4798,9 +4813,12 @@ void transport_do_task_sg_chain(struct se_cmd *cmd) | |||
4798 | */ | 4813 | */ |
4799 | sg_end = &task->task_sg[task->task_sg_num - 1]; | 4814 | sg_end = &task->task_sg[task->task_sg_num - 1]; |
4800 | sg_end->page_link &= ~0x02; | 4815 | sg_end->page_link &= ~0x02; |
4801 | sg_count += (task->task_sg_num + 1); | ||
4802 | } else | ||
4803 | sg_count += task->task_sg_num; | 4816 | sg_count += task->task_sg_num; |
4817 | task_sg_num = (task->task_sg_num + 1); | ||
4818 | } else { | ||
4819 | sg_count += task->task_sg_num; | ||
4820 | task_sg_num = task->task_sg_num; | ||
4821 | } | ||
4804 | } | 4822 | } |
4805 | /* | 4823 | /* |
4806 | * Setup the starting pointer and total t_tasks_sg_linked_no including | 4824 | * Setup the starting pointer and total t_tasks_sg_linked_no including |
@@ -4809,21 +4827,20 @@ void transport_do_task_sg_chain(struct se_cmd *cmd) | |||
4809 | T_TASK(cmd)->t_tasks_sg_chained = sg_first; | 4827 | T_TASK(cmd)->t_tasks_sg_chained = sg_first; |
4810 | T_TASK(cmd)->t_tasks_sg_chained_no = sg_count; | 4828 | T_TASK(cmd)->t_tasks_sg_chained_no = sg_count; |
4811 | 4829 | ||
4812 | DEBUG_CMD_M("Setup T_TASK(cmd)->t_tasks_sg_chained: %p and" | 4830 | DEBUG_CMD_M("Setup cmd: %p T_TASK(cmd)->t_tasks_sg_chained: %p and" |
4813 | " t_tasks_sg_chained_no: %u\n", T_TASK(cmd)->t_tasks_sg_chained, | 4831 | " t_tasks_sg_chained_no: %u\n", cmd, T_TASK(cmd)->t_tasks_sg_chained, |
4814 | T_TASK(cmd)->t_tasks_sg_chained_no); | 4832 | T_TASK(cmd)->t_tasks_sg_chained_no); |
4815 | 4833 | ||
4816 | for_each_sg(T_TASK(cmd)->t_tasks_sg_chained, sg, | 4834 | for_each_sg(T_TASK(cmd)->t_tasks_sg_chained, sg, |
4817 | T_TASK(cmd)->t_tasks_sg_chained_no, i) { | 4835 | T_TASK(cmd)->t_tasks_sg_chained_no, i) { |
4818 | 4836 | ||
4819 | DEBUG_CMD_M("SG: %p page: %p length: %d offset: %d\n", | 4837 | DEBUG_CMD_M("SG[%d]: %p page: %p length: %d offset: %d, magic: 0x%08x\n", |
4820 | sg, sg_page(sg), sg->length, sg->offset); | 4838 | i, sg, sg_page(sg), sg->length, sg->offset, sg->sg_magic); |
4821 | if (sg_is_chain(sg)) | 4839 | if (sg_is_chain(sg)) |
4822 | DEBUG_CMD_M("SG: %p sg_is_chain=1\n", sg); | 4840 | DEBUG_CMD_M("SG: %p sg_is_chain=1\n", sg); |
4823 | if (sg_is_last(sg)) | 4841 | if (sg_is_last(sg)) |
4824 | DEBUG_CMD_M("SG: %p sg_is_last=1\n", sg); | 4842 | DEBUG_CMD_M("SG: %p sg_is_last=1\n", sg); |
4825 | } | 4843 | } |
4826 | |||
4827 | } | 4844 | } |
4828 | EXPORT_SYMBOL(transport_do_task_sg_chain); | 4845 | EXPORT_SYMBOL(transport_do_task_sg_chain); |
4829 | 4846 | ||
@@ -5297,6 +5314,8 @@ void transport_generic_free_cmd( | |||
5297 | if (wait_for_tasks && cmd->transport_wait_for_tasks) | 5314 | if (wait_for_tasks && cmd->transport_wait_for_tasks) |
5298 | cmd->transport_wait_for_tasks(cmd, 0, 0); | 5315 | cmd->transport_wait_for_tasks(cmd, 0, 0); |
5299 | 5316 | ||
5317 | transport_free_dev_tasks(cmd); | ||
5318 | |||
5300 | transport_generic_remove(cmd, release_to_pool, | 5319 | transport_generic_remove(cmd, release_to_pool, |
5301 | session_reinstatement); | 5320 | session_reinstatement); |
5302 | } | 5321 | } |
@@ -6132,6 +6151,9 @@ get_cmd: | |||
6132 | case TRANSPORT_REMOVE: | 6151 | case TRANSPORT_REMOVE: |
6133 | transport_generic_remove(cmd, 1, 0); | 6152 | transport_generic_remove(cmd, 1, 0); |
6134 | break; | 6153 | break; |
6154 | case TRANSPORT_FREE_CMD_INTR: | ||
6155 | transport_generic_free_cmd(cmd, 0, 1, 0); | ||
6156 | break; | ||
6135 | case TRANSPORT_PROCESS_TMR: | 6157 | case TRANSPORT_PROCESS_TMR: |
6136 | transport_generic_do_tmr(cmd); | 6158 | transport_generic_do_tmr(cmd); |
6137 | break; | 6159 | break; |
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 49e51778f733..c056a1132ae1 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <scsi/scsi_host.h> | 35 | #include <scsi/scsi_host.h> |
36 | #include <scsi/scsi_device.h> | 36 | #include <scsi/scsi_device.h> |
37 | #include <scsi/scsi_cmnd.h> | 37 | #include <scsi/scsi_cmnd.h> |
38 | #include <scsi/scsi_tcq.h> | ||
38 | #include <scsi/libfc.h> | 39 | #include <scsi/libfc.h> |
39 | #include <scsi/fc_encode.h> | 40 | #include <scsi/fc_encode.h> |
40 | 41 | ||
@@ -592,8 +593,25 @@ static void ft_send_cmd(struct ft_cmd *cmd) | |||
592 | case FCP_CFL_WRDATA | FCP_CFL_RDDATA: | 593 | case FCP_CFL_WRDATA | FCP_CFL_RDDATA: |
593 | goto err; /* TBD not supported by tcm_fc yet */ | 594 | goto err; /* TBD not supported by tcm_fc yet */ |
594 | } | 595 | } |
596 | /* | ||
597 | * Locate the SAM Task Attr from fc_pri_ta | ||
598 | */ | ||
599 | switch (fcp->fc_pri_ta & FCP_PTA_MASK) { | ||
600 | case FCP_PTA_HEADQ: | ||
601 | task_attr = MSG_HEAD_TAG; | ||
602 | break; | ||
603 | case FCP_PTA_ORDERED: | ||
604 | task_attr = MSG_ORDERED_TAG; | ||
605 | break; | ||
606 | case FCP_PTA_ACA: | ||
607 | task_attr = MSG_ACA_TAG; | ||
608 | break; | ||
609 | case FCP_PTA_SIMPLE: /* Fallthrough */ | ||
610 | default: | ||
611 | task_attr = MSG_SIMPLE_TAG; | ||
612 | } | ||
613 | |||
595 | 614 | ||
596 | /* FCP_PTA_ maps 1:1 to TASK_ATTR_ */ | ||
597 | task_attr = fcp->fc_pri_ta & FCP_PTA_MASK; | 615 | task_attr = fcp->fc_pri_ta & FCP_PTA_MASK; |
598 | data_len = ntohl(fcp->fc_dl); | 616 | data_len = ntohl(fcp->fc_dl); |
599 | cmd->cdb = fcp->fc_cdb; | 617 | cmd->cdb = fcp->fc_cdb; |
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c index fcdbbffe88cc..84e868c255dd 100644 --- a/drivers/target/tcm_fc/tfc_conf.c +++ b/drivers/target/tcm_fc/tfc_conf.c | |||
@@ -519,13 +519,6 @@ static u32 ft_tpg_get_inst_index(struct se_portal_group *se_tpg) | |||
519 | return tpg->index; | 519 | return tpg->index; |
520 | } | 520 | } |
521 | 521 | ||
522 | static u64 ft_pack_lun(unsigned int index) | ||
523 | { | ||
524 | WARN_ON(index >= 256); | ||
525 | /* Caller wants this byte-swapped */ | ||
526 | return cpu_to_le64((index & 0xff) << 8); | ||
527 | } | ||
528 | |||
529 | static struct target_core_fabric_ops ft_fabric_ops = { | 522 | static struct target_core_fabric_ops ft_fabric_ops = { |
530 | .get_fabric_name = ft_get_fabric_name, | 523 | .get_fabric_name = ft_get_fabric_name, |
531 | .get_fabric_proto_ident = fc_get_fabric_proto_ident, | 524 | .get_fabric_proto_ident = fc_get_fabric_proto_ident, |
@@ -564,7 +557,6 @@ static struct target_core_fabric_ops ft_fabric_ops = { | |||
564 | .get_fabric_sense_len = ft_get_fabric_sense_len, | 557 | .get_fabric_sense_len = ft_get_fabric_sense_len, |
565 | .set_fabric_sense_len = ft_set_fabric_sense_len, | 558 | .set_fabric_sense_len = ft_set_fabric_sense_len, |
566 | .is_state_remove = ft_is_state_remove, | 559 | .is_state_remove = ft_is_state_remove, |
567 | .pack_lun = ft_pack_lun, | ||
568 | /* | 560 | /* |
569 | * Setup function pointers for generic logic in | 561 | * Setup function pointers for generic logic in |
570 | * target_core_fabric_configfs.c | 562 | * target_core_fabric_configfs.c |
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index bfa05e801823..c0e8f2eeb886 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c | |||
@@ -4096,8 +4096,7 @@ static int __init cy_init(void) | |||
4096 | if (!cy_serial_driver) | 4096 | if (!cy_serial_driver) |
4097 | goto err; | 4097 | goto err; |
4098 | 4098 | ||
4099 | printk(KERN_INFO "Cyclades driver " CY_VERSION " (built %s %s)\n", | 4099 | printk(KERN_INFO "Cyclades driver " CY_VERSION "\n"); |
4100 | __DATE__, __TIME__); | ||
4101 | 4100 | ||
4102 | /* Initialize the tty_driver structure */ | 4101 | /* Initialize the tty_driver structure */ |
4103 | 4102 | ||
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index b1aecc7bb32a..fd347ff34d07 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c | |||
@@ -61,8 +61,7 @@ | |||
61 | #include <linux/delay.h> | 61 | #include <linux/delay.h> |
62 | 62 | ||
63 | 63 | ||
64 | #define VERSION_STRING DRIVER_DESC " 2.1d (build date: " \ | 64 | #define VERSION_STRING DRIVER_DESC " 2.1d" |
65 | __DATE__ " " __TIME__ ")" | ||
66 | 65 | ||
67 | /* Macros definitions */ | 66 | /* Macros definitions */ |
68 | 67 | ||
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 652bdac8ce8e..6d5d6e679fc7 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c | |||
@@ -1420,7 +1420,7 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
1420 | port->flags = UPF_BOOT_AUTOCONF; | 1420 | port->flags = UPF_BOOT_AUTOCONF; |
1421 | port->ops = &atmel_pops; | 1421 | port->ops = &atmel_pops; |
1422 | port->fifosize = 1; | 1422 | port->fifosize = 1; |
1423 | port->line = pdev->id; | 1423 | port->line = data->num; |
1424 | port->dev = &pdev->dev; | 1424 | port->dev = &pdev->dev; |
1425 | port->mapbase = pdev->resource[0].start; | 1425 | port->mapbase = pdev->resource[0].start; |
1426 | port->irq = pdev->resource[1].start; | 1426 | port->irq = pdev->resource[1].start; |
diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index bea5c215460c..84db7321cce8 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c | |||
@@ -907,9 +907,10 @@ static int m32r_sio_request_port(struct uart_port *port) | |||
907 | return ret; | 907 | return ret; |
908 | } | 908 | } |
909 | 909 | ||
910 | static void m32r_sio_config_port(struct uart_port *port, int flags) | 910 | static void m32r_sio_config_port(struct uart_port *port, int unused) |
911 | { | 911 | { |
912 | struct uart_sio_port *up = (struct uart_sio_port *)port; | 912 | struct uart_sio_port *up = (struct uart_sio_port *)port; |
913 | unsigned long flags; | ||
913 | 914 | ||
914 | spin_lock_irqsave(&up->port.lock, flags); | 915 | spin_lock_irqsave(&up->port.lock, flags); |
915 | 916 | ||
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index 3f2e07011a48..cfb5aa72b196 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c | |||
@@ -100,6 +100,7 @@ struct twl6030_usb { | |||
100 | u8 linkstat; | 100 | u8 linkstat; |
101 | u8 asleep; | 101 | u8 asleep; |
102 | bool irq_enabled; | 102 | bool irq_enabled; |
103 | unsigned long features; | ||
103 | }; | 104 | }; |
104 | 105 | ||
105 | #define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg) | 106 | #define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg) |
@@ -204,6 +205,12 @@ static int twl6030_start_srp(struct otg_transceiver *x) | |||
204 | 205 | ||
205 | static int twl6030_usb_ldo_init(struct twl6030_usb *twl) | 206 | static int twl6030_usb_ldo_init(struct twl6030_usb *twl) |
206 | { | 207 | { |
208 | char *regulator_name; | ||
209 | |||
210 | if (twl->features & TWL6025_SUBCLASS) | ||
211 | regulator_name = "ldousb"; | ||
212 | else | ||
213 | regulator_name = "vusb"; | ||
207 | 214 | ||
208 | /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */ | 215 | /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */ |
209 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG); | 216 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG); |
@@ -214,7 +221,7 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl) | |||
214 | /* Program MISC2 register and set bit VUSB_IN_VBAT */ | 221 | /* Program MISC2 register and set bit VUSB_IN_VBAT */ |
215 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2); | 222 | twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2); |
216 | 223 | ||
217 | twl->usb3v3 = regulator_get(twl->dev, "vusb"); | 224 | twl->usb3v3 = regulator_get(twl->dev, regulator_name); |
218 | if (IS_ERR(twl->usb3v3)) | 225 | if (IS_ERR(twl->usb3v3)) |
219 | return -ENODEV; | 226 | return -ENODEV; |
220 | 227 | ||
@@ -409,6 +416,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
409 | twl->dev = &pdev->dev; | 416 | twl->dev = &pdev->dev; |
410 | twl->irq1 = platform_get_irq(pdev, 0); | 417 | twl->irq1 = platform_get_irq(pdev, 0); |
411 | twl->irq2 = platform_get_irq(pdev, 1); | 418 | twl->irq2 = platform_get_irq(pdev, 1); |
419 | twl->features = pdata->features; | ||
412 | twl->otg.dev = twl->dev; | 420 | twl->otg.dev = twl->dev; |
413 | twl->otg.label = "twl6030"; | 421 | twl->otg.label = "twl6030"; |
414 | twl->otg.set_host = twl6030_set_host; | 422 | twl->otg.set_host = twl6030_set_host; |
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c index ea39336addfb..f70bd63b0187 100644 --- a/drivers/video/mb862xx/mb862xxfbdrv.c +++ b/drivers/video/mb862xx/mb862xxfbdrv.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/fb.h> | 17 | #include <linux/fb.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/uaccess.h> | ||
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
21 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 7c608c5ccf84..00d615d7aa21 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig | |||
@@ -42,7 +42,7 @@ config W1_MASTER_MXC | |||
42 | 42 | ||
43 | config W1_MASTER_DS1WM | 43 | config W1_MASTER_DS1WM |
44 | tristate "Maxim DS1WM 1-wire busmaster" | 44 | tristate "Maxim DS1WM 1-wire busmaster" |
45 | depends on W1 && ARM && HAVE_CLK | 45 | depends on W1 |
46 | help | 46 | help |
47 | Say Y here to enable the DS1WM 1-wire driver, such as that | 47 | Say Y here to enable the DS1WM 1-wire driver, such as that |
48 | in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like | 48 | in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like |
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c index 0855d6cce3c1..ad57593d224a 100644 --- a/drivers/w1/masters/ds1wm.c +++ b/drivers/w1/masters/ds1wm.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #define DS1WM_INT 0x02 /* R/W interrupt status */ | 33 | #define DS1WM_INT 0x02 /* R/W interrupt status */ |
34 | #define DS1WM_INT_EN 0x03 /* R/W interrupt enable */ | 34 | #define DS1WM_INT_EN 0x03 /* R/W interrupt enable */ |
35 | #define DS1WM_CLKDIV 0x04 /* R/W 5 bits of divisor and pre-scale */ | 35 | #define DS1WM_CLKDIV 0x04 /* R/W 5 bits of divisor and pre-scale */ |
36 | #define DS1WM_CNTRL 0x05 /* R/W master control register (not used yet) */ | ||
36 | 37 | ||
37 | #define DS1WM_CMD_1W_RESET (1 << 0) /* force reset on 1-wire bus */ | 38 | #define DS1WM_CMD_1W_RESET (1 << 0) /* force reset on 1-wire bus */ |
38 | #define DS1WM_CMD_SRA (1 << 1) /* enable Search ROM accelerator mode */ | 39 | #define DS1WM_CMD_SRA (1 << 1) /* enable Search ROM accelerator mode */ |
@@ -56,6 +57,7 @@ | |||
56 | #define DS1WM_INTEN_ERSRF (1 << 5) /* enable rx shift register full int */ | 57 | #define DS1WM_INTEN_ERSRF (1 << 5) /* enable rx shift register full int */ |
57 | #define DS1WM_INTEN_DQO (1 << 6) /* enable direct bus driving ops */ | 58 | #define DS1WM_INTEN_DQO (1 << 6) /* enable direct bus driving ops */ |
58 | 59 | ||
60 | #define DS1WM_INTEN_NOT_IAS (~DS1WM_INTEN_IAS) /* all but INTR active state */ | ||
59 | 61 | ||
60 | #define DS1WM_TIMEOUT (HZ * 5) | 62 | #define DS1WM_TIMEOUT (HZ * 5) |
61 | 63 | ||
@@ -63,41 +65,50 @@ static struct { | |||
63 | unsigned long freq; | 65 | unsigned long freq; |
64 | unsigned long divisor; | 66 | unsigned long divisor; |
65 | } freq[] = { | 67 | } freq[] = { |
66 | { 4000000, 0x8 }, | 68 | { 1000000, 0x80 }, |
67 | { 5000000, 0x2 }, | 69 | { 2000000, 0x84 }, |
68 | { 6000000, 0x5 }, | 70 | { 3000000, 0x81 }, |
69 | { 7000000, 0x3 }, | 71 | { 4000000, 0x88 }, |
70 | { 8000000, 0xc }, | 72 | { 5000000, 0x82 }, |
71 | { 10000000, 0x6 }, | 73 | { 6000000, 0x85 }, |
72 | { 12000000, 0x9 }, | 74 | { 7000000, 0x83 }, |
73 | { 14000000, 0x7 }, | 75 | { 8000000, 0x8c }, |
74 | { 16000000, 0x10 }, | 76 | { 10000000, 0x86 }, |
75 | { 20000000, 0xa }, | 77 | { 12000000, 0x89 }, |
76 | { 24000000, 0xd }, | 78 | { 14000000, 0x87 }, |
77 | { 28000000, 0xb }, | 79 | { 16000000, 0x90 }, |
78 | { 32000000, 0x14 }, | 80 | { 20000000, 0x8a }, |
79 | { 40000000, 0xe }, | 81 | { 24000000, 0x8d }, |
80 | { 48000000, 0x11 }, | 82 | { 28000000, 0x8b }, |
81 | { 56000000, 0xf }, | 83 | { 32000000, 0x94 }, |
82 | { 64000000, 0x18 }, | 84 | { 40000000, 0x8e }, |
83 | { 80000000, 0x12 }, | 85 | { 48000000, 0x91 }, |
84 | { 96000000, 0x15 }, | 86 | { 56000000, 0x8f }, |
85 | { 112000000, 0x13 }, | 87 | { 64000000, 0x98 }, |
86 | { 128000000, 0x1c }, | 88 | { 80000000, 0x92 }, |
89 | { 96000000, 0x95 }, | ||
90 | { 112000000, 0x93 }, | ||
91 | { 128000000, 0x9c }, | ||
92 | /* you can continue this table, consult the OPERATION - CLOCK DIVISOR | ||
93 | section of the ds1wm spec sheet. */ | ||
87 | }; | 94 | }; |
88 | 95 | ||
89 | struct ds1wm_data { | 96 | struct ds1wm_data { |
90 | void __iomem *map; | 97 | void __iomem *map; |
91 | int bus_shift; /* # of shifts to calc register offsets */ | 98 | int bus_shift; /* # of shifts to calc register offsets */ |
92 | struct platform_device *pdev; | 99 | struct platform_device *pdev; |
93 | const struct mfd_cell *cell; | 100 | const struct mfd_cell *cell; |
94 | int irq; | 101 | int irq; |
95 | int active_high; | 102 | int slave_present; |
96 | int slave_present; | 103 | void *reset_complete; |
97 | void *reset_complete; | 104 | void *read_complete; |
98 | void *read_complete; | 105 | void *write_complete; |
99 | void *write_complete; | 106 | int read_error; |
100 | u8 read_byte; /* last byte received */ | 107 | /* last byte received */ |
108 | u8 read_byte; | ||
109 | /* byte to write that makes all intr disabled, */ | ||
110 | /* considering active_state (IAS) (optimization) */ | ||
111 | u8 int_en_reg_none; | ||
101 | }; | 112 | }; |
102 | 113 | ||
103 | static inline void ds1wm_write_register(struct ds1wm_data *ds1wm_data, u32 reg, | 114 | static inline void ds1wm_write_register(struct ds1wm_data *ds1wm_data, u32 reg, |
@@ -115,23 +126,39 @@ static inline u8 ds1wm_read_register(struct ds1wm_data *ds1wm_data, u32 reg) | |||
115 | static irqreturn_t ds1wm_isr(int isr, void *data) | 126 | static irqreturn_t ds1wm_isr(int isr, void *data) |
116 | { | 127 | { |
117 | struct ds1wm_data *ds1wm_data = data; | 128 | struct ds1wm_data *ds1wm_data = data; |
118 | u8 intr = ds1wm_read_register(ds1wm_data, DS1WM_INT); | 129 | u8 intr; |
130 | u8 inten = ds1wm_read_register(ds1wm_data, DS1WM_INT_EN); | ||
131 | /* if no bits are set in int enable register (except the IAS) | ||
132 | than go no further, reading the regs below has side effects */ | ||
133 | if (!(inten & DS1WM_INTEN_NOT_IAS)) | ||
134 | return IRQ_NONE; | ||
119 | 135 | ||
120 | ds1wm_data->slave_present = (intr & DS1WM_INT_PDR) ? 0 : 1; | 136 | ds1wm_write_register(ds1wm_data, |
137 | DS1WM_INT_EN, ds1wm_data->int_en_reg_none); | ||
121 | 138 | ||
122 | if ((intr & DS1WM_INT_PD) && ds1wm_data->reset_complete) | 139 | /* this read action clears the INTR and certain flags in ds1wm */ |
123 | complete(ds1wm_data->reset_complete); | 140 | intr = ds1wm_read_register(ds1wm_data, DS1WM_INT); |
124 | 141 | ||
125 | if ((intr & DS1WM_INT_TSRE) && ds1wm_data->write_complete) | 142 | ds1wm_data->slave_present = (intr & DS1WM_INT_PDR) ? 0 : 1; |
126 | complete(ds1wm_data->write_complete); | ||
127 | 143 | ||
144 | if ((intr & DS1WM_INT_TSRE) && ds1wm_data->write_complete) { | ||
145 | inten &= ~DS1WM_INTEN_ETMT; | ||
146 | complete(ds1wm_data->write_complete); | ||
147 | } | ||
128 | if (intr & DS1WM_INT_RBF) { | 148 | if (intr & DS1WM_INT_RBF) { |
149 | /* this read clears the RBF flag */ | ||
129 | ds1wm_data->read_byte = ds1wm_read_register(ds1wm_data, | 150 | ds1wm_data->read_byte = ds1wm_read_register(ds1wm_data, |
130 | DS1WM_DATA); | 151 | DS1WM_DATA); |
152 | inten &= ~DS1WM_INTEN_ERBF; | ||
131 | if (ds1wm_data->read_complete) | 153 | if (ds1wm_data->read_complete) |
132 | complete(ds1wm_data->read_complete); | 154 | complete(ds1wm_data->read_complete); |
133 | } | 155 | } |
156 | if ((intr & DS1WM_INT_PD) && ds1wm_data->reset_complete) { | ||
157 | inten &= ~DS1WM_INTEN_EPD; | ||
158 | complete(ds1wm_data->reset_complete); | ||
159 | } | ||
134 | 160 | ||
161 | ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, inten); | ||
135 | return IRQ_HANDLED; | 162 | return IRQ_HANDLED; |
136 | } | 163 | } |
137 | 164 | ||
@@ -142,33 +169,19 @@ static int ds1wm_reset(struct ds1wm_data *ds1wm_data) | |||
142 | 169 | ||
143 | ds1wm_data->reset_complete = &reset_done; | 170 | ds1wm_data->reset_complete = &reset_done; |
144 | 171 | ||
172 | /* enable Presence detect only */ | ||
145 | ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, DS1WM_INTEN_EPD | | 173 | ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, DS1WM_INTEN_EPD | |
146 | (ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0)); | 174 | ds1wm_data->int_en_reg_none); |
147 | 175 | ||
148 | ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_1W_RESET); | 176 | ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_1W_RESET); |
149 | 177 | ||
150 | timeleft = wait_for_completion_timeout(&reset_done, DS1WM_TIMEOUT); | 178 | timeleft = wait_for_completion_timeout(&reset_done, DS1WM_TIMEOUT); |
151 | ds1wm_data->reset_complete = NULL; | 179 | ds1wm_data->reset_complete = NULL; |
152 | if (!timeleft) { | 180 | if (!timeleft) { |
153 | dev_err(&ds1wm_data->pdev->dev, "reset failed\n"); | 181 | dev_err(&ds1wm_data->pdev->dev, "reset failed, timed out\n"); |
154 | return 1; | 182 | return 1; |
155 | } | 183 | } |
156 | 184 | ||
157 | /* Wait for the end of the reset. According to the specs, the time | ||
158 | * from when the interrupt is asserted to the end of the reset is: | ||
159 | * tRSTH - tPDH - tPDL - tPDI | ||
160 | * 625 us - 60 us - 240 us - 100 ns = 324.9 us | ||
161 | * | ||
162 | * We'll wait a bit longer just to be sure. | ||
163 | * Was udelay(500), but if it is going to busywait the cpu that long, | ||
164 | * might as well come back later. | ||
165 | */ | ||
166 | msleep(1); | ||
167 | |||
168 | ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, | ||
169 | DS1WM_INTEN_ERBF | DS1WM_INTEN_ETMT | DS1WM_INTEN_EPD | | ||
170 | (ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0)); | ||
171 | |||
172 | if (!ds1wm_data->slave_present) { | 185 | if (!ds1wm_data->slave_present) { |
173 | dev_dbg(&ds1wm_data->pdev->dev, "reset: no devices found\n"); | 186 | dev_dbg(&ds1wm_data->pdev->dev, "reset: no devices found\n"); |
174 | return 1; | 187 | return 1; |
@@ -179,26 +192,47 @@ static int ds1wm_reset(struct ds1wm_data *ds1wm_data) | |||
179 | 192 | ||
180 | static int ds1wm_write(struct ds1wm_data *ds1wm_data, u8 data) | 193 | static int ds1wm_write(struct ds1wm_data *ds1wm_data, u8 data) |
181 | { | 194 | { |
195 | unsigned long timeleft; | ||
182 | DECLARE_COMPLETION_ONSTACK(write_done); | 196 | DECLARE_COMPLETION_ONSTACK(write_done); |
183 | ds1wm_data->write_complete = &write_done; | 197 | ds1wm_data->write_complete = &write_done; |
184 | 198 | ||
199 | ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, | ||
200 | ds1wm_data->int_en_reg_none | DS1WM_INTEN_ETMT); | ||
201 | |||
185 | ds1wm_write_register(ds1wm_data, DS1WM_DATA, data); | 202 | ds1wm_write_register(ds1wm_data, DS1WM_DATA, data); |
186 | 203 | ||
187 | wait_for_completion_timeout(&write_done, DS1WM_TIMEOUT); | 204 | timeleft = wait_for_completion_timeout(&write_done, DS1WM_TIMEOUT); |
205 | |||
188 | ds1wm_data->write_complete = NULL; | 206 | ds1wm_data->write_complete = NULL; |
207 | if (!timeleft) { | ||
208 | dev_err(&ds1wm_data->pdev->dev, "write failed, timed out\n"); | ||
209 | return -ETIMEDOUT; | ||
210 | } | ||
189 | 211 | ||
190 | return 0; | 212 | return 0; |
191 | } | 213 | } |
192 | 214 | ||
193 | static int ds1wm_read(struct ds1wm_data *ds1wm_data, unsigned char write_data) | 215 | static u8 ds1wm_read(struct ds1wm_data *ds1wm_data, unsigned char write_data) |
194 | { | 216 | { |
217 | unsigned long timeleft; | ||
218 | u8 intEnable = DS1WM_INTEN_ERBF | ds1wm_data->int_en_reg_none; | ||
195 | DECLARE_COMPLETION_ONSTACK(read_done); | 219 | DECLARE_COMPLETION_ONSTACK(read_done); |
220 | |||
221 | ds1wm_read_register(ds1wm_data, DS1WM_DATA); | ||
222 | |||
196 | ds1wm_data->read_complete = &read_done; | 223 | ds1wm_data->read_complete = &read_done; |
224 | ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, intEnable); | ||
197 | 225 | ||
198 | ds1wm_write(ds1wm_data, write_data); | 226 | ds1wm_write_register(ds1wm_data, DS1WM_DATA, write_data); |
199 | wait_for_completion_timeout(&read_done, DS1WM_TIMEOUT); | 227 | timeleft = wait_for_completion_timeout(&read_done, DS1WM_TIMEOUT); |
200 | ds1wm_data->read_complete = NULL; | ||
201 | 228 | ||
229 | ds1wm_data->read_complete = NULL; | ||
230 | if (!timeleft) { | ||
231 | dev_err(&ds1wm_data->pdev->dev, "read failed, timed out\n"); | ||
232 | ds1wm_data->read_error = -ETIMEDOUT; | ||
233 | return 0xFF; | ||
234 | } | ||
235 | ds1wm_data->read_error = 0; | ||
202 | return ds1wm_data->read_byte; | 236 | return ds1wm_data->read_byte; |
203 | } | 237 | } |
204 | 238 | ||
@@ -206,8 +240,8 @@ static int ds1wm_find_divisor(int gclk) | |||
206 | { | 240 | { |
207 | int i; | 241 | int i; |
208 | 242 | ||
209 | for (i = 0; i < ARRAY_SIZE(freq); i++) | 243 | for (i = ARRAY_SIZE(freq)-1; i >= 0; --i) |
210 | if (gclk <= freq[i].freq) | 244 | if (gclk >= freq[i].freq) |
211 | return freq[i].divisor; | 245 | return freq[i].divisor; |
212 | 246 | ||
213 | return 0; | 247 | return 0; |
@@ -222,6 +256,8 @@ static void ds1wm_up(struct ds1wm_data *ds1wm_data) | |||
222 | ds1wm_data->cell->enable(ds1wm_data->pdev); | 256 | ds1wm_data->cell->enable(ds1wm_data->pdev); |
223 | 257 | ||
224 | divisor = ds1wm_find_divisor(plat->clock_rate); | 258 | divisor = ds1wm_find_divisor(plat->clock_rate); |
259 | dev_dbg(&ds1wm_data->pdev->dev, | ||
260 | "found divisor 0x%x for clock %d\n", divisor, plat->clock_rate); | ||
225 | if (divisor == 0) { | 261 | if (divisor == 0) { |
226 | dev_err(&ds1wm_data->pdev->dev, | 262 | dev_err(&ds1wm_data->pdev->dev, |
227 | "no suitable divisor for %dHz clock\n", | 263 | "no suitable divisor for %dHz clock\n", |
@@ -242,7 +278,7 @@ static void ds1wm_down(struct ds1wm_data *ds1wm_data) | |||
242 | 278 | ||
243 | /* Disable interrupts. */ | 279 | /* Disable interrupts. */ |
244 | ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, | 280 | ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, |
245 | ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0); | 281 | ds1wm_data->int_en_reg_none); |
246 | 282 | ||
247 | if (ds1wm_data->cell->disable) | 283 | if (ds1wm_data->cell->disable) |
248 | ds1wm_data->cell->disable(ds1wm_data->pdev); | 284 | ds1wm_data->cell->disable(ds1wm_data->pdev); |
@@ -279,41 +315,121 @@ static void ds1wm_search(void *data, struct w1_master *master_dev, | |||
279 | { | 315 | { |
280 | struct ds1wm_data *ds1wm_data = data; | 316 | struct ds1wm_data *ds1wm_data = data; |
281 | int i; | 317 | int i; |
282 | unsigned long long rom_id; | 318 | int ms_discrep_bit = -1; |
283 | 319 | u64 r = 0; /* holds the progress of the search */ | |
284 | /* XXX We need to iterate for multiple devices per the DS1WM docs. | 320 | u64 r_prime, d; |
285 | * See http://www.maxim-ic.com/appnotes.cfm/appnote_number/120. */ | 321 | unsigned slaves_found = 0; |
286 | if (ds1wm_reset(ds1wm_data)) | 322 | unsigned int pass = 0; |
287 | return; | 323 | |
288 | 324 | dev_dbg(&ds1wm_data->pdev->dev, "search begin\n"); | |
289 | ds1wm_write(ds1wm_data, search_type); | 325 | while (true) { |
290 | ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_SRA); | 326 | ++pass; |
291 | 327 | if (pass > 100) { | |
292 | for (rom_id = 0, i = 0; i < 16; i++) { | 328 | dev_dbg(&ds1wm_data->pdev->dev, |
293 | 329 | "too many attempts (100), search aborted\n"); | |
294 | unsigned char resp, r, d; | 330 | return; |
295 | 331 | } | |
296 | resp = ds1wm_read(ds1wm_data, 0x00); | 332 | |
297 | 333 | if (ds1wm_reset(ds1wm_data)) { | |
298 | r = ((resp & 0x02) >> 1) | | 334 | dev_dbg(&ds1wm_data->pdev->dev, |
299 | ((resp & 0x08) >> 2) | | 335 | "pass: %d reset error (or no slaves)\n", pass); |
300 | ((resp & 0x20) >> 3) | | 336 | break; |
301 | ((resp & 0x80) >> 4); | 337 | } |
302 | 338 | ||
303 | d = ((resp & 0x01) >> 0) | | 339 | dev_dbg(&ds1wm_data->pdev->dev, |
304 | ((resp & 0x04) >> 1) | | 340 | "pass: %d r : %0#18llx writing SEARCH_ROM\n", pass, r); |
305 | ((resp & 0x10) >> 2) | | 341 | ds1wm_write(ds1wm_data, search_type); |
306 | ((resp & 0x40) >> 3); | 342 | dev_dbg(&ds1wm_data->pdev->dev, |
307 | 343 | "pass: %d entering ASM\n", pass); | |
308 | rom_id |= (unsigned long long) r << (i * 4); | 344 | ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_SRA); |
309 | 345 | dev_dbg(&ds1wm_data->pdev->dev, | |
310 | } | 346 | "pass: %d begining nibble loop\n", pass); |
311 | dev_dbg(&ds1wm_data->pdev->dev, "found 0x%08llX\n", rom_id); | 347 | |
312 | 348 | r_prime = 0; | |
313 | ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA); | 349 | d = 0; |
314 | ds1wm_reset(ds1wm_data); | 350 | /* we work one nibble at a time */ |
315 | 351 | /* each nibble is interleaved to form a byte */ | |
316 | slave_found(master_dev, rom_id); | 352 | for (i = 0; i < 16; i++) { |
353 | |||
354 | unsigned char resp, _r, _r_prime, _d; | ||
355 | |||
356 | _r = (r >> (4*i)) & 0xf; | ||
357 | _r = ((_r & 0x1) << 1) | | ||
358 | ((_r & 0x2) << 2) | | ||
359 | ((_r & 0x4) << 3) | | ||
360 | ((_r & 0x8) << 4); | ||
361 | |||
362 | /* writes _r, then reads back: */ | ||
363 | resp = ds1wm_read(ds1wm_data, _r); | ||
364 | |||
365 | if (ds1wm_data->read_error) { | ||
366 | dev_err(&ds1wm_data->pdev->dev, | ||
367 | "pass: %d nibble: %d read error\n", pass, i); | ||
368 | break; | ||
369 | } | ||
370 | |||
371 | _r_prime = ((resp & 0x02) >> 1) | | ||
372 | ((resp & 0x08) >> 2) | | ||
373 | ((resp & 0x20) >> 3) | | ||
374 | ((resp & 0x80) >> 4); | ||
375 | |||
376 | _d = ((resp & 0x01) >> 0) | | ||
377 | ((resp & 0x04) >> 1) | | ||
378 | ((resp & 0x10) >> 2) | | ||
379 | ((resp & 0x40) >> 3); | ||
380 | |||
381 | r_prime |= (unsigned long long) _r_prime << (i * 4); | ||
382 | d |= (unsigned long long) _d << (i * 4); | ||
383 | |||
384 | } | ||
385 | if (ds1wm_data->read_error) { | ||
386 | dev_err(&ds1wm_data->pdev->dev, | ||
387 | "pass: %d read error, retrying\n", pass); | ||
388 | break; | ||
389 | } | ||
390 | dev_dbg(&ds1wm_data->pdev->dev, | ||
391 | "pass: %d r\': %0#18llx d:%0#18llx\n", | ||
392 | pass, r_prime, d); | ||
393 | dev_dbg(&ds1wm_data->pdev->dev, | ||
394 | "pass: %d nibble loop complete, exiting ASM\n", pass); | ||
395 | ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA); | ||
396 | dev_dbg(&ds1wm_data->pdev->dev, | ||
397 | "pass: %d resetting bus\n", pass); | ||
398 | ds1wm_reset(ds1wm_data); | ||
399 | if ((r_prime & ((u64)1 << 63)) && (d & ((u64)1 << 63))) { | ||
400 | dev_err(&ds1wm_data->pdev->dev, | ||
401 | "pass: %d bus error, retrying\n", pass); | ||
402 | continue; /* start over */ | ||
403 | } | ||
404 | |||
405 | |||
406 | dev_dbg(&ds1wm_data->pdev->dev, | ||
407 | "pass: %d found %0#18llx\n", pass, r_prime); | ||
408 | slave_found(master_dev, r_prime); | ||
409 | ++slaves_found; | ||
410 | dev_dbg(&ds1wm_data->pdev->dev, | ||
411 | "pass: %d complete, preparing next pass\n", pass); | ||
412 | |||
413 | /* any discrepency found which we already choose the | ||
414 | '1' branch is now is now irrelevant we reveal the | ||
415 | next branch with this: */ | ||
416 | d &= ~r; | ||
417 | /* find last bit set, i.e. the most signif. bit set */ | ||
418 | ms_discrep_bit = fls64(d) - 1; | ||
419 | dev_dbg(&ds1wm_data->pdev->dev, | ||
420 | "pass: %d new d:%0#18llx MS discrep bit:%d\n", | ||
421 | pass, d, ms_discrep_bit); | ||
422 | |||
423 | /* prev_ms_discrep_bit = ms_discrep_bit; | ||
424 | prepare for next ROM search: */ | ||
425 | if (ms_discrep_bit == -1) | ||
426 | break; | ||
427 | |||
428 | r = (r & ~(~0ull << (ms_discrep_bit))) | 1 << ms_discrep_bit; | ||
429 | } /* end while true */ | ||
430 | dev_dbg(&ds1wm_data->pdev->dev, | ||
431 | "pass: %d total: %d search done ms d bit pos: %d\n", pass, | ||
432 | slaves_found, ms_discrep_bit); | ||
317 | } | 433 | } |
318 | 434 | ||
319 | /* --------------------------------------------------------------------- */ | 435 | /* --------------------------------------------------------------------- */ |
@@ -373,15 +489,15 @@ static int ds1wm_probe(struct platform_device *pdev) | |||
373 | goto err1; | 489 | goto err1; |
374 | } | 490 | } |
375 | ds1wm_data->irq = res->start; | 491 | ds1wm_data->irq = res->start; |
376 | ds1wm_data->active_high = plat->active_high; | 492 | ds1wm_data->int_en_reg_none = (plat->active_high ? DS1WM_INTEN_IAS : 0); |
377 | 493 | ||
378 | if (res->flags & IORESOURCE_IRQ_HIGHEDGE) | 494 | if (res->flags & IORESOURCE_IRQ_HIGHEDGE) |
379 | irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING); | 495 | irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING); |
380 | if (res->flags & IORESOURCE_IRQ_LOWEDGE) | 496 | if (res->flags & IORESOURCE_IRQ_LOWEDGE) |
381 | irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING); | 497 | irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING); |
382 | 498 | ||
383 | ret = request_irq(ds1wm_data->irq, ds1wm_isr, IRQF_DISABLED, | 499 | ret = request_irq(ds1wm_data->irq, ds1wm_isr, |
384 | "ds1wm", ds1wm_data); | 500 | IRQF_DISABLED | IRQF_SHARED, "ds1wm", ds1wm_data); |
385 | if (ret) | 501 | if (ret) |
386 | goto err1; | 502 | goto err1; |
387 | 503 | ||
@@ -468,5 +584,6 @@ module_exit(ds1wm_exit); | |||
468 | 584 | ||
469 | MODULE_LICENSE("GPL"); | 585 | MODULE_LICENSE("GPL"); |
470 | MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, " | 586 | MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, " |
471 | "Matt Reimer <mreimer@vpop.net>"); | 587 | "Matt Reimer <mreimer@vpop.net>," |
588 | "Jean-Francois Dagenais <dagenaisj@sonatest.com>"); | ||
472 | MODULE_DESCRIPTION("DS1WM w1 busmaster driver"); | 589 | MODULE_DESCRIPTION("DS1WM w1 busmaster driver"); |
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index f0c909625bd1..d0cb01b42012 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig | |||
@@ -16,6 +16,13 @@ config W1_SLAVE_SMEM | |||
16 | Say Y here if you want to connect 1-wire | 16 | Say Y here if you want to connect 1-wire |
17 | simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire. | 17 | simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire. |
18 | 18 | ||
19 | config W1_SLAVE_DS2408 | ||
20 | tristate "8-Channel Addressable Switch (IO Expander) 0x29 family support (DS2408)" | ||
21 | help | ||
22 | Say Y here if you want to use a 1-wire | ||
23 | |||
24 | DS2408 8-Channel Addressable Switch device support | ||
25 | |||
19 | config W1_SLAVE_DS2423 | 26 | config W1_SLAVE_DS2423 |
20 | tristate "Counter 1-wire device (DS2423)" | 27 | tristate "Counter 1-wire device (DS2423)" |
21 | select CRC16 | 28 | select CRC16 |
@@ -61,6 +68,19 @@ config W1_SLAVE_DS2760 | |||
61 | 68 | ||
62 | If you are unsure, say N. | 69 | If you are unsure, say N. |
63 | 70 | ||
71 | config W1_SLAVE_DS2780 | ||
72 | tristate "Dallas 2780 battery monitor chip" | ||
73 | depends on W1 | ||
74 | help | ||
75 | If you enable this you will have the DS2780 battery monitor | ||
76 | chip support. | ||
77 | |||
78 | The battery monitor chip is used in many batteries/devices | ||
79 | as the one who is responsible for charging/discharging/monitoring | ||
80 | Li+ batteries. | ||
81 | |||
82 | If you are unsure, say N. | ||
83 | |||
64 | config W1_SLAVE_BQ27000 | 84 | config W1_SLAVE_BQ27000 |
65 | tristate "BQ27000 slave support" | 85 | tristate "BQ27000 slave support" |
66 | depends on W1 | 86 | depends on W1 |
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile index 3c76350a24f7..1f31e9fb0b25 100644 --- a/drivers/w1/slaves/Makefile +++ b/drivers/w1/slaves/Makefile | |||
@@ -4,8 +4,10 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o | 5 | obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o |
6 | obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o | 6 | obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o |
7 | obj-$(CONFIG_W1_SLAVE_DS2408) += w1_ds2408.o | ||
7 | obj-$(CONFIG_W1_SLAVE_DS2423) += w1_ds2423.o | 8 | obj-$(CONFIG_W1_SLAVE_DS2423) += w1_ds2423.o |
8 | obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o | 9 | obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o |
9 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o | 10 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o |
10 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o | 11 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o |
12 | obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o | ||
11 | obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o | 13 | obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o |
diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c new file mode 100644 index 000000000000..c37781899d90 --- /dev/null +++ b/drivers/w1/slaves/w1_ds2408.c | |||
@@ -0,0 +1,402 @@ | |||
1 | /* | ||
2 | * w1_ds2408.c - w1 family 29 (DS2408) driver | ||
3 | * | ||
4 | * Copyright (c) 2010 Jean-Francois Dagenais <dagenaisj@sonatest.com> | ||
5 | * | ||
6 | * This source code is licensed under the GNU General Public License, | ||
7 | * Version 2. See the file COPYING for more details. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/moduleparam.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/slab.h> | ||
17 | |||
18 | #include "../w1.h" | ||
19 | #include "../w1_int.h" | ||
20 | #include "../w1_family.h" | ||
21 | |||
22 | MODULE_LICENSE("GPL"); | ||
23 | MODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>"); | ||
24 | MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO"); | ||
25 | |||
26 | |||
27 | #define W1_F29_RETRIES 3 | ||
28 | |||
29 | #define W1_F29_REG_LOGIG_STATE 0x88 /* R */ | ||
30 | #define W1_F29_REG_OUTPUT_LATCH_STATE 0x89 /* R */ | ||
31 | #define W1_F29_REG_ACTIVITY_LATCH_STATE 0x8A /* R */ | ||
32 | #define W1_F29_REG_COND_SEARCH_SELECT_MASK 0x8B /* RW */ | ||
33 | #define W1_F29_REG_COND_SEARCH_POL_SELECT 0x8C /* RW */ | ||
34 | #define W1_F29_REG_CONTROL_AND_STATUS 0x8D /* RW */ | ||
35 | |||
36 | #define W1_F29_FUNC_READ_PIO_REGS 0xF0 | ||
37 | #define W1_F29_FUNC_CHANN_ACCESS_READ 0xF5 | ||
38 | #define W1_F29_FUNC_CHANN_ACCESS_WRITE 0x5A | ||
39 | /* also used to write the control/status reg (0x8D): */ | ||
40 | #define W1_F29_FUNC_WRITE_COND_SEARCH_REG 0xCC | ||
41 | #define W1_F29_FUNC_RESET_ACTIVITY_LATCHES 0xC3 | ||
42 | |||
43 | #define W1_F29_SUCCESS_CONFIRM_BYTE 0xAA | ||
44 | |||
45 | static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf) | ||
46 | { | ||
47 | u8 wrbuf[3]; | ||
48 | dev_dbg(&sl->dev, | ||
49 | "Reading with slave: %p, reg addr: %0#4x, buff addr: %p", | ||
50 | sl, (unsigned int)address, buf); | ||
51 | |||
52 | if (!buf) | ||
53 | return -EINVAL; | ||
54 | |||
55 | mutex_lock(&sl->master->mutex); | ||
56 | dev_dbg(&sl->dev, "mutex locked"); | ||
57 | |||
58 | if (w1_reset_select_slave(sl)) { | ||
59 | mutex_unlock(&sl->master->mutex); | ||
60 | return -EIO; | ||
61 | } | ||
62 | |||
63 | wrbuf[0] = W1_F29_FUNC_READ_PIO_REGS; | ||
64 | wrbuf[1] = address; | ||
65 | wrbuf[2] = 0; | ||
66 | w1_write_block(sl->master, wrbuf, 3); | ||
67 | *buf = w1_read_8(sl->master); | ||
68 | |||
69 | mutex_unlock(&sl->master->mutex); | ||
70 | dev_dbg(&sl->dev, "mutex unlocked"); | ||
71 | return 1; | ||
72 | } | ||
73 | |||
74 | static ssize_t w1_f29_read_state( | ||
75 | struct file *filp, struct kobject *kobj, | ||
76 | struct bin_attribute *bin_attr, | ||
77 | char *buf, loff_t off, size_t count) | ||
78 | { | ||
79 | dev_dbg(&kobj_to_w1_slave(kobj)->dev, | ||
80 | "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", | ||
81 | bin_attr->attr.name, kobj, (unsigned int)off, count, buf); | ||
82 | if (count != 1 || off != 0) | ||
83 | return -EFAULT; | ||
84 | return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf); | ||
85 | } | ||
86 | |||
87 | static ssize_t w1_f29_read_output( | ||
88 | struct file *filp, struct kobject *kobj, | ||
89 | struct bin_attribute *bin_attr, | ||
90 | char *buf, loff_t off, size_t count) | ||
91 | { | ||
92 | dev_dbg(&kobj_to_w1_slave(kobj)->dev, | ||
93 | "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", | ||
94 | bin_attr->attr.name, kobj, (unsigned int)off, count, buf); | ||
95 | if (count != 1 || off != 0) | ||
96 | return -EFAULT; | ||
97 | return _read_reg(kobj_to_w1_slave(kobj), | ||
98 | W1_F29_REG_OUTPUT_LATCH_STATE, buf); | ||
99 | } | ||
100 | |||
101 | static ssize_t w1_f29_read_activity( | ||
102 | struct file *filp, struct kobject *kobj, | ||
103 | struct bin_attribute *bin_attr, | ||
104 | char *buf, loff_t off, size_t count) | ||
105 | { | ||
106 | dev_dbg(&kobj_to_w1_slave(kobj)->dev, | ||
107 | "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", | ||
108 | bin_attr->attr.name, kobj, (unsigned int)off, count, buf); | ||
109 | if (count != 1 || off != 0) | ||
110 | return -EFAULT; | ||
111 | return _read_reg(kobj_to_w1_slave(kobj), | ||
112 | W1_F29_REG_ACTIVITY_LATCH_STATE, buf); | ||
113 | } | ||
114 | |||
115 | static ssize_t w1_f29_read_cond_search_mask( | ||
116 | struct file *filp, struct kobject *kobj, | ||
117 | struct bin_attribute *bin_attr, | ||
118 | char *buf, loff_t off, size_t count) | ||
119 | { | ||
120 | dev_dbg(&kobj_to_w1_slave(kobj)->dev, | ||
121 | "Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p", | ||
122 | bin_attr->attr.name, kobj, (unsigned int)off, count, buf); | ||
123 | if (count != 1 || off != 0) | ||
124 | return -EFAULT; | ||
125 | return _read_reg(kobj_to_w1_slave(kobj), | ||
126 | W1_F29_REG_COND_SEARCH_SELECT_MASK, buf); | ||
127 | } | ||
128 | |||
129 | static ssize_t w1_f29_read_cond_search_polarity( | ||
130 | struct file *filp, struct kobject *kobj, | ||
131 | struct bin_attribute *bin_attr, | ||
132 | char *buf, loff_t off, size_t count) | ||
133 | { | ||
134 | if (count != 1 || off != 0) | ||
135 | return -EFAULT; | ||
136 | return _read_reg(kobj_to_w1_slave(kobj), | ||
137 | W1_F29_REG_COND_SEARCH_POL_SELECT, buf); | ||
138 | } | ||
139 | |||
140 | static ssize_t w1_f29_read_status_control( | ||
141 | struct file *filp, struct kobject *kobj, | ||
142 | struct bin_attribute *bin_attr, | ||
143 | char *buf, loff_t off, size_t count) | ||
144 | { | ||
145 | if (count != 1 || off != 0) | ||
146 | return -EFAULT; | ||
147 | return _read_reg(kobj_to_w1_slave(kobj), | ||
148 | W1_F29_REG_CONTROL_AND_STATUS, buf); | ||
149 | } | ||
150 | |||
151 | |||
152 | |||
153 | |||
154 | static ssize_t w1_f29_write_output( | ||
155 | struct file *filp, struct kobject *kobj, | ||
156 | struct bin_attribute *bin_attr, | ||
157 | char *buf, loff_t off, size_t count) | ||
158 | { | ||
159 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | ||
160 | u8 w1_buf[3]; | ||
161 | u8 readBack; | ||
162 | unsigned int retries = W1_F29_RETRIES; | ||
163 | |||
164 | if (count != 1 || off != 0) | ||
165 | return -EFAULT; | ||
166 | |||
167 | dev_dbg(&sl->dev, "locking mutex for write_output"); | ||
168 | mutex_lock(&sl->master->mutex); | ||
169 | dev_dbg(&sl->dev, "mutex locked"); | ||
170 | |||
171 | if (w1_reset_select_slave(sl)) | ||
172 | goto error; | ||
173 | |||
174 | while (retries--) { | ||
175 | w1_buf[0] = W1_F29_FUNC_CHANN_ACCESS_WRITE; | ||
176 | w1_buf[1] = *buf; | ||
177 | w1_buf[2] = ~(*buf); | ||
178 | w1_write_block(sl->master, w1_buf, 3); | ||
179 | |||
180 | readBack = w1_read_8(sl->master); | ||
181 | /* here the master could read another byte which | ||
182 | would be the PIO reg (the actual pin logic state) | ||
183 | since in this driver we don't know which pins are | ||
184 | in and outs, there's no value to read the state and | ||
185 | compare. with (*buf) so end this command abruptly: */ | ||
186 | if (w1_reset_resume_command(sl->master)) | ||
187 | goto error; | ||
188 | |||
189 | if (readBack != 0xAA) { | ||
190 | /* try again, the slave is ready for a command */ | ||
191 | continue; | ||
192 | } | ||
193 | |||
194 | /* go read back the output latches */ | ||
195 | /* (the direct effect of the write above) */ | ||
196 | w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS; | ||
197 | w1_buf[1] = W1_F29_REG_OUTPUT_LATCH_STATE; | ||
198 | w1_buf[2] = 0; | ||
199 | w1_write_block(sl->master, w1_buf, 3); | ||
200 | /* read the result of the READ_PIO_REGS command */ | ||
201 | if (w1_read_8(sl->master) == *buf) { | ||
202 | /* success! */ | ||
203 | mutex_unlock(&sl->master->mutex); | ||
204 | dev_dbg(&sl->dev, | ||
205 | "mutex unlocked, retries:%d", retries); | ||
206 | return 1; | ||
207 | } | ||
208 | } | ||
209 | error: | ||
210 | mutex_unlock(&sl->master->mutex); | ||
211 | dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries); | ||
212 | |||
213 | return -EIO; | ||
214 | } | ||
215 | |||
216 | |||
217 | /** | ||
218 | * Writing to the activity file resets the activity latches. | ||
219 | */ | ||
220 | static ssize_t w1_f29_write_activity( | ||
221 | struct file *filp, struct kobject *kobj, | ||
222 | struct bin_attribute *bin_attr, | ||
223 | char *buf, loff_t off, size_t count) | ||
224 | { | ||
225 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | ||
226 | unsigned int retries = W1_F29_RETRIES; | ||
227 | |||
228 | if (count != 1 || off != 0) | ||
229 | return -EFAULT; | ||
230 | |||
231 | mutex_lock(&sl->master->mutex); | ||
232 | |||
233 | if (w1_reset_select_slave(sl)) | ||
234 | goto error; | ||
235 | |||
236 | while (retries--) { | ||
237 | w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES); | ||
238 | if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) { | ||
239 | mutex_unlock(&sl->master->mutex); | ||
240 | return 1; | ||
241 | } | ||
242 | if (w1_reset_resume_command(sl->master)) | ||
243 | goto error; | ||
244 | } | ||
245 | |||
246 | error: | ||
247 | mutex_unlock(&sl->master->mutex); | ||
248 | return -EIO; | ||
249 | } | ||
250 | |||
251 | static ssize_t w1_f29_write_status_control( | ||
252 | struct file *filp, | ||
253 | struct kobject *kobj, | ||
254 | struct bin_attribute *bin_attr, | ||
255 | char *buf, | ||
256 | loff_t off, | ||
257 | size_t count) | ||
258 | { | ||
259 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | ||
260 | u8 w1_buf[4]; | ||
261 | unsigned int retries = W1_F29_RETRIES; | ||
262 | |||
263 | if (count != 1 || off != 0) | ||
264 | return -EFAULT; | ||
265 | |||
266 | mutex_lock(&sl->master->mutex); | ||
267 | |||
268 | if (w1_reset_select_slave(sl)) | ||
269 | goto error; | ||
270 | |||
271 | while (retries--) { | ||
272 | w1_buf[0] = W1_F29_FUNC_WRITE_COND_SEARCH_REG; | ||
273 | w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS; | ||
274 | w1_buf[2] = 0; | ||
275 | w1_buf[3] = *buf; | ||
276 | |||
277 | w1_write_block(sl->master, w1_buf, 4); | ||
278 | if (w1_reset_resume_command(sl->master)) | ||
279 | goto error; | ||
280 | |||
281 | w1_buf[0] = W1_F29_FUNC_READ_PIO_REGS; | ||
282 | w1_buf[1] = W1_F29_REG_CONTROL_AND_STATUS; | ||
283 | w1_buf[2] = 0; | ||
284 | |||
285 | w1_write_block(sl->master, w1_buf, 3); | ||
286 | if (w1_read_8(sl->master) == *buf) { | ||
287 | /* success! */ | ||
288 | mutex_unlock(&sl->master->mutex); | ||
289 | return 1; | ||
290 | } | ||
291 | } | ||
292 | error: | ||
293 | mutex_unlock(&sl->master->mutex); | ||
294 | |||
295 | return -EIO; | ||
296 | } | ||
297 | |||
298 | |||
299 | |||
300 | #define NB_SYSFS_BIN_FILES 6 | ||
301 | static struct bin_attribute w1_f29_sysfs_bin_files[NB_SYSFS_BIN_FILES] = { | ||
302 | { | ||
303 | .attr = { | ||
304 | .name = "state", | ||
305 | .mode = S_IRUGO, | ||
306 | }, | ||
307 | .size = 1, | ||
308 | .read = w1_f29_read_state, | ||
309 | }, | ||
310 | { | ||
311 | .attr = { | ||
312 | .name = "output", | ||
313 | .mode = S_IRUGO | S_IWUSR | S_IWGRP, | ||
314 | }, | ||
315 | .size = 1, | ||
316 | .read = w1_f29_read_output, | ||
317 | .write = w1_f29_write_output, | ||
318 | }, | ||
319 | { | ||
320 | .attr = { | ||
321 | .name = "activity", | ||
322 | .mode = S_IRUGO, | ||
323 | }, | ||
324 | .size = 1, | ||
325 | .read = w1_f29_read_activity, | ||
326 | .write = w1_f29_write_activity, | ||
327 | }, | ||
328 | { | ||
329 | .attr = { | ||
330 | .name = "cond_search_mask", | ||
331 | .mode = S_IRUGO, | ||
332 | }, | ||
333 | .size = 1, | ||
334 | .read = w1_f29_read_cond_search_mask, | ||
335 | .write = 0, | ||
336 | }, | ||
337 | { | ||
338 | .attr = { | ||
339 | .name = "cond_search_polarity", | ||
340 | .mode = S_IRUGO, | ||
341 | }, | ||
342 | .size = 1, | ||
343 | .read = w1_f29_read_cond_search_polarity, | ||
344 | .write = 0, | ||
345 | }, | ||
346 | { | ||
347 | .attr = { | ||
348 | .name = "status_control", | ||
349 | .mode = S_IRUGO | S_IWUSR | S_IWGRP, | ||
350 | }, | ||
351 | .size = 1, | ||
352 | .read = w1_f29_read_status_control, | ||
353 | .write = w1_f29_write_status_control, | ||
354 | } | ||
355 | }; | ||
356 | |||
357 | static int w1_f29_add_slave(struct w1_slave *sl) | ||
358 | { | ||
359 | int err = 0; | ||
360 | int i; | ||
361 | |||
362 | for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i) | ||
363 | err = sysfs_create_bin_file( | ||
364 | &sl->dev.kobj, | ||
365 | &(w1_f29_sysfs_bin_files[i])); | ||
366 | if (err) | ||
367 | while (--i >= 0) | ||
368 | sysfs_remove_bin_file(&sl->dev.kobj, | ||
369 | &(w1_f29_sysfs_bin_files[i])); | ||
370 | return err; | ||
371 | } | ||
372 | |||
373 | static void w1_f29_remove_slave(struct w1_slave *sl) | ||
374 | { | ||
375 | int i; | ||
376 | for (i = NB_SYSFS_BIN_FILES; i <= 0; --i) | ||
377 | sysfs_remove_bin_file(&sl->dev.kobj, | ||
378 | &(w1_f29_sysfs_bin_files[i])); | ||
379 | } | ||
380 | |||
381 | static struct w1_family_ops w1_f29_fops = { | ||
382 | .add_slave = w1_f29_add_slave, | ||
383 | .remove_slave = w1_f29_remove_slave, | ||
384 | }; | ||
385 | |||
386 | static struct w1_family w1_family_29 = { | ||
387 | .fid = W1_FAMILY_DS2408, | ||
388 | .fops = &w1_f29_fops, | ||
389 | }; | ||
390 | |||
391 | static int __init w1_f29_init(void) | ||
392 | { | ||
393 | return w1_register_family(&w1_family_29); | ||
394 | } | ||
395 | |||
396 | static void __exit w1_f29_exit(void) | ||
397 | { | ||
398 | w1_unregister_family(&w1_family_29); | ||
399 | } | ||
400 | |||
401 | module_init(w1_f29_init); | ||
402 | module_exit(w1_f29_exit); | ||
diff --git a/drivers/w1/slaves/w1_ds2780.c b/drivers/w1/slaves/w1_ds2780.c new file mode 100644 index 000000000000..274c8f38303f --- /dev/null +++ b/drivers/w1/slaves/w1_ds2780.c | |||
@@ -0,0 +1,217 @@ | |||
1 | /* | ||
2 | * 1-Wire implementation for the ds2780 chip | ||
3 | * | ||
4 | * Copyright (C) 2010 Indesign, LLC | ||
5 | * | ||
6 | * Author: Clifton Barnes <cabarnes@indesign-llc.com> | ||
7 | * | ||
8 | * Based on w1-ds2760 driver | ||
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 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/mutex.h> | ||
22 | #include <linux/idr.h> | ||
23 | |||
24 | #include "../w1.h" | ||
25 | #include "../w1_int.h" | ||
26 | #include "../w1_family.h" | ||
27 | #include "w1_ds2780.h" | ||
28 | |||
29 | int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, | ||
30 | int io) | ||
31 | { | ||
32 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
33 | |||
34 | if (!dev) | ||
35 | return -ENODEV; | ||
36 | |||
37 | mutex_lock(&sl->master->mutex); | ||
38 | |||
39 | if (addr > DS2780_DATA_SIZE || addr < 0) { | ||
40 | count = 0; | ||
41 | goto out; | ||
42 | } | ||
43 | count = min_t(int, count, DS2780_DATA_SIZE - addr); | ||
44 | |||
45 | if (w1_reset_select_slave(sl) == 0) { | ||
46 | if (io) { | ||
47 | w1_write_8(sl->master, W1_DS2780_WRITE_DATA); | ||
48 | w1_write_8(sl->master, addr); | ||
49 | w1_write_block(sl->master, buf, count); | ||
50 | /* XXX w1_write_block returns void, not n_written */ | ||
51 | } else { | ||
52 | w1_write_8(sl->master, W1_DS2780_READ_DATA); | ||
53 | w1_write_8(sl->master, addr); | ||
54 | count = w1_read_block(sl->master, buf, count); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | out: | ||
59 | mutex_unlock(&sl->master->mutex); | ||
60 | |||
61 | return count; | ||
62 | } | ||
63 | EXPORT_SYMBOL(w1_ds2780_io); | ||
64 | |||
65 | int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd) | ||
66 | { | ||
67 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
68 | |||
69 | if (!dev) | ||
70 | return -EINVAL; | ||
71 | |||
72 | mutex_lock(&sl->master->mutex); | ||
73 | |||
74 | if (w1_reset_select_slave(sl) == 0) { | ||
75 | w1_write_8(sl->master, cmd); | ||
76 | w1_write_8(sl->master, addr); | ||
77 | } | ||
78 | |||
79 | mutex_unlock(&sl->master->mutex); | ||
80 | return 0; | ||
81 | } | ||
82 | EXPORT_SYMBOL(w1_ds2780_eeprom_cmd); | ||
83 | |||
84 | static ssize_t w1_ds2780_read_bin(struct file *filp, | ||
85 | struct kobject *kobj, | ||
86 | struct bin_attribute *bin_attr, | ||
87 | char *buf, loff_t off, size_t count) | ||
88 | { | ||
89 | struct device *dev = container_of(kobj, struct device, kobj); | ||
90 | return w1_ds2780_io(dev, buf, off, count, 0); | ||
91 | } | ||
92 | |||
93 | static struct bin_attribute w1_ds2780_bin_attr = { | ||
94 | .attr = { | ||
95 | .name = "w1_slave", | ||
96 | .mode = S_IRUGO, | ||
97 | }, | ||
98 | .size = DS2780_DATA_SIZE, | ||
99 | .read = w1_ds2780_read_bin, | ||
100 | }; | ||
101 | |||
102 | static DEFINE_IDR(bat_idr); | ||
103 | static DEFINE_MUTEX(bat_idr_lock); | ||
104 | |||
105 | static int new_bat_id(void) | ||
106 | { | ||
107 | int ret; | ||
108 | |||
109 | while (1) { | ||
110 | int id; | ||
111 | |||
112 | ret = idr_pre_get(&bat_idr, GFP_KERNEL); | ||
113 | if (ret == 0) | ||
114 | return -ENOMEM; | ||
115 | |||
116 | mutex_lock(&bat_idr_lock); | ||
117 | ret = idr_get_new(&bat_idr, NULL, &id); | ||
118 | mutex_unlock(&bat_idr_lock); | ||
119 | |||
120 | if (ret == 0) { | ||
121 | ret = id & MAX_ID_MASK; | ||
122 | break; | ||
123 | } else if (ret == -EAGAIN) { | ||
124 | continue; | ||
125 | } else { | ||
126 | break; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | static void release_bat_id(int id) | ||
134 | { | ||
135 | mutex_lock(&bat_idr_lock); | ||
136 | idr_remove(&bat_idr, id); | ||
137 | mutex_unlock(&bat_idr_lock); | ||
138 | } | ||
139 | |||
140 | static int w1_ds2780_add_slave(struct w1_slave *sl) | ||
141 | { | ||
142 | int ret; | ||
143 | int id; | ||
144 | struct platform_device *pdev; | ||
145 | |||
146 | id = new_bat_id(); | ||
147 | if (id < 0) { | ||
148 | ret = id; | ||
149 | goto noid; | ||
150 | } | ||
151 | |||
152 | pdev = platform_device_alloc("ds2780-battery", id); | ||
153 | if (!pdev) { | ||
154 | ret = -ENOMEM; | ||
155 | goto pdev_alloc_failed; | ||
156 | } | ||
157 | pdev->dev.parent = &sl->dev; | ||
158 | |||
159 | ret = platform_device_add(pdev); | ||
160 | if (ret) | ||
161 | goto pdev_add_failed; | ||
162 | |||
163 | ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2780_bin_attr); | ||
164 | if (ret) | ||
165 | goto bin_attr_failed; | ||
166 | |||
167 | dev_set_drvdata(&sl->dev, pdev); | ||
168 | |||
169 | return 0; | ||
170 | |||
171 | bin_attr_failed: | ||
172 | pdev_add_failed: | ||
173 | platform_device_unregister(pdev); | ||
174 | pdev_alloc_failed: | ||
175 | release_bat_id(id); | ||
176 | noid: | ||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | static void w1_ds2780_remove_slave(struct w1_slave *sl) | ||
181 | { | ||
182 | struct platform_device *pdev = dev_get_drvdata(&sl->dev); | ||
183 | int id = pdev->id; | ||
184 | |||
185 | platform_device_unregister(pdev); | ||
186 | release_bat_id(id); | ||
187 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2780_bin_attr); | ||
188 | } | ||
189 | |||
190 | static struct w1_family_ops w1_ds2780_fops = { | ||
191 | .add_slave = w1_ds2780_add_slave, | ||
192 | .remove_slave = w1_ds2780_remove_slave, | ||
193 | }; | ||
194 | |||
195 | static struct w1_family w1_ds2780_family = { | ||
196 | .fid = W1_FAMILY_DS2780, | ||
197 | .fops = &w1_ds2780_fops, | ||
198 | }; | ||
199 | |||
200 | static int __init w1_ds2780_init(void) | ||
201 | { | ||
202 | idr_init(&bat_idr); | ||
203 | return w1_register_family(&w1_ds2780_family); | ||
204 | } | ||
205 | |||
206 | static void __exit w1_ds2780_exit(void) | ||
207 | { | ||
208 | w1_unregister_family(&w1_ds2780_family); | ||
209 | idr_destroy(&bat_idr); | ||
210 | } | ||
211 | |||
212 | module_init(w1_ds2780_init); | ||
213 | module_exit(w1_ds2780_exit); | ||
214 | |||
215 | MODULE_LICENSE("GPL"); | ||
216 | MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>"); | ||
217 | MODULE_DESCRIPTION("1-wire Driver for Maxim/Dallas DS2780 Stand-Alone Fuel Gauge IC"); | ||
diff --git a/drivers/w1/slaves/w1_ds2780.h b/drivers/w1/slaves/w1_ds2780.h new file mode 100644 index 000000000000..a1fba79eb1b5 --- /dev/null +++ b/drivers/w1/slaves/w1_ds2780.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * 1-Wire implementation for the ds2780 chip | ||
3 | * | ||
4 | * Copyright (C) 2010 Indesign, LLC | ||
5 | * | ||
6 | * Author: Clifton Barnes <cabarnes@indesign-llc.com> | ||
7 | * | ||
8 | * Based on w1-ds2760 driver | ||
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 | */ | ||
15 | |||
16 | #ifndef _W1_DS2780_H | ||
17 | #define _W1_DS2780_H | ||
18 | |||
19 | /* Function commands */ | ||
20 | #define W1_DS2780_READ_DATA 0x69 | ||
21 | #define W1_DS2780_WRITE_DATA 0x6C | ||
22 | #define W1_DS2780_COPY_DATA 0x48 | ||
23 | #define W1_DS2780_RECALL_DATA 0xB8 | ||
24 | #define W1_DS2780_LOCK 0x6A | ||
25 | |||
26 | /* Register map */ | ||
27 | /* Register 0x00 Reserved */ | ||
28 | #define DS2780_STATUS_REG 0x01 | ||
29 | #define DS2780_RAAC_MSB_REG 0x02 | ||
30 | #define DS2780_RAAC_LSB_REG 0x03 | ||
31 | #define DS2780_RSAC_MSB_REG 0x04 | ||
32 | #define DS2780_RSAC_LSB_REG 0x05 | ||
33 | #define DS2780_RARC_REG 0x06 | ||
34 | #define DS2780_RSRC_REG 0x07 | ||
35 | #define DS2780_IAVG_MSB_REG 0x08 | ||
36 | #define DS2780_IAVG_LSB_REG 0x09 | ||
37 | #define DS2780_TEMP_MSB_REG 0x0A | ||
38 | #define DS2780_TEMP_LSB_REG 0x0B | ||
39 | #define DS2780_VOLT_MSB_REG 0x0C | ||
40 | #define DS2780_VOLT_LSB_REG 0x0D | ||
41 | #define DS2780_CURRENT_MSB_REG 0x0E | ||
42 | #define DS2780_CURRENT_LSB_REG 0x0F | ||
43 | #define DS2780_ACR_MSB_REG 0x10 | ||
44 | #define DS2780_ACR_LSB_REG 0x11 | ||
45 | #define DS2780_ACRL_MSB_REG 0x12 | ||
46 | #define DS2780_ACRL_LSB_REG 0x13 | ||
47 | #define DS2780_AS_REG 0x14 | ||
48 | #define DS2780_SFR_REG 0x15 | ||
49 | #define DS2780_FULL_MSB_REG 0x16 | ||
50 | #define DS2780_FULL_LSB_REG 0x17 | ||
51 | #define DS2780_AE_MSB_REG 0x18 | ||
52 | #define DS2780_AE_LSB_REG 0x19 | ||
53 | #define DS2780_SE_MSB_REG 0x1A | ||
54 | #define DS2780_SE_LSB_REG 0x1B | ||
55 | /* Register 0x1C - 0x1E Reserved */ | ||
56 | #define DS2780_EEPROM_REG 0x1F | ||
57 | #define DS2780_EEPROM_BLOCK0_START 0x20 | ||
58 | /* Register 0x20 - 0x2F User EEPROM */ | ||
59 | #define DS2780_EEPROM_BLOCK0_END 0x2F | ||
60 | /* Register 0x30 - 0x5F Reserved */ | ||
61 | #define DS2780_EEPROM_BLOCK1_START 0x60 | ||
62 | #define DS2780_CONTROL_REG 0x60 | ||
63 | #define DS2780_AB_REG 0x61 | ||
64 | #define DS2780_AC_MSB_REG 0x62 | ||
65 | #define DS2780_AC_LSB_REG 0x63 | ||
66 | #define DS2780_VCHG_REG 0x64 | ||
67 | #define DS2780_IMIN_REG 0x65 | ||
68 | #define DS2780_VAE_REG 0x66 | ||
69 | #define DS2780_IAE_REG 0x67 | ||
70 | #define DS2780_AE_40_REG 0x68 | ||
71 | #define DS2780_RSNSP_REG 0x69 | ||
72 | #define DS2780_FULL_40_MSB_REG 0x6A | ||
73 | #define DS2780_FULL_40_LSB_REG 0x6B | ||
74 | #define DS2780_FULL_3040_SLOPE_REG 0x6C | ||
75 | #define DS2780_FULL_2030_SLOPE_REG 0x6D | ||
76 | #define DS2780_FULL_1020_SLOPE_REG 0x6E | ||
77 | #define DS2780_FULL_0010_SLOPE_REG 0x6F | ||
78 | #define DS2780_AE_3040_SLOPE_REG 0x70 | ||
79 | #define DS2780_AE_2030_SLOPE_REG 0x71 | ||
80 | #define DS2780_AE_1020_SLOPE_REG 0x72 | ||
81 | #define DS2780_AE_0010_SLOPE_REG 0x73 | ||
82 | #define DS2780_SE_3040_SLOPE_REG 0x74 | ||
83 | #define DS2780_SE_2030_SLOPE_REG 0x75 | ||
84 | #define DS2780_SE_1020_SLOPE_REG 0x76 | ||
85 | #define DS2780_SE_0010_SLOPE_REG 0x77 | ||
86 | #define DS2780_RSGAIN_MSB_REG 0x78 | ||
87 | #define DS2780_RSGAIN_LSB_REG 0x79 | ||
88 | #define DS2780_RSTC_REG 0x7A | ||
89 | #define DS2780_FRSGAIN_MSB_REG 0x7B | ||
90 | #define DS2780_FRSGAIN_LSB_REG 0x7C | ||
91 | #define DS2780_EEPROM_BLOCK1_END 0x7C | ||
92 | /* Register 0x7D - 0xFF Reserved */ | ||
93 | |||
94 | /* Number of valid register addresses */ | ||
95 | #define DS2780_DATA_SIZE 0x80 | ||
96 | |||
97 | /* Status register bits */ | ||
98 | #define DS2780_STATUS_REG_CHGTF (1 << 7) | ||
99 | #define DS2780_STATUS_REG_AEF (1 << 6) | ||
100 | #define DS2780_STATUS_REG_SEF (1 << 5) | ||
101 | #define DS2780_STATUS_REG_LEARNF (1 << 4) | ||
102 | /* Bit 3 Reserved */ | ||
103 | #define DS2780_STATUS_REG_UVF (1 << 2) | ||
104 | #define DS2780_STATUS_REG_PORF (1 << 1) | ||
105 | /* Bit 0 Reserved */ | ||
106 | |||
107 | /* Control register bits */ | ||
108 | /* Bit 7 Reserved */ | ||
109 | #define DS2780_CONTROL_REG_UVEN (1 << 6) | ||
110 | #define DS2780_CONTROL_REG_PMOD (1 << 5) | ||
111 | #define DS2780_CONTROL_REG_RNAOP (1 << 4) | ||
112 | /* Bit 0 - 3 Reserved */ | ||
113 | |||
114 | /* Special feature register bits */ | ||
115 | /* Bit 1 - 7 Reserved */ | ||
116 | #define DS2780_SFR_REG_PIOSC (1 << 0) | ||
117 | |||
118 | /* EEPROM register bits */ | ||
119 | #define DS2780_EEPROM_REG_EEC (1 << 7) | ||
120 | #define DS2780_EEPROM_REG_LOCK (1 << 6) | ||
121 | /* Bit 2 - 6 Reserved */ | ||
122 | #define DS2780_EEPROM_REG_BL1 (1 << 1) | ||
123 | #define DS2780_EEPROM_REG_BL0 (1 << 0) | ||
124 | |||
125 | extern int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, | ||
126 | int io); | ||
127 | extern int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd); | ||
128 | |||
129 | #endif /* !_W1_DS2780_H */ | ||
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index b7b5014ff714..10606c822756 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
@@ -827,7 +827,7 @@ void w1_reconnect_slaves(struct w1_family *f, int attach) | |||
827 | mutex_unlock(&w1_mlock); | 827 | mutex_unlock(&w1_mlock); |
828 | } | 828 | } |
829 | 829 | ||
830 | static void w1_slave_found(struct w1_master *dev, u64 rn) | 830 | void w1_slave_found(struct w1_master *dev, u64 rn) |
831 | { | 831 | { |
832 | struct w1_slave *sl; | 832 | struct w1_slave *sl; |
833 | struct w1_reg_num *tmp; | 833 | struct w1_reg_num *tmp; |
@@ -933,14 +933,15 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb | |||
933 | } | 933 | } |
934 | } | 934 | } |
935 | 935 | ||
936 | void w1_search_process(struct w1_master *dev, u8 search_type) | 936 | void w1_search_process_cb(struct w1_master *dev, u8 search_type, |
937 | w1_slave_found_callback cb) | ||
937 | { | 938 | { |
938 | struct w1_slave *sl, *sln; | 939 | struct w1_slave *sl, *sln; |
939 | 940 | ||
940 | list_for_each_entry(sl, &dev->slist, w1_slave_entry) | 941 | list_for_each_entry(sl, &dev->slist, w1_slave_entry) |
941 | clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); | 942 | clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); |
942 | 943 | ||
943 | w1_search_devices(dev, search_type, w1_slave_found); | 944 | w1_search_devices(dev, search_type, cb); |
944 | 945 | ||
945 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { | 946 | list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { |
946 | if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) | 947 | if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) |
@@ -953,6 +954,11 @@ void w1_search_process(struct w1_master *dev, u8 search_type) | |||
953 | dev->search_count--; | 954 | dev->search_count--; |
954 | } | 955 | } |
955 | 956 | ||
957 | static void w1_search_process(struct w1_master *dev, u8 search_type) | ||
958 | { | ||
959 | w1_search_process_cb(dev, search_type, w1_slave_found); | ||
960 | } | ||
961 | |||
956 | int w1_process(void *data) | 962 | int w1_process(void *data) |
957 | { | 963 | { |
958 | struct w1_master *dev = (struct w1_master *) data; | 964 | struct w1_master *dev = (struct w1_master *) data; |
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index d8a9709f3449..1ce23fc6186c 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h | |||
@@ -55,6 +55,7 @@ struct w1_reg_num | |||
55 | #define W1_READ_ROM 0x33 | 55 | #define W1_READ_ROM 0x33 |
56 | #define W1_READ_PSUPPLY 0xB4 | 56 | #define W1_READ_PSUPPLY 0xB4 |
57 | #define W1_MATCH_ROM 0x55 | 57 | #define W1_MATCH_ROM 0x55 |
58 | #define W1_RESUME_CMD 0xA5 | ||
58 | 59 | ||
59 | #define W1_SLAVE_ACTIVE 0 | 60 | #define W1_SLAVE_ACTIVE 0 |
60 | 61 | ||
@@ -193,7 +194,9 @@ void w1_destroy_master_attributes(struct w1_master *master); | |||
193 | void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); | 194 | void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); |
194 | void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); | 195 | void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); |
195 | struct w1_slave *w1_search_slave(struct w1_reg_num *id); | 196 | struct w1_slave *w1_search_slave(struct w1_reg_num *id); |
196 | void w1_search_process(struct w1_master *dev, u8 search_type); | 197 | void w1_slave_found(struct w1_master *dev, u64 rn); |
198 | void w1_search_process_cb(struct w1_master *dev, u8 search_type, | ||
199 | w1_slave_found_callback cb); | ||
197 | struct w1_master *w1_search_master_id(u32 id); | 200 | struct w1_master *w1_search_master_id(u32 id); |
198 | 201 | ||
199 | /* Disconnect and reconnect devices in the given family. Used for finding | 202 | /* Disconnect and reconnect devices in the given family. Used for finding |
@@ -213,6 +216,7 @@ void w1_write_block(struct w1_master *, const u8 *, int); | |||
213 | void w1_touch_block(struct w1_master *, u8 *, int); | 216 | void w1_touch_block(struct w1_master *, u8 *, int); |
214 | u8 w1_read_block(struct w1_master *, u8 *, int); | 217 | u8 w1_read_block(struct w1_master *, u8 *, int); |
215 | int w1_reset_select_slave(struct w1_slave *sl); | 218 | int w1_reset_select_slave(struct w1_slave *sl); |
219 | int w1_reset_resume_command(struct w1_master *); | ||
216 | void w1_next_pullup(struct w1_master *, int); | 220 | void w1_next_pullup(struct w1_master *, int); |
217 | 221 | ||
218 | static inline struct w1_slave* dev_to_w1_slave(struct device *dev) | 222 | static inline struct w1_slave* dev_to_w1_slave(struct device *dev) |
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index f3b636d7cafe..97479ae70b9c 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h | |||
@@ -34,8 +34,10 @@ | |||
34 | #define W1_THERM_DS1822 0x22 | 34 | #define W1_THERM_DS1822 0x22 |
35 | #define W1_EEPROM_DS2433 0x23 | 35 | #define W1_EEPROM_DS2433 0x23 |
36 | #define W1_THERM_DS18B20 0x28 | 36 | #define W1_THERM_DS18B20 0x28 |
37 | #define W1_FAMILY_DS2408 0x29 | ||
37 | #define W1_EEPROM_DS2431 0x2D | 38 | #define W1_EEPROM_DS2431 0x2D |
38 | #define W1_FAMILY_DS2760 0x30 | 39 | #define W1_FAMILY_DS2760 0x30 |
40 | #define W1_FAMILY_DS2780 0x32 | ||
39 | 41 | ||
40 | #define MAXNAMELEN 32 | 42 | #define MAXNAMELEN 32 |
41 | 43 | ||
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index 3ebe9726a9e5..8e8b64cfafb6 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c | |||
@@ -390,6 +390,32 @@ int w1_reset_select_slave(struct w1_slave *sl) | |||
390 | EXPORT_SYMBOL_GPL(w1_reset_select_slave); | 390 | EXPORT_SYMBOL_GPL(w1_reset_select_slave); |
391 | 391 | ||
392 | /** | 392 | /** |
393 | * When the workflow with a slave amongst many requires several | ||
394 | * successive commands a reset between each, this function is similar | ||
395 | * to doing a reset then a match ROM for the last matched ROM. The | ||
396 | * advantage being that the matched ROM step is skipped in favor of the | ||
397 | * resume command. The slave must support the command of course. | ||
398 | * | ||
399 | * If the bus has only one slave, traditionnaly the match ROM is skipped | ||
400 | * and a "SKIP ROM" is done for efficiency. On multi-slave busses, this | ||
401 | * doesn't work of course, but the resume command is the next best thing. | ||
402 | * | ||
403 | * The w1 master lock must be held. | ||
404 | * | ||
405 | * @param dev the master device | ||
406 | */ | ||
407 | int w1_reset_resume_command(struct w1_master *dev) | ||
408 | { | ||
409 | if (w1_reset_bus(dev)) | ||
410 | return -1; | ||
411 | |||
412 | /* This will make only the last matched slave perform a skip ROM. */ | ||
413 | w1_write_8(dev, W1_RESUME_CMD); | ||
414 | return 0; | ||
415 | } | ||
416 | EXPORT_SYMBOL_GPL(w1_reset_resume_command); | ||
417 | |||
418 | /** | ||
393 | * Put out a strong pull-up of the specified duration after the next write | 419 | * Put out a strong pull-up of the specified duration after the next write |
394 | * operation. Not all hardware supports strong pullups. Hardware that | 420 | * operation. Not all hardware supports strong pullups. Hardware that |
395 | * doesn't support strong pullups will sleep for the given time after the | 421 | * doesn't support strong pullups will sleep for the given time after the |
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c index 7e667bc77ef2..55aabd927c60 100644 --- a/drivers/w1/w1_netlink.c +++ b/drivers/w1/w1_netlink.c | |||
@@ -55,6 +55,9 @@ static void w1_send_slave(struct w1_master *dev, u64 rn) | |||
55 | struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)(hdr + 1); | 55 | struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)(hdr + 1); |
56 | int avail; | 56 | int avail; |
57 | 57 | ||
58 | /* update kernel slave list */ | ||
59 | w1_slave_found(dev, rn); | ||
60 | |||
58 | avail = dev->priv_size - cmd->len; | 61 | avail = dev->priv_size - cmd->len; |
59 | 62 | ||
60 | if (avail > 8) { | 63 | if (avail > 8) { |
@@ -85,7 +88,7 @@ static int w1_process_search_command(struct w1_master *dev, struct cn_msg *msg, | |||
85 | dev->priv = msg; | 88 | dev->priv = msg; |
86 | dev->priv_size = avail; | 89 | dev->priv_size = avail; |
87 | 90 | ||
88 | w1_search_devices(dev, search_type, w1_send_slave); | 91 | w1_search_process_cb(dev, search_type, w1_send_slave); |
89 | 92 | ||
90 | msg->ack = 0; | 93 | msg->ack = 0; |
91 | cn_netlink_send(msg, 0, GFP_KERNEL); | 94 | cn_netlink_send(msg, 0, GFP_KERNEL); |