diff options
Diffstat (limited to 'drivers')
405 files changed, 19979 insertions, 5133 deletions
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 6174965d9a4d..f916ddf63938 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c | |||
@@ -781,7 +781,8 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) | |||
781 | sk_for_each(s, node, head) { | 781 | sk_for_each(s, node, head) { |
782 | vcc = atm_sk(s); | 782 | vcc = atm_sk(s); |
783 | if (vcc->dev == dev && vcc->vci == vci && | 783 | if (vcc->dev == dev && vcc->vci == vci && |
784 | vcc->vpi == vpi && vcc->qos.rxtp.traffic_class != ATM_NONE) | 784 | vcc->vpi == vpi && vcc->qos.rxtp.traffic_class != ATM_NONE && |
785 | test_bit(ATM_VF_READY, &vcc->flags)) | ||
785 | goto out; | 786 | goto out; |
786 | } | 787 | } |
787 | vcc = NULL; | 788 | vcc = NULL; |
@@ -907,6 +908,10 @@ static void pclose(struct atm_vcc *vcc) | |||
907 | clear_bit(ATM_VF_ADDR, &vcc->flags); | 908 | clear_bit(ATM_VF_ADDR, &vcc->flags); |
908 | clear_bit(ATM_VF_READY, &vcc->flags); | 909 | clear_bit(ATM_VF_READY, &vcc->flags); |
909 | 910 | ||
911 | /* Hold up vcc_destroy_socket() (our caller) until solos_bh() in the | ||
912 | tasklet has finished processing any incoming packets (and, more to | ||
913 | the point, using the vcc pointer). */ | ||
914 | tasklet_unlock_wait(&card->tlet); | ||
910 | return; | 915 | return; |
911 | } | 916 | } |
912 | 917 | ||
diff --git a/drivers/base/node.c b/drivers/base/node.c index 2bdd8a94ec94..2872e86837b2 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
@@ -66,8 +66,7 @@ static ssize_t node_read_meminfo(struct sys_device * dev, | |||
66 | struct sysinfo i; | 66 | struct sysinfo i; |
67 | 67 | ||
68 | si_meminfo_node(&i, nid); | 68 | si_meminfo_node(&i, nid); |
69 | 69 | n = sprintf(buf, | |
70 | n = sprintf(buf, "\n" | ||
71 | "Node %d MemTotal: %8lu kB\n" | 70 | "Node %d MemTotal: %8lu kB\n" |
72 | "Node %d MemFree: %8lu kB\n" | 71 | "Node %d MemFree: %8lu kB\n" |
73 | "Node %d MemUsed: %8lu kB\n" | 72 | "Node %d MemUsed: %8lu kB\n" |
@@ -78,13 +77,33 @@ static ssize_t node_read_meminfo(struct sys_device * dev, | |||
78 | "Node %d Active(file): %8lu kB\n" | 77 | "Node %d Active(file): %8lu kB\n" |
79 | "Node %d Inactive(file): %8lu kB\n" | 78 | "Node %d Inactive(file): %8lu kB\n" |
80 | "Node %d Unevictable: %8lu kB\n" | 79 | "Node %d Unevictable: %8lu kB\n" |
81 | "Node %d Mlocked: %8lu kB\n" | 80 | "Node %d Mlocked: %8lu kB\n", |
81 | nid, K(i.totalram), | ||
82 | nid, K(i.freeram), | ||
83 | nid, K(i.totalram - i.freeram), | ||
84 | nid, K(node_page_state(nid, NR_ACTIVE_ANON) + | ||
85 | node_page_state(nid, NR_ACTIVE_FILE)), | ||
86 | nid, K(node_page_state(nid, NR_INACTIVE_ANON) + | ||
87 | node_page_state(nid, NR_INACTIVE_FILE)), | ||
88 | nid, K(node_page_state(nid, NR_ACTIVE_ANON)), | ||
89 | nid, K(node_page_state(nid, NR_INACTIVE_ANON)), | ||
90 | nid, K(node_page_state(nid, NR_ACTIVE_FILE)), | ||
91 | nid, K(node_page_state(nid, NR_INACTIVE_FILE)), | ||
92 | nid, K(node_page_state(nid, NR_UNEVICTABLE)), | ||
93 | nid, K(node_page_state(nid, NR_MLOCK))); | ||
94 | |||
82 | #ifdef CONFIG_HIGHMEM | 95 | #ifdef CONFIG_HIGHMEM |
96 | n += sprintf(buf + n, | ||
83 | "Node %d HighTotal: %8lu kB\n" | 97 | "Node %d HighTotal: %8lu kB\n" |
84 | "Node %d HighFree: %8lu kB\n" | 98 | "Node %d HighFree: %8lu kB\n" |
85 | "Node %d LowTotal: %8lu kB\n" | 99 | "Node %d LowTotal: %8lu kB\n" |
86 | "Node %d LowFree: %8lu kB\n" | 100 | "Node %d LowFree: %8lu kB\n", |
101 | nid, K(i.totalhigh), | ||
102 | nid, K(i.freehigh), | ||
103 | nid, K(i.totalram - i.totalhigh), | ||
104 | nid, K(i.freeram - i.freehigh)); | ||
87 | #endif | 105 | #endif |
106 | n += sprintf(buf + n, | ||
88 | "Node %d Dirty: %8lu kB\n" | 107 | "Node %d Dirty: %8lu kB\n" |
89 | "Node %d Writeback: %8lu kB\n" | 108 | "Node %d Writeback: %8lu kB\n" |
90 | "Node %d FilePages: %8lu kB\n" | 109 | "Node %d FilePages: %8lu kB\n" |
@@ -99,25 +118,6 @@ static ssize_t node_read_meminfo(struct sys_device * dev, | |||
99 | "Node %d Slab: %8lu kB\n" | 118 | "Node %d Slab: %8lu kB\n" |
100 | "Node %d SReclaimable: %8lu kB\n" | 119 | "Node %d SReclaimable: %8lu kB\n" |
101 | "Node %d SUnreclaim: %8lu kB\n", | 120 | "Node %d SUnreclaim: %8lu kB\n", |
102 | nid, K(i.totalram), | ||
103 | nid, K(i.freeram), | ||
104 | nid, K(i.totalram - i.freeram), | ||
105 | nid, K(node_page_state(nid, NR_ACTIVE_ANON) + | ||
106 | node_page_state(nid, NR_ACTIVE_FILE)), | ||
107 | nid, K(node_page_state(nid, NR_INACTIVE_ANON) + | ||
108 | node_page_state(nid, NR_INACTIVE_FILE)), | ||
109 | nid, K(node_page_state(nid, NR_ACTIVE_ANON)), | ||
110 | nid, K(node_page_state(nid, NR_INACTIVE_ANON)), | ||
111 | nid, K(node_page_state(nid, NR_ACTIVE_FILE)), | ||
112 | nid, K(node_page_state(nid, NR_INACTIVE_FILE)), | ||
113 | nid, K(node_page_state(nid, NR_UNEVICTABLE)), | ||
114 | nid, K(node_page_state(nid, NR_MLOCK)), | ||
115 | #ifdef CONFIG_HIGHMEM | ||
116 | nid, K(i.totalhigh), | ||
117 | nid, K(i.freehigh), | ||
118 | nid, K(i.totalram - i.totalhigh), | ||
119 | nid, K(i.freeram - i.freehigh), | ||
120 | #endif | ||
121 | nid, K(node_page_state(nid, NR_FILE_DIRTY)), | 121 | nid, K(node_page_state(nid, NR_FILE_DIRTY)), |
122 | nid, K(node_page_state(nid, NR_WRITEBACK)), | 122 | nid, K(node_page_state(nid, NR_WRITEBACK)), |
123 | nid, K(node_page_state(nid, NR_FILE_PAGES)), | 123 | nid, K(node_page_state(nid, NR_FILE_PAGES)), |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 273cee1cc77b..dc9641660605 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -9,6 +9,7 @@ FONTMAPFILE = cp437.uni | |||
9 | 9 | ||
10 | obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o | 10 | obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o |
11 | 11 | ||
12 | obj-y += tty_mutex.o | ||
12 | obj-$(CONFIG_LEGACY_PTYS) += pty.o | 13 | obj-$(CONFIG_LEGACY_PTYS) += pty.o |
13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o | 14 | obj-$(CONFIG_UNIX98_PTYS) += pty.o |
14 | obj-y += misc.o | 15 | obj-y += misc.o |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 4f8d60c25a98..a11c8c9ca3d4 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -1072,7 +1072,7 @@ static int get_serial_info(struct async_struct * info, | |||
1072 | if (!retinfo) | 1072 | if (!retinfo) |
1073 | return -EFAULT; | 1073 | return -EFAULT; |
1074 | memset(&tmp, 0, sizeof(tmp)); | 1074 | memset(&tmp, 0, sizeof(tmp)); |
1075 | lock_kernel(); | 1075 | tty_lock(); |
1076 | tmp.type = state->type; | 1076 | tmp.type = state->type; |
1077 | tmp.line = state->line; | 1077 | tmp.line = state->line; |
1078 | tmp.port = state->port; | 1078 | tmp.port = state->port; |
@@ -1083,7 +1083,7 @@ static int get_serial_info(struct async_struct * info, | |||
1083 | tmp.close_delay = state->close_delay; | 1083 | tmp.close_delay = state->close_delay; |
1084 | tmp.closing_wait = state->closing_wait; | 1084 | tmp.closing_wait = state->closing_wait; |
1085 | tmp.custom_divisor = state->custom_divisor; | 1085 | tmp.custom_divisor = state->custom_divisor; |
1086 | unlock_kernel(); | 1086 | tty_unlock(); |
1087 | if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) | 1087 | if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) |
1088 | return -EFAULT; | 1088 | return -EFAULT; |
1089 | return 0; | 1089 | return 0; |
@@ -1100,14 +1100,14 @@ static int set_serial_info(struct async_struct * info, | |||
1100 | if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) | 1100 | if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) |
1101 | return -EFAULT; | 1101 | return -EFAULT; |
1102 | 1102 | ||
1103 | lock_kernel(); | 1103 | tty_lock(); |
1104 | state = info->state; | 1104 | state = info->state; |
1105 | old_state = *state; | 1105 | old_state = *state; |
1106 | 1106 | ||
1107 | change_irq = new_serial.irq != state->irq; | 1107 | change_irq = new_serial.irq != state->irq; |
1108 | change_port = (new_serial.port != state->port); | 1108 | change_port = (new_serial.port != state->port); |
1109 | if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) { | 1109 | if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) { |
1110 | unlock_kernel(); | 1110 | tty_unlock(); |
1111 | return -EINVAL; | 1111 | return -EINVAL; |
1112 | } | 1112 | } |
1113 | 1113 | ||
@@ -1127,7 +1127,7 @@ static int set_serial_info(struct async_struct * info, | |||
1127 | } | 1127 | } |
1128 | 1128 | ||
1129 | if (new_serial.baud_base < 9600) { | 1129 | if (new_serial.baud_base < 9600) { |
1130 | unlock_kernel(); | 1130 | tty_unlock(); |
1131 | return -EINVAL; | 1131 | return -EINVAL; |
1132 | } | 1132 | } |
1133 | 1133 | ||
@@ -1163,7 +1163,7 @@ check_and_exit: | |||
1163 | } | 1163 | } |
1164 | } else | 1164 | } else |
1165 | retval = startup(info); | 1165 | retval = startup(info); |
1166 | unlock_kernel(); | 1166 | tty_unlock(); |
1167 | return retval; | 1167 | return retval; |
1168 | } | 1168 | } |
1169 | 1169 | ||
@@ -1528,6 +1528,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1528 | { | 1528 | { |
1529 | struct async_struct * info = tty->driver_data; | 1529 | struct async_struct * info = tty->driver_data; |
1530 | unsigned long orig_jiffies, char_time; | 1530 | unsigned long orig_jiffies, char_time; |
1531 | int tty_was_locked = tty_locked(); | ||
1531 | int lsr; | 1532 | int lsr; |
1532 | 1533 | ||
1533 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) | 1534 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) |
@@ -1538,7 +1539,12 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1538 | 1539 | ||
1539 | orig_jiffies = jiffies; | 1540 | orig_jiffies = jiffies; |
1540 | 1541 | ||
1541 | lock_kernel(); | 1542 | /* |
1543 | * tty_wait_until_sent is called from lots of places, | ||
1544 | * with or without the BTM. | ||
1545 | */ | ||
1546 | if (!tty_was_locked) | ||
1547 | tty_lock(); | ||
1542 | /* | 1548 | /* |
1543 | * Set the check interval to be 1/5 of the estimated time to | 1549 | * Set the check interval to be 1/5 of the estimated time to |
1544 | * send a single character, and make it at least 1. The check | 1550 | * send a single character, and make it at least 1. The check |
@@ -1579,7 +1585,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1579 | break; | 1585 | break; |
1580 | } | 1586 | } |
1581 | __set_current_state(TASK_RUNNING); | 1587 | __set_current_state(TASK_RUNNING); |
1582 | unlock_kernel(); | 1588 | if (!tty_was_locked) |
1589 | tty_unlock(); | ||
1583 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 1590 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
1584 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | 1591 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); |
1585 | #endif | 1592 | #endif |
@@ -1703,7 +1710,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1703 | printk("block_til_ready blocking: ttys%d, count = %d\n", | 1710 | printk("block_til_ready blocking: ttys%d, count = %d\n", |
1704 | info->line, state->count); | 1711 | info->line, state->count); |
1705 | #endif | 1712 | #endif |
1713 | tty_unlock(); | ||
1706 | schedule(); | 1714 | schedule(); |
1715 | tty_lock(); | ||
1707 | } | 1716 | } |
1708 | __set_current_state(TASK_RUNNING); | 1717 | __set_current_state(TASK_RUNNING); |
1709 | remove_wait_queue(&info->open_wait, &wait); | 1718 | remove_wait_queue(&info->open_wait, &wait); |
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index 555cd93c2ee5..d5fa113afe37 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c | |||
@@ -67,15 +67,15 @@ static void set_led(char state) | |||
67 | 67 | ||
68 | static int briq_panel_open(struct inode *ino, struct file *filep) | 68 | static int briq_panel_open(struct inode *ino, struct file *filep) |
69 | { | 69 | { |
70 | lock_kernel(); | 70 | tty_lock(); |
71 | /* enforce single access, vfd_is_open is protected by BKL */ | 71 | /* enforce single access, vfd_is_open is protected by BKL */ |
72 | if (vfd_is_open) { | 72 | if (vfd_is_open) { |
73 | unlock_kernel(); | 73 | tty_unlock(); |
74 | return -EBUSY; | 74 | return -EBUSY; |
75 | } | 75 | } |
76 | vfd_is_open = 1; | 76 | vfd_is_open = 1; |
77 | 77 | ||
78 | unlock_kernel(); | 78 | tty_unlock(); |
79 | return 0; | 79 | return 0; |
80 | } | 80 | } |
81 | 81 | ||
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 9824b4162904..27aad9422332 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -65,7 +65,6 @@ | |||
65 | #include <linux/tty.h> | 65 | #include <linux/tty.h> |
66 | #include <linux/tty_flip.h> | 66 | #include <linux/tty_flip.h> |
67 | #include <linux/serial.h> | 67 | #include <linux/serial.h> |
68 | #include <linux/smp_lock.h> | ||
69 | #include <linux/major.h> | 68 | #include <linux/major.h> |
70 | #include <linux/string.h> | 69 | #include <linux/string.h> |
71 | #include <linux/fcntl.h> | 70 | #include <linux/fcntl.h> |
@@ -1608,7 +1607,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
1608 | * If the port is the middle of closing, bail out now | 1607 | * If the port is the middle of closing, bail out now |
1609 | */ | 1608 | */ |
1610 | if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { | 1609 | if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { |
1611 | wait_event_interruptible(info->port.close_wait, | 1610 | wait_event_interruptible_tty(info->port.close_wait, |
1612 | !(info->port.flags & ASYNC_CLOSING)); | 1611 | !(info->port.flags & ASYNC_CLOSING)); |
1613 | return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; | 1612 | return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; |
1614 | } | 1613 | } |
@@ -1655,7 +1654,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1655 | return; /* Just in case.... */ | 1654 | return; /* Just in case.... */ |
1656 | 1655 | ||
1657 | orig_jiffies = jiffies; | 1656 | orig_jiffies = jiffies; |
1658 | lock_kernel(); | ||
1659 | /* | 1657 | /* |
1660 | * Set the check interval to be 1/5 of the estimated time to | 1658 | * Set the check interval to be 1/5 of the estimated time to |
1661 | * send a single character, and make it at least 1. The check | 1659 | * send a single character, and make it at least 1. The check |
@@ -1702,7 +1700,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1702 | } | 1700 | } |
1703 | /* Run one more char cycle */ | 1701 | /* Run one more char cycle */ |
1704 | msleep_interruptible(jiffies_to_msecs(char_time * 5)); | 1702 | msleep_interruptible(jiffies_to_msecs(char_time * 5)); |
1705 | unlock_kernel(); | ||
1706 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT | 1703 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT |
1707 | printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); | 1704 | printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); |
1708 | #endif | 1705 | #endif |
@@ -1959,7 +1956,6 @@ static int cy_chars_in_buffer(struct tty_struct *tty) | |||
1959 | int char_count; | 1956 | int char_count; |
1960 | __u32 tx_put, tx_get, tx_bufsize; | 1957 | __u32 tx_put, tx_get, tx_bufsize; |
1961 | 1958 | ||
1962 | lock_kernel(); | ||
1963 | tx_get = readl(&buf_ctrl->tx_get); | 1959 | tx_get = readl(&buf_ctrl->tx_get); |
1964 | tx_put = readl(&buf_ctrl->tx_put); | 1960 | tx_put = readl(&buf_ctrl->tx_put); |
1965 | tx_bufsize = readl(&buf_ctrl->tx_bufsize); | 1961 | tx_bufsize = readl(&buf_ctrl->tx_bufsize); |
@@ -1971,7 +1967,6 @@ static int cy_chars_in_buffer(struct tty_struct *tty) | |||
1971 | printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", | 1967 | printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", |
1972 | info->line, info->xmit_cnt + char_count); | 1968 | info->line, info->xmit_cnt + char_count); |
1973 | #endif | 1969 | #endif |
1974 | unlock_kernel(); | ||
1975 | return info->xmit_cnt + char_count; | 1970 | return info->xmit_cnt + char_count; |
1976 | } | 1971 | } |
1977 | #endif /* Z_EXT_CHARS_IN_BUFFER */ | 1972 | #endif /* Z_EXT_CHARS_IN_BUFFER */ |
@@ -2359,17 +2354,22 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, | |||
2359 | struct serial_struct __user *new_info) | 2354 | struct serial_struct __user *new_info) |
2360 | { | 2355 | { |
2361 | struct serial_struct new_serial; | 2356 | struct serial_struct new_serial; |
2357 | int ret; | ||
2362 | 2358 | ||
2363 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) | 2359 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) |
2364 | return -EFAULT; | 2360 | return -EFAULT; |
2365 | 2361 | ||
2362 | mutex_lock(&info->port.mutex); | ||
2366 | if (!capable(CAP_SYS_ADMIN)) { | 2363 | if (!capable(CAP_SYS_ADMIN)) { |
2367 | if (new_serial.close_delay != info->port.close_delay || | 2364 | if (new_serial.close_delay != info->port.close_delay || |
2368 | new_serial.baud_base != info->baud || | 2365 | new_serial.baud_base != info->baud || |
2369 | (new_serial.flags & ASYNC_FLAGS & | 2366 | (new_serial.flags & ASYNC_FLAGS & |
2370 | ~ASYNC_USR_MASK) != | 2367 | ~ASYNC_USR_MASK) != |
2371 | (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) | 2368 | (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) |
2369 | { | ||
2370 | mutex_unlock(&info->port.mutex); | ||
2372 | return -EPERM; | 2371 | return -EPERM; |
2372 | } | ||
2373 | info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) | | 2373 | info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) | |
2374 | (new_serial.flags & ASYNC_USR_MASK); | 2374 | (new_serial.flags & ASYNC_USR_MASK); |
2375 | info->baud = new_serial.baud_base; | 2375 | info->baud = new_serial.baud_base; |
@@ -2392,10 +2392,12 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, | |||
2392 | check_and_exit: | 2392 | check_and_exit: |
2393 | if (info->port.flags & ASYNC_INITIALIZED) { | 2393 | if (info->port.flags & ASYNC_INITIALIZED) { |
2394 | cy_set_line_char(info, tty); | 2394 | cy_set_line_char(info, tty); |
2395 | return 0; | 2395 | ret = 0; |
2396 | } else { | 2396 | } else { |
2397 | return cy_startup(info, tty); | 2397 | ret = cy_startup(info, tty); |
2398 | } | 2398 | } |
2399 | mutex_unlock(&info->port.mutex); | ||
2400 | return ret; | ||
2399 | } /* set_serial_info */ | 2401 | } /* set_serial_info */ |
2400 | 2402 | ||
2401 | /* | 2403 | /* |
@@ -2438,7 +2440,6 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
2438 | 2440 | ||
2439 | card = info->card; | 2441 | card = info->card; |
2440 | 2442 | ||
2441 | lock_kernel(); | ||
2442 | if (!cy_is_Z(card)) { | 2443 | if (!cy_is_Z(card)) { |
2443 | unsigned long flags; | 2444 | unsigned long flags; |
2444 | int channel = info->line - card->first_line; | 2445 | int channel = info->line - card->first_line; |
@@ -2478,7 +2479,6 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
2478 | ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); | 2479 | ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); |
2479 | } | 2480 | } |
2480 | end: | 2481 | end: |
2481 | unlock_kernel(); | ||
2482 | return result; | 2482 | return result; |
2483 | } /* cy_tiomget */ | 2483 | } /* cy_tiomget */ |
2484 | 2484 | ||
@@ -2696,7 +2696,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
2696 | printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", | 2696 | printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", |
2697 | info->line, cmd, arg); | 2697 | info->line, cmd, arg); |
2698 | #endif | 2698 | #endif |
2699 | lock_kernel(); | ||
2700 | 2699 | ||
2701 | switch (cmd) { | 2700 | switch (cmd) { |
2702 | case CYGETMON: | 2701 | case CYGETMON: |
@@ -2817,7 +2816,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
2817 | default: | 2816 | default: |
2818 | ret_val = -ENOIOCTLCMD; | 2817 | ret_val = -ENOIOCTLCMD; |
2819 | } | 2818 | } |
2820 | unlock_kernel(); | ||
2821 | 2819 | ||
2822 | #ifdef CY_DEBUG_OTHER | 2820 | #ifdef CY_DEBUG_OTHER |
2823 | printk(KERN_DEBUG "cyc:cy_ioctl done\n"); | 2821 | printk(KERN_DEBUG "cyc:cy_ioctl done\n"); |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 6f5ffe1320f7..d9df46aa0fba 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include <linux/ctype.h> | 36 | #include <linux/ctype.h> |
37 | #include <linux/tty.h> | 37 | #include <linux/tty.h> |
38 | #include <linux/tty_flip.h> | 38 | #include <linux/tty_flip.h> |
39 | #include <linux/smp_lock.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/ioport.h> | 40 | #include <linux/ioport.h> |
41 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
42 | #include <linux/uaccess.h> | 42 | #include <linux/uaccess.h> |
@@ -2105,7 +2105,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, | |||
2105 | break; | 2105 | break; |
2106 | case DIGI_SETAW: | 2106 | case DIGI_SETAW: |
2107 | case DIGI_SETAF: | 2107 | case DIGI_SETAF: |
2108 | lock_kernel(); | ||
2109 | if (cmd == DIGI_SETAW) { | 2108 | if (cmd == DIGI_SETAW) { |
2110 | /* Setup an event to indicate when the transmit | 2109 | /* Setup an event to indicate when the transmit |
2111 | buffer empties */ | 2110 | buffer empties */ |
@@ -2118,7 +2117,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, | |||
2118 | if (tty->ldisc->ops->flush_buffer) | 2117 | if (tty->ldisc->ops->flush_buffer) |
2119 | tty->ldisc->ops->flush_buffer(tty); | 2118 | tty->ldisc->ops->flush_buffer(tty); |
2120 | } | 2119 | } |
2121 | unlock_kernel(); | ||
2122 | /* Fall Thru */ | 2120 | /* Fall Thru */ |
2123 | case DIGI_SETA: | 2121 | case DIGI_SETA: |
2124 | if (copy_from_user(&ch->digiext, argp, sizeof(digi_t))) | 2122 | if (copy_from_user(&ch->digiext, argp, sizeof(digi_t))) |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 911e1da6def2..07f3ea38b582 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -1486,7 +1486,9 @@ ip2_open( PTTY tty, struct file *pFile ) | |||
1486 | 1486 | ||
1487 | if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { | 1487 | if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { |
1488 | if ( pCh->flags & ASYNC_CLOSING ) { | 1488 | if ( pCh->flags & ASYNC_CLOSING ) { |
1489 | tty_unlock(); | ||
1489 | schedule(); | 1490 | schedule(); |
1491 | tty_lock(); | ||
1490 | } | 1492 | } |
1491 | if ( tty_hung_up_p(pFile) ) { | 1493 | if ( tty_hung_up_p(pFile) ) { |
1492 | set_current_state( TASK_RUNNING ); | 1494 | set_current_state( TASK_RUNNING ); |
@@ -1548,7 +1550,9 @@ ip2_open( PTTY tty, struct file *pFile ) | |||
1548 | rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); | 1550 | rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); |
1549 | break; | 1551 | break; |
1550 | } | 1552 | } |
1553 | tty_unlock(); | ||
1551 | schedule(); | 1554 | schedule(); |
1555 | tty_lock(); | ||
1552 | } | 1556 | } |
1553 | set_current_state( TASK_RUNNING ); | 1557 | set_current_state( TASK_RUNNING ); |
1554 | remove_wait_queue(&pCh->open_wait, &wait); | 1558 | remove_wait_queue(&pCh->open_wait, &wait); |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 094bdc355b1f..ff68e7c34ce7 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -2176,6 +2176,14 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2176 | info->io.addr_data = res->start; | 2176 | info->io.addr_data = res->start; |
2177 | 2177 | ||
2178 | info->io.regspacing = DEFAULT_REGSPACING; | 2178 | info->io.regspacing = DEFAULT_REGSPACING; |
2179 | res = pnp_get_resource(dev, | ||
2180 | (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? | ||
2181 | IORESOURCE_IO : IORESOURCE_MEM, | ||
2182 | 1); | ||
2183 | if (res) { | ||
2184 | if (res->start > info->io.addr_data) | ||
2185 | info->io.regspacing = res->start - info->io.addr_data; | ||
2186 | } | ||
2179 | info->io.regsize = DEFAULT_REGSPACING; | 2187 | info->io.regsize = DEFAULT_REGSPACING; |
2180 | info->io.regshift = 0; | 2188 | info->io.regshift = 0; |
2181 | 2189 | ||
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 98310e1aae30..c27e9d21fea9 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -124,7 +124,6 @@ | |||
124 | #include <linux/fs.h> | 124 | #include <linux/fs.h> |
125 | #include <linux/sched.h> | 125 | #include <linux/sched.h> |
126 | #include <linux/serial.h> | 126 | #include <linux/serial.h> |
127 | #include <linux/smp_lock.h> | ||
128 | #include <linux/mm.h> | 127 | #include <linux/mm.h> |
129 | #include <linux/interrupt.h> | 128 | #include <linux/interrupt.h> |
130 | #include <linux/timer.h> | 129 | #include <linux/timer.h> |
@@ -872,7 +871,6 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty) | |||
872 | static int isicom_open(struct tty_struct *tty, struct file *filp) | 871 | static int isicom_open(struct tty_struct *tty, struct file *filp) |
873 | { | 872 | { |
874 | struct isi_port *port; | 873 | struct isi_port *port; |
875 | struct isi_board *card; | ||
876 | struct tty_port *tport; | 874 | struct tty_port *tport; |
877 | 875 | ||
878 | tport = isicom_find_port(tty); | 876 | tport = isicom_find_port(tty); |
@@ -1118,8 +1116,7 @@ static int isicom_set_serial_info(struct tty_struct *tty, | |||
1118 | if (copy_from_user(&newinfo, info, sizeof(newinfo))) | 1116 | if (copy_from_user(&newinfo, info, sizeof(newinfo))) |
1119 | return -EFAULT; | 1117 | return -EFAULT; |
1120 | 1118 | ||
1121 | lock_kernel(); | 1119 | mutex_lock(&port->port.mutex); |
1122 | |||
1123 | reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) != | 1120 | reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) != |
1124 | (newinfo.flags & ASYNC_SPD_MASK)); | 1121 | (newinfo.flags & ASYNC_SPD_MASK)); |
1125 | 1122 | ||
@@ -1128,7 +1125,7 @@ static int isicom_set_serial_info(struct tty_struct *tty, | |||
1128 | (newinfo.closing_wait != port->port.closing_wait) || | 1125 | (newinfo.closing_wait != port->port.closing_wait) || |
1129 | ((newinfo.flags & ~ASYNC_USR_MASK) != | 1126 | ((newinfo.flags & ~ASYNC_USR_MASK) != |
1130 | (port->port.flags & ~ASYNC_USR_MASK))) { | 1127 | (port->port.flags & ~ASYNC_USR_MASK))) { |
1131 | unlock_kernel(); | 1128 | mutex_unlock(&port->port.mutex); |
1132 | return -EPERM; | 1129 | return -EPERM; |
1133 | } | 1130 | } |
1134 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | 1131 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | |
@@ -1145,7 +1142,7 @@ static int isicom_set_serial_info(struct tty_struct *tty, | |||
1145 | isicom_config_port(tty); | 1142 | isicom_config_port(tty); |
1146 | spin_unlock_irqrestore(&port->card->card_lock, flags); | 1143 | spin_unlock_irqrestore(&port->card->card_lock, flags); |
1147 | } | 1144 | } |
1148 | unlock_kernel(); | 1145 | mutex_unlock(&port->port.mutex); |
1149 | return 0; | 1146 | return 0; |
1150 | } | 1147 | } |
1151 | 1148 | ||
@@ -1154,7 +1151,7 @@ static int isicom_get_serial_info(struct isi_port *port, | |||
1154 | { | 1151 | { |
1155 | struct serial_struct out_info; | 1152 | struct serial_struct out_info; |
1156 | 1153 | ||
1157 | lock_kernel(); | 1154 | mutex_lock(&port->port.mutex); |
1158 | memset(&out_info, 0, sizeof(out_info)); | 1155 | memset(&out_info, 0, sizeof(out_info)); |
1159 | /* out_info.type = ? */ | 1156 | /* out_info.type = ? */ |
1160 | out_info.line = port - isi_ports; | 1157 | out_info.line = port - isi_ports; |
@@ -1164,7 +1161,7 @@ static int isicom_get_serial_info(struct isi_port *port, | |||
1164 | /* out_info.baud_base = ? */ | 1161 | /* out_info.baud_base = ? */ |
1165 | out_info.close_delay = port->port.close_delay; | 1162 | out_info.close_delay = port->port.close_delay; |
1166 | out_info.closing_wait = port->port.closing_wait; | 1163 | out_info.closing_wait = port->port.closing_wait; |
1167 | unlock_kernel(); | 1164 | mutex_unlock(&port->port.mutex); |
1168 | if (copy_to_user(info, &out_info, sizeof(out_info))) | 1165 | if (copy_to_user(info, &out_info, sizeof(out_info))) |
1169 | return -EFAULT; | 1166 | return -EFAULT; |
1170 | return 0; | 1167 | return 0; |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 4e395c956a09..be28391adb79 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -203,9 +203,9 @@ static int stli_shared; | |||
203 | * the board has been detected, and whether it is actually running a slave | 203 | * the board has been detected, and whether it is actually running a slave |
204 | * or not. | 204 | * or not. |
205 | */ | 205 | */ |
206 | #define BST_FOUND 0x1 | 206 | #define BST_FOUND 0 |
207 | #define BST_STARTED 0x2 | 207 | #define BST_STARTED 1 |
208 | #define BST_PROBED 0x4 | 208 | #define BST_PROBED 2 |
209 | 209 | ||
210 | /* | 210 | /* |
211 | * Define the set of port state flags. These are marked for internal | 211 | * Define the set of port state flags. These are marked for internal |
@@ -816,7 +816,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
816 | brdp = stli_brds[brdnr]; | 816 | brdp = stli_brds[brdnr]; |
817 | if (brdp == NULL) | 817 | if (brdp == NULL) |
818 | return -ENODEV; | 818 | return -ENODEV; |
819 | if ((brdp->state & BST_STARTED) == 0) | 819 | if (!test_bit(BST_STARTED, &brdp->state)) |
820 | return -ENODEV; | 820 | return -ENODEV; |
821 | portnr = MINOR2PORT(minordev); | 821 | portnr = MINOR2PORT(minordev); |
822 | if (portnr > brdp->nrports) | 822 | if (portnr > brdp->nrports) |
@@ -954,7 +954,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l | |||
954 | * order of opens and closes may not be preserved across shared | 954 | * order of opens and closes may not be preserved across shared |
955 | * memory, so we must wait until it is complete. | 955 | * memory, so we must wait until it is complete. |
956 | */ | 956 | */ |
957 | wait_event_interruptible(portp->raw_wait, | 957 | wait_event_interruptible_tty(portp->raw_wait, |
958 | !test_bit(ST_CLOSING, &portp->state)); | 958 | !test_bit(ST_CLOSING, &portp->state)); |
959 | if (signal_pending(current)) { | 959 | if (signal_pending(current)) { |
960 | return -ERESTARTSYS; | 960 | return -ERESTARTSYS; |
@@ -989,7 +989,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l | |||
989 | set_bit(ST_OPENING, &portp->state); | 989 | set_bit(ST_OPENING, &portp->state); |
990 | spin_unlock_irqrestore(&brd_lock, flags); | 990 | spin_unlock_irqrestore(&brd_lock, flags); |
991 | 991 | ||
992 | wait_event_interruptible(portp->raw_wait, | 992 | wait_event_interruptible_tty(portp->raw_wait, |
993 | !test_bit(ST_OPENING, &portp->state)); | 993 | !test_bit(ST_OPENING, &portp->state)); |
994 | if (signal_pending(current)) | 994 | if (signal_pending(current)) |
995 | rc = -ERESTARTSYS; | 995 | rc = -ERESTARTSYS; |
@@ -1020,7 +1020,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned | |||
1020 | * occurs on this port. | 1020 | * occurs on this port. |
1021 | */ | 1021 | */ |
1022 | if (wait) { | 1022 | if (wait) { |
1023 | wait_event_interruptible(portp->raw_wait, | 1023 | wait_event_interruptible_tty(portp->raw_wait, |
1024 | !test_bit(ST_CLOSING, &portp->state)); | 1024 | !test_bit(ST_CLOSING, &portp->state)); |
1025 | if (signal_pending(current)) { | 1025 | if (signal_pending(current)) { |
1026 | return -ERESTARTSYS; | 1026 | return -ERESTARTSYS; |
@@ -1052,7 +1052,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned | |||
1052 | * to come back. | 1052 | * to come back. |
1053 | */ | 1053 | */ |
1054 | rc = 0; | 1054 | rc = 0; |
1055 | wait_event_interruptible(portp->raw_wait, | 1055 | wait_event_interruptible_tty(portp->raw_wait, |
1056 | !test_bit(ST_CLOSING, &portp->state)); | 1056 | !test_bit(ST_CLOSING, &portp->state)); |
1057 | if (signal_pending(current)) | 1057 | if (signal_pending(current)) |
1058 | rc = -ERESTARTSYS; | 1058 | rc = -ERESTARTSYS; |
@@ -1073,6 +1073,10 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned | |||
1073 | 1073 | ||
1074 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) | 1074 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) |
1075 | { | 1075 | { |
1076 | /* | ||
1077 | * no need for wait_event_tty because clearing ST_CMDING cannot block | ||
1078 | * on BTM | ||
1079 | */ | ||
1076 | wait_event_interruptible(portp->raw_wait, | 1080 | wait_event_interruptible(portp->raw_wait, |
1077 | !test_bit(ST_CMDING, &portp->state)); | 1081 | !test_bit(ST_CMDING, &portp->state)); |
1078 | if (signal_pending(current)) | 1082 | if (signal_pending(current)) |
@@ -1846,7 +1850,7 @@ static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stlip | |||
1846 | rc = stli_portcmdstats(NULL, portp); | 1850 | rc = stli_portcmdstats(NULL, portp); |
1847 | 1851 | ||
1848 | uart = "UNKNOWN"; | 1852 | uart = "UNKNOWN"; |
1849 | if (brdp->state & BST_STARTED) { | 1853 | if (test_bit(BST_STARTED, &brdp->state)) { |
1850 | switch (stli_comstats.hwid) { | 1854 | switch (stli_comstats.hwid) { |
1851 | case 0: uart = "2681"; break; | 1855 | case 0: uart = "2681"; break; |
1852 | case 1: uart = "SC26198"; break; | 1856 | case 1: uart = "SC26198"; break; |
@@ -1855,7 +1859,7 @@ static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stlip | |||
1855 | } | 1859 | } |
1856 | seq_printf(m, "%d: uart:%s ", portnr, uart); | 1860 | seq_printf(m, "%d: uart:%s ", portnr, uart); |
1857 | 1861 | ||
1858 | if ((brdp->state & BST_STARTED) && (rc >= 0)) { | 1862 | if (test_bit(BST_STARTED, &brdp->state) && rc >= 0) { |
1859 | char sep; | 1863 | char sep; |
1860 | 1864 | ||
1861 | seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal, | 1865 | seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal, |
@@ -2355,7 +2359,7 @@ static void stli_poll(unsigned long arg) | |||
2355 | brdp = stli_brds[brdnr]; | 2359 | brdp = stli_brds[brdnr]; |
2356 | if (brdp == NULL) | 2360 | if (brdp == NULL) |
2357 | continue; | 2361 | continue; |
2358 | if ((brdp->state & BST_STARTED) == 0) | 2362 | if (!test_bit(BST_STARTED, &brdp->state)) |
2359 | continue; | 2363 | continue; |
2360 | 2364 | ||
2361 | spin_lock(&brd_lock); | 2365 | spin_lock(&brd_lock); |
@@ -3140,7 +3144,7 @@ static int stli_initecp(struct stlibrd *brdp) | |||
3140 | } | 3144 | } |
3141 | 3145 | ||
3142 | 3146 | ||
3143 | brdp->state |= BST_FOUND; | 3147 | set_bit(BST_FOUND, &brdp->state); |
3144 | return 0; | 3148 | return 0; |
3145 | err_unmap: | 3149 | err_unmap: |
3146 | iounmap(brdp->membase); | 3150 | iounmap(brdp->membase); |
@@ -3297,7 +3301,7 @@ static int stli_initonb(struct stlibrd *brdp) | |||
3297 | brdp->panels[0] = brdp->nrports; | 3301 | brdp->panels[0] = brdp->nrports; |
3298 | 3302 | ||
3299 | 3303 | ||
3300 | brdp->state |= BST_FOUND; | 3304 | set_bit(BST_FOUND, &brdp->state); |
3301 | return 0; | 3305 | return 0; |
3302 | err_unmap: | 3306 | err_unmap: |
3303 | iounmap(brdp->membase); | 3307 | iounmap(brdp->membase); |
@@ -3407,7 +3411,7 @@ stli_donestartup: | |||
3407 | spin_unlock_irqrestore(&brd_lock, flags); | 3411 | spin_unlock_irqrestore(&brd_lock, flags); |
3408 | 3412 | ||
3409 | if (rc == 0) | 3413 | if (rc == 0) |
3410 | brdp->state |= BST_STARTED; | 3414 | set_bit(BST_STARTED, &brdp->state); |
3411 | 3415 | ||
3412 | if (! stli_timeron) { | 3416 | if (! stli_timeron) { |
3413 | stli_timeron++; | 3417 | stli_timeron++; |
@@ -3710,7 +3714,7 @@ static int __devinit stli_pciprobe(struct pci_dev *pdev, | |||
3710 | if (retval) | 3714 | if (retval) |
3711 | goto err_null; | 3715 | goto err_null; |
3712 | 3716 | ||
3713 | brdp->state |= BST_PROBED; | 3717 | set_bit(BST_PROBED, &brdp->state); |
3714 | pci_set_drvdata(pdev, brdp); | 3718 | pci_set_drvdata(pdev, brdp); |
3715 | 3719 | ||
3716 | EBRDENABLE(brdp); | 3720 | EBRDENABLE(brdp); |
@@ -3841,7 +3845,7 @@ static int __init stli_initbrds(void) | |||
3841 | brdp = stli_brds[i]; | 3845 | brdp = stli_brds[i]; |
3842 | if (brdp == NULL) | 3846 | if (brdp == NULL) |
3843 | continue; | 3847 | continue; |
3844 | if (brdp->state & BST_FOUND) { | 3848 | if (test_bit(BST_FOUND, &brdp->state)) { |
3845 | EBRDENABLE(brdp); | 3849 | EBRDENABLE(brdp); |
3846 | brdp->enable = NULL; | 3850 | brdp->enable = NULL; |
3847 | brdp->disable = NULL; | 3851 | brdp->disable = NULL; |
@@ -4011,6 +4015,7 @@ static int stli_getbrdstats(combrd_t __user *bp) | |||
4011 | return -ENODEV; | 4015 | return -ENODEV; |
4012 | 4016 | ||
4013 | memset(&stli_brdstats, 0, sizeof(combrd_t)); | 4017 | memset(&stli_brdstats, 0, sizeof(combrd_t)); |
4018 | |||
4014 | stli_brdstats.brd = brdp->brdnr; | 4019 | stli_brdstats.brd = brdp->brdnr; |
4015 | stli_brdstats.type = brdp->brdtype; | 4020 | stli_brdstats.type = brdp->brdtype; |
4016 | stli_brdstats.hwid = 0; | 4021 | stli_brdstats.hwid = 0; |
@@ -4076,10 +4081,13 @@ static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp) | |||
4076 | if (brdp == NULL) | 4081 | if (brdp == NULL) |
4077 | return -ENODEV; | 4082 | return -ENODEV; |
4078 | 4083 | ||
4079 | if (brdp->state & BST_STARTED) { | 4084 | mutex_lock(&portp->port.mutex); |
4085 | if (test_bit(BST_STARTED, &brdp->state)) { | ||
4080 | if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, | 4086 | if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, |
4081 | &stli_cdkstats, sizeof(asystats_t), 1)) < 0) | 4087 | &stli_cdkstats, sizeof(asystats_t), 1)) < 0) { |
4088 | mutex_unlock(&portp->port.mutex); | ||
4082 | return rc; | 4089 | return rc; |
4090 | } | ||
4083 | } else { | 4091 | } else { |
4084 | memset(&stli_cdkstats, 0, sizeof(asystats_t)); | 4092 | memset(&stli_cdkstats, 0, sizeof(asystats_t)); |
4085 | } | 4093 | } |
@@ -4124,6 +4132,7 @@ static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp) | |||
4124 | stli_comstats.modem = stli_cdkstats.dcdcnt; | 4132 | stli_comstats.modem = stli_cdkstats.dcdcnt; |
4125 | stli_comstats.hwid = stli_cdkstats.hwid; | 4133 | stli_comstats.hwid = stli_cdkstats.hwid; |
4126 | stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals); | 4134 | stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals); |
4135 | mutex_unlock(&portp->port.mutex); | ||
4127 | 4136 | ||
4128 | return 0; | 4137 | return 0; |
4129 | } | 4138 | } |
@@ -4186,15 +4195,20 @@ static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp) | |||
4186 | if (!brdp) | 4195 | if (!brdp) |
4187 | return -ENODEV; | 4196 | return -ENODEV; |
4188 | 4197 | ||
4189 | if (brdp->state & BST_STARTED) { | 4198 | mutex_lock(&portp->port.mutex); |
4190 | if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) | 4199 | |
4200 | if (test_bit(BST_STARTED, &brdp->state)) { | ||
4201 | if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) { | ||
4202 | mutex_unlock(&portp->port.mutex); | ||
4191 | return rc; | 4203 | return rc; |
4204 | } | ||
4192 | } | 4205 | } |
4193 | 4206 | ||
4194 | memset(&stli_comstats, 0, sizeof(comstats_t)); | 4207 | memset(&stli_comstats, 0, sizeof(comstats_t)); |
4195 | stli_comstats.brd = portp->brdnr; | 4208 | stli_comstats.brd = portp->brdnr; |
4196 | stli_comstats.panel = portp->panelnr; | 4209 | stli_comstats.panel = portp->panelnr; |
4197 | stli_comstats.port = portp->portnr; | 4210 | stli_comstats.port = portp->portnr; |
4211 | mutex_unlock(&portp->port.mutex); | ||
4198 | 4212 | ||
4199 | if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t))) | 4213 | if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t))) |
4200 | return -EFAULT; | 4214 | return -EFAULT; |
@@ -4266,8 +4280,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4266 | done = 0; | 4280 | done = 0; |
4267 | rc = 0; | 4281 | rc = 0; |
4268 | 4282 | ||
4269 | lock_kernel(); | ||
4270 | |||
4271 | switch (cmd) { | 4283 | switch (cmd) { |
4272 | case COM_GETPORTSTATS: | 4284 | case COM_GETPORTSTATS: |
4273 | rc = stli_getportstats(NULL, NULL, argp); | 4285 | rc = stli_getportstats(NULL, NULL, argp); |
@@ -4290,8 +4302,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4290 | done++; | 4302 | done++; |
4291 | break; | 4303 | break; |
4292 | } | 4304 | } |
4293 | unlock_kernel(); | ||
4294 | |||
4295 | if (done) | 4305 | if (done) |
4296 | return rc; | 4306 | return rc; |
4297 | 4307 | ||
@@ -4308,8 +4318,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4308 | if (brdp->state == 0) | 4318 | if (brdp->state == 0) |
4309 | return -ENODEV; | 4319 | return -ENODEV; |
4310 | 4320 | ||
4311 | lock_kernel(); | ||
4312 | |||
4313 | switch (cmd) { | 4321 | switch (cmd) { |
4314 | case STL_BINTR: | 4322 | case STL_BINTR: |
4315 | EBRDINTR(brdp); | 4323 | EBRDINTR(brdp); |
@@ -4318,10 +4326,10 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4318 | rc = stli_startbrd(brdp); | 4326 | rc = stli_startbrd(brdp); |
4319 | break; | 4327 | break; |
4320 | case STL_BSTOP: | 4328 | case STL_BSTOP: |
4321 | brdp->state &= ~BST_STARTED; | 4329 | clear_bit(BST_STARTED, &brdp->state); |
4322 | break; | 4330 | break; |
4323 | case STL_BRESET: | 4331 | case STL_BRESET: |
4324 | brdp->state &= ~BST_STARTED; | 4332 | clear_bit(BST_STARTED, &brdp->state); |
4325 | EBRDRESET(brdp); | 4333 | EBRDRESET(brdp); |
4326 | if (stli_shared == 0) { | 4334 | if (stli_shared == 0) { |
4327 | if (brdp->reenable != NULL) | 4335 | if (brdp->reenable != NULL) |
@@ -4332,7 +4340,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4332 | rc = -ENOIOCTLCMD; | 4340 | rc = -ENOIOCTLCMD; |
4333 | break; | 4341 | break; |
4334 | } | 4342 | } |
4335 | unlock_kernel(); | ||
4336 | return rc; | 4343 | return rc; |
4337 | } | 4344 | } |
4338 | 4345 | ||
@@ -4378,7 +4385,8 @@ static void istallion_cleanup_isa(void) | |||
4378 | unsigned int j; | 4385 | unsigned int j; |
4379 | 4386 | ||
4380 | for (j = 0; (j < stli_nrbrds); j++) { | 4387 | for (j = 0; (j < stli_nrbrds); j++) { |
4381 | if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED)) | 4388 | if ((brdp = stli_brds[j]) == NULL || |
4389 | test_bit(BST_PROBED, &brdp->state)) | ||
4382 | continue; | 4390 | continue; |
4383 | 4391 | ||
4384 | stli_cleanup_ports(brdp); | 4392 | stli_cleanup_ports(brdp); |
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 25be2102a60a..a7ca75212bfe 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -299,7 +299,7 @@ int kbd_rate(struct kbd_repeat *rep) | |||
299 | */ | 299 | */ |
300 | static void put_queue(struct vc_data *vc, int ch) | 300 | static void put_queue(struct vc_data *vc, int ch) |
301 | { | 301 | { |
302 | struct tty_struct *tty = vc->vc_tty; | 302 | struct tty_struct *tty = vc->port.tty; |
303 | 303 | ||
304 | if (tty) { | 304 | if (tty) { |
305 | tty_insert_flip_char(tty, ch, 0); | 305 | tty_insert_flip_char(tty, ch, 0); |
@@ -309,7 +309,7 @@ static void put_queue(struct vc_data *vc, int ch) | |||
309 | 309 | ||
310 | static void puts_queue(struct vc_data *vc, char *cp) | 310 | static void puts_queue(struct vc_data *vc, char *cp) |
311 | { | 311 | { |
312 | struct tty_struct *tty = vc->vc_tty; | 312 | struct tty_struct *tty = vc->port.tty; |
313 | 313 | ||
314 | if (!tty) | 314 | if (!tty) |
315 | return; | 315 | return; |
@@ -485,7 +485,7 @@ static void fn_show_ptregs(struct vc_data *vc) | |||
485 | 485 | ||
486 | static void fn_hold(struct vc_data *vc) | 486 | static void fn_hold(struct vc_data *vc) |
487 | { | 487 | { |
488 | struct tty_struct *tty = vc->vc_tty; | 488 | struct tty_struct *tty = vc->port.tty; |
489 | 489 | ||
490 | if (rep || !tty) | 490 | if (rep || !tty) |
491 | return; | 491 | return; |
@@ -563,7 +563,7 @@ static void fn_inc_console(struct vc_data *vc) | |||
563 | 563 | ||
564 | static void fn_send_intr(struct vc_data *vc) | 564 | static void fn_send_intr(struct vc_data *vc) |
565 | { | 565 | { |
566 | struct tty_struct *tty = vc->vc_tty; | 566 | struct tty_struct *tty = vc->port.tty; |
567 | 567 | ||
568 | if (!tty) | 568 | if (!tty) |
569 | return; | 569 | return; |
@@ -1162,7 +1162,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
1162 | struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down }; | 1162 | struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down }; |
1163 | int rc; | 1163 | int rc; |
1164 | 1164 | ||
1165 | tty = vc->vc_tty; | 1165 | tty = vc->port.tty; |
1166 | 1166 | ||
1167 | if (tty && (!tty->driver_data)) { | 1167 | if (tty && (!tty->driver_data)) { |
1168 | /* No driver data? Strange. Okay we fix it then. */ | 1168 | /* No driver data? Strange. Okay we fix it then. */ |
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index cd650ca8c679..abdafd488980 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c | |||
@@ -242,7 +242,7 @@ int misc_deregister(struct miscdevice *misc) | |||
242 | { | 242 | { |
243 | int i = DYNAMIC_MINORS - misc->minor - 1; | 243 | int i = DYNAMIC_MINORS - misc->minor - 1; |
244 | 244 | ||
245 | if (list_empty(&misc->list)) | 245 | if (WARN_ON(list_empty(&misc->list))) |
246 | return -EINVAL; | 246 | return -EINVAL; |
247 | 247 | ||
248 | mutex_lock(&misc_mtx); | 248 | mutex_lock(&misc_mtx); |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index d2692d443f7b..3fc89da856ae 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -2193,7 +2193,7 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port | |||
2193 | port->mon_data.up_txcnt += (cnt - port->xmit_cnt); | 2193 | port->mon_data.up_txcnt += (cnt - port->xmit_cnt); |
2194 | port->icount.tx += (cnt - port->xmit_cnt); | 2194 | port->icount.tx += (cnt - port->xmit_cnt); |
2195 | 2195 | ||
2196 | if (port->xmit_cnt < WAKEUP_CHARS && tty) | 2196 | if (port->xmit_cnt < WAKEUP_CHARS) |
2197 | tty_wakeup(tty); | 2197 | tty_wakeup(tty); |
2198 | 2198 | ||
2199 | if (port->xmit_cnt <= 0) { | 2199 | if (port->xmit_cnt <= 0) { |
diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c index e4089c432f15..099105e0894e 100644 --- a/drivers/char/n_gsm.c +++ b/drivers/char/n_gsm.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <linux/sched.h> | 43 | #include <linux/sched.h> |
44 | #include <linux/interrupt.h> | 44 | #include <linux/interrupt.h> |
45 | #include <linux/tty.h> | 45 | #include <linux/tty.h> |
46 | #include <linux/timer.h> | ||
47 | #include <linux/ctype.h> | 46 | #include <linux/ctype.h> |
48 | #include <linux/mm.h> | 47 | #include <linux/mm.h> |
49 | #include <linux/string.h> | 48 | #include <linux/string.h> |
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index c68118efad84..47d32281032c 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c | |||
@@ -598,18 +598,18 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | |||
598 | return -EFAULT; | 598 | return -EFAULT; |
599 | } | 599 | } |
600 | 600 | ||
601 | lock_kernel(); | 601 | tty_lock(); |
602 | 602 | ||
603 | for (;;) { | 603 | for (;;) { |
604 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { | 604 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { |
605 | unlock_kernel(); | 605 | tty_unlock(); |
606 | return -EIO; | 606 | return -EIO; |
607 | } | 607 | } |
608 | 608 | ||
609 | n_hdlc = tty2n_hdlc (tty); | 609 | n_hdlc = tty2n_hdlc (tty); |
610 | if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || | 610 | if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || |
611 | tty != n_hdlc->tty) { | 611 | tty != n_hdlc->tty) { |
612 | unlock_kernel(); | 612 | tty_unlock(); |
613 | return 0; | 613 | return 0; |
614 | } | 614 | } |
615 | 615 | ||
@@ -619,13 +619,13 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | |||
619 | 619 | ||
620 | /* no data */ | 620 | /* no data */ |
621 | if (file->f_flags & O_NONBLOCK) { | 621 | if (file->f_flags & O_NONBLOCK) { |
622 | unlock_kernel(); | 622 | tty_unlock(); |
623 | return -EAGAIN; | 623 | return -EAGAIN; |
624 | } | 624 | } |
625 | 625 | ||
626 | interruptible_sleep_on (&tty->read_wait); | 626 | interruptible_sleep_on (&tty->read_wait); |
627 | if (signal_pending(current)) { | 627 | if (signal_pending(current)) { |
628 | unlock_kernel(); | 628 | tty_unlock(); |
629 | return -EINTR; | 629 | return -EINTR; |
630 | } | 630 | } |
631 | } | 631 | } |
@@ -648,7 +648,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | |||
648 | kfree(rbuf); | 648 | kfree(rbuf); |
649 | else | 649 | else |
650 | n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); | 650 | n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); |
651 | unlock_kernel(); | 651 | tty_unlock(); |
652 | return ret; | 652 | return ret; |
653 | 653 | ||
654 | } /* end of n_hdlc_tty_read() */ | 654 | } /* end of n_hdlc_tty_read() */ |
@@ -691,7 +691,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, | |||
691 | count = maxframe; | 691 | count = maxframe; |
692 | } | 692 | } |
693 | 693 | ||
694 | lock_kernel(); | 694 | tty_lock(); |
695 | 695 | ||
696 | add_wait_queue(&tty->write_wait, &wait); | 696 | add_wait_queue(&tty->write_wait, &wait); |
697 | set_current_state(TASK_INTERRUPTIBLE); | 697 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -731,7 +731,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, | |||
731 | n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); | 731 | n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); |
732 | n_hdlc_send_frames(n_hdlc,tty); | 732 | n_hdlc_send_frames(n_hdlc,tty); |
733 | } | 733 | } |
734 | unlock_kernel(); | 734 | tty_unlock(); |
735 | return error; | 735 | return error; |
736 | 736 | ||
737 | } /* end of n_hdlc_tty_write() */ | 737 | } /* end of n_hdlc_tty_write() */ |
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index c1d8b54c816d..a98290d7a2c5 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -1067,7 +1067,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1067 | 1067 | ||
1068 | TRACE_L("read()"); | 1068 | TRACE_L("read()"); |
1069 | 1069 | ||
1070 | lock_kernel(); | 1070 | tty_lock(); |
1071 | 1071 | ||
1072 | pClient = findClient(pInfo, task_pid(current)); | 1072 | pClient = findClient(pInfo, task_pid(current)); |
1073 | if (pClient) { | 1073 | if (pClient) { |
@@ -1079,7 +1079,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1079 | goto unlock; | 1079 | goto unlock; |
1080 | } | 1080 | } |
1081 | /* block until there is a message: */ | 1081 | /* block until there is a message: */ |
1082 | wait_event_interruptible(pInfo->read_wait, | 1082 | wait_event_interruptible_tty(pInfo->read_wait, |
1083 | (pMsg = remove_msg(pInfo, pClient))); | 1083 | (pMsg = remove_msg(pInfo, pClient))); |
1084 | } | 1084 | } |
1085 | 1085 | ||
@@ -1109,7 +1109,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1109 | } | 1109 | } |
1110 | ret = -EPERM; | 1110 | ret = -EPERM; |
1111 | unlock: | 1111 | unlock: |
1112 | unlock_kernel(); | 1112 | tty_unlock(); |
1113 | return ret; | 1113 | return ret; |
1114 | } | 1114 | } |
1115 | 1115 | ||
@@ -1158,7 +1158,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | |||
1158 | pHeader->locks = 0; | 1158 | pHeader->locks = 0; |
1159 | pHeader->owner = NULL; | 1159 | pHeader->owner = NULL; |
1160 | 1160 | ||
1161 | lock_kernel(); | 1161 | tty_lock(); |
1162 | 1162 | ||
1163 | pClient = findClient(pInfo, task_pid(current)); | 1163 | pClient = findClient(pInfo, task_pid(current)); |
1164 | if (pClient) { | 1164 | if (pClient) { |
@@ -1177,7 +1177,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | |||
1177 | add_tx_queue(pInfo, pHeader); | 1177 | add_tx_queue(pInfo, pHeader); |
1178 | trigger_transmit(pInfo); | 1178 | trigger_transmit(pInfo); |
1179 | 1179 | ||
1180 | unlock_kernel(); | 1180 | tty_unlock(); |
1181 | 1181 | ||
1182 | return 0; | 1182 | return 0; |
1183 | } | 1183 | } |
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index bdae8327143c..428f4fe0b5f7 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -1102,6 +1102,11 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | |||
1102 | if (I_IUCLC(tty) && L_IEXTEN(tty)) | 1102 | if (I_IUCLC(tty) && L_IEXTEN(tty)) |
1103 | c = tolower(c); | 1103 | c = tolower(c); |
1104 | 1104 | ||
1105 | if (L_EXTPROC(tty)) { | ||
1106 | put_tty_queue(c, tty); | ||
1107 | return; | ||
1108 | } | ||
1109 | |||
1105 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && | 1110 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && |
1106 | I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) && | 1111 | I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) && |
1107 | c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) { | 1112 | c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) { |
@@ -1409,7 +1414,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1409 | 1414 | ||
1410 | n_tty_set_room(tty); | 1415 | n_tty_set_room(tty); |
1411 | 1416 | ||
1412 | if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) { | 1417 | if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) || |
1418 | L_EXTPROC(tty)) { | ||
1413 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); | 1419 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); |
1414 | if (waitqueue_active(&tty->read_wait)) | 1420 | if (waitqueue_active(&tty->read_wait)) |
1415 | wake_up_interruptible(&tty->read_wait); | 1421 | wake_up_interruptible(&tty->read_wait); |
@@ -1585,7 +1591,7 @@ static int n_tty_open(struct tty_struct *tty) | |||
1585 | static inline int input_available_p(struct tty_struct *tty, int amt) | 1591 | static inline int input_available_p(struct tty_struct *tty, int amt) |
1586 | { | 1592 | { |
1587 | tty_flush_to_ldisc(tty); | 1593 | tty_flush_to_ldisc(tty); |
1588 | if (tty->icanon) { | 1594 | if (tty->icanon && !L_EXTPROC(tty)) { |
1589 | if (tty->canon_data) | 1595 | if (tty->canon_data) |
1590 | return 1; | 1596 | return 1; |
1591 | } else if (tty->read_cnt >= (amt ? amt : 1)) | 1597 | } else if (tty->read_cnt >= (amt ? amt : 1)) |
@@ -1632,6 +1638,11 @@ static int copy_from_read_buf(struct tty_struct *tty, | |||
1632 | spin_lock_irqsave(&tty->read_lock, flags); | 1638 | spin_lock_irqsave(&tty->read_lock, flags); |
1633 | tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); | 1639 | tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); |
1634 | tty->read_cnt -= n; | 1640 | tty->read_cnt -= n; |
1641 | /* Turn single EOF into zero-length read */ | ||
1642 | if (L_EXTPROC(tty) && tty->icanon && n == 1) { | ||
1643 | if (!tty->read_cnt && (*b)[n-1] == EOF_CHAR(tty)) | ||
1644 | n--; | ||
1645 | } | ||
1635 | spin_unlock_irqrestore(&tty->read_lock, flags); | 1646 | spin_unlock_irqrestore(&tty->read_lock, flags); |
1636 | *b += n; | 1647 | *b += n; |
1637 | *nr -= n; | 1648 | *nr -= n; |
@@ -1812,7 +1823,7 @@ do_it_again: | |||
1812 | nr--; | 1823 | nr--; |
1813 | } | 1824 | } |
1814 | 1825 | ||
1815 | if (tty->icanon) { | 1826 | if (tty->icanon && !L_EXTPROC(tty)) { |
1816 | /* N.B. avoid overrun if nr == 0 */ | 1827 | /* N.B. avoid overrun if nr == 0 */ |
1817 | while (nr && tty->read_cnt) { | 1828 | while (nr && tty->read_cnt) { |
1818 | int eol; | 1829 | int eol; |
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index a6638003f530..18af923093c3 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c | |||
@@ -1611,6 +1611,8 @@ static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
1611 | ret = tty_init_termios(tty); | 1611 | ret = tty_init_termios(tty); |
1612 | if (ret == 0) { | 1612 | if (ret == 0) { |
1613 | tty_driver_kref_get(driver); | 1613 | tty_driver_kref_get(driver); |
1614 | tty->count++; | ||
1615 | tty->driver_data = port; | ||
1614 | driver->ttys[tty->index] = tty; | 1616 | driver->ttys[tty->index] = tty; |
1615 | } | 1617 | } |
1616 | return ret; | 1618 | return ret; |
@@ -1639,7 +1641,7 @@ static int ntty_activate(struct tty_port *tport, struct tty_struct *tty) | |||
1639 | 1641 | ||
1640 | static int ntty_open(struct tty_struct *tty, struct file *filp) | 1642 | static int ntty_open(struct tty_struct *tty, struct file *filp) |
1641 | { | 1643 | { |
1642 | struct port *port = get_port_by_tty(tty); | 1644 | struct port *port = tty->driver_data; |
1643 | return tty_port_open(&port->port, tty, filp); | 1645 | return tty_port_open(&port->port, tty, filp); |
1644 | } | 1646 | } |
1645 | 1647 | ||
diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c index 65920163f53d..9fe538347932 100644 --- a/drivers/char/pcmcia/ipwireless/network.c +++ b/drivers/char/pcmcia/ipwireless/network.c | |||
@@ -239,7 +239,7 @@ static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel, | |||
239 | return err; | 239 | return err; |
240 | } | 240 | } |
241 | 241 | ||
242 | static struct ppp_channel_ops ipwireless_ppp_channel_ops = { | 242 | static const struct ppp_channel_ops ipwireless_ppp_channel_ops = { |
243 | .start_xmit = ipwireless_ppp_start_xmit, | 243 | .start_xmit = ipwireless_ppp_start_xmit, |
244 | .ioctl = ipwireless_ppp_ioctl | 244 | .ioctl = ipwireless_ppp_ioctl |
245 | }; | 245 | }; |
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index d83a43130df4..ad46eae1f9bb 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -62,7 +62,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp) | |||
62 | if (tty->driver == ptm_driver) | 62 | if (tty->driver == ptm_driver) |
63 | devpts_pty_kill(tty->link); | 63 | devpts_pty_kill(tty->link); |
64 | #endif | 64 | #endif |
65 | tty_unlock(); | ||
65 | tty_vhangup(tty->link); | 66 | tty_vhangup(tty->link); |
67 | tty_lock(); | ||
66 | } | 68 | } |
67 | } | 69 | } |
68 | 70 | ||
@@ -171,6 +173,23 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg) | |||
171 | return 0; | 173 | return 0; |
172 | } | 174 | } |
173 | 175 | ||
176 | /* Send a signal to the slave */ | ||
177 | static int pty_signal(struct tty_struct *tty, int sig) | ||
178 | { | ||
179 | unsigned long flags; | ||
180 | struct pid *pgrp; | ||
181 | |||
182 | if (tty->link) { | ||
183 | spin_lock_irqsave(&tty->link->ctrl_lock, flags); | ||
184 | pgrp = get_pid(tty->link->pgrp); | ||
185 | spin_unlock_irqrestore(&tty->link->ctrl_lock, flags); | ||
186 | |||
187 | kill_pgrp(pgrp, sig, 1); | ||
188 | put_pid(pgrp); | ||
189 | } | ||
190 | return 0; | ||
191 | } | ||
192 | |||
174 | static void pty_flush_buffer(struct tty_struct *tty) | 193 | static void pty_flush_buffer(struct tty_struct *tty) |
175 | { | 194 | { |
176 | struct tty_struct *to = tty->link; | 195 | struct tty_struct *to = tty->link; |
@@ -321,6 +340,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, | |||
321 | switch (cmd) { | 340 | switch (cmd) { |
322 | case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ | 341 | case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ |
323 | return pty_set_lock(tty, (int __user *) arg); | 342 | return pty_set_lock(tty, (int __user *) arg); |
343 | case TIOCSIG: /* Send signal to other side of pty */ | ||
344 | return pty_signal(tty, (int) arg); | ||
324 | } | 345 | } |
325 | return -ENOIOCTLCMD; | 346 | return -ENOIOCTLCMD; |
326 | } | 347 | } |
@@ -476,6 +497,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, | |||
476 | return pty_set_lock(tty, (int __user *)arg); | 497 | return pty_set_lock(tty, (int __user *)arg); |
477 | case TIOCGPTN: /* Get PT Number */ | 498 | case TIOCGPTN: /* Get PT Number */ |
478 | return put_user(tty->index, (unsigned int __user *)arg); | 499 | return put_user(tty->index, (unsigned int __user *)arg); |
500 | case TIOCSIG: /* Send signal to other side of pty */ | ||
501 | return pty_signal(tty, (int) arg); | ||
479 | } | 502 | } |
480 | 503 | ||
481 | return -ENOIOCTLCMD; | 504 | return -ENOIOCTLCMD; |
@@ -626,7 +649,7 @@ static const struct tty_operations pty_unix98_ops = { | |||
626 | * allocated_ptys_lock handles the list of free pty numbers | 649 | * allocated_ptys_lock handles the list of free pty numbers |
627 | */ | 650 | */ |
628 | 651 | ||
629 | static int __ptmx_open(struct inode *inode, struct file *filp) | 652 | static int ptmx_open(struct inode *inode, struct file *filp) |
630 | { | 653 | { |
631 | struct tty_struct *tty; | 654 | struct tty_struct *tty; |
632 | int retval; | 655 | int retval; |
@@ -635,11 +658,14 @@ static int __ptmx_open(struct inode *inode, struct file *filp) | |||
635 | nonseekable_open(inode, filp); | 658 | nonseekable_open(inode, filp); |
636 | 659 | ||
637 | /* find a device that is not in use. */ | 660 | /* find a device that is not in use. */ |
661 | tty_lock(); | ||
638 | index = devpts_new_index(inode); | 662 | index = devpts_new_index(inode); |
663 | tty_unlock(); | ||
639 | if (index < 0) | 664 | if (index < 0) |
640 | return index; | 665 | return index; |
641 | 666 | ||
642 | mutex_lock(&tty_mutex); | 667 | mutex_lock(&tty_mutex); |
668 | tty_lock(); | ||
643 | tty = tty_init_dev(ptm_driver, index, 1); | 669 | tty = tty_init_dev(ptm_driver, index, 1); |
644 | mutex_unlock(&tty_mutex); | 670 | mutex_unlock(&tty_mutex); |
645 | 671 | ||
@@ -657,26 +683,21 @@ static int __ptmx_open(struct inode *inode, struct file *filp) | |||
657 | goto out1; | 683 | goto out1; |
658 | 684 | ||
659 | retval = ptm_driver->ops->open(tty, filp); | 685 | retval = ptm_driver->ops->open(tty, filp); |
660 | if (!retval) | 686 | if (retval) |
661 | return 0; | 687 | goto out2; |
662 | out1: | 688 | out1: |
689 | tty_unlock(); | ||
690 | return retval; | ||
691 | out2: | ||
692 | tty_unlock(); | ||
663 | tty_release(inode, filp); | 693 | tty_release(inode, filp); |
664 | return retval; | 694 | return retval; |
665 | out: | 695 | out: |
666 | devpts_kill_index(inode, index); | 696 | devpts_kill_index(inode, index); |
697 | tty_unlock(); | ||
667 | return retval; | 698 | return retval; |
668 | } | 699 | } |
669 | 700 | ||
670 | static int ptmx_open(struct inode *inode, struct file *filp) | ||
671 | { | ||
672 | int ret; | ||
673 | |||
674 | lock_kernel(); | ||
675 | ret = __ptmx_open(inode, filp); | ||
676 | unlock_kernel(); | ||
677 | return ret; | ||
678 | } | ||
679 | |||
680 | static struct file_operations ptmx_fops; | 701 | static struct file_operations ptmx_fops; |
681 | 702 | ||
682 | static void __init unix98_pty_init(void) | 703 | static void __init unix98_pty_init(void) |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index b02332a5412f..af4de1fe8445 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include <linux/init.h> | 47 | #include <linux/init.h> |
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/tty_flip.h> | 49 | #include <linux/tty_flip.h> |
50 | #include <linux/smp_lock.h> | ||
51 | #include <linux/spinlock.h> | 50 | #include <linux/spinlock.h> |
52 | #include <linux/device.h> | 51 | #include <linux/device.h> |
53 | 52 | ||
@@ -1184,6 +1183,7 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port, | |||
1184 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) | 1183 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) |
1185 | return -EFAULT; | 1184 | return -EFAULT; |
1186 | 1185 | ||
1186 | mutex_lock(&port->port.mutex); | ||
1187 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != | 1187 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != |
1188 | (tmp.flags & ASYNC_SPD_MASK)); | 1188 | (tmp.flags & ASYNC_SPD_MASK)); |
1189 | 1189 | ||
@@ -1191,8 +1191,10 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port, | |||
1191 | if ((tmp.close_delay != port->port.close_delay) || | 1191 | if ((tmp.close_delay != port->port.close_delay) || |
1192 | (tmp.closing_wait != port->port.closing_wait) || | 1192 | (tmp.closing_wait != port->port.closing_wait) || |
1193 | ((tmp.flags & ~ASYNC_USR_MASK) != | 1193 | ((tmp.flags & ~ASYNC_USR_MASK) != |
1194 | (port->port.flags & ~ASYNC_USR_MASK))) | 1194 | (port->port.flags & ~ASYNC_USR_MASK))) { |
1195 | mutex_unlock(&port->port.mutex); | ||
1195 | return -EPERM; | 1196 | return -EPERM; |
1197 | } | ||
1196 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | 1198 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | |
1197 | (tmp.flags & ASYNC_USR_MASK)); | 1199 | (tmp.flags & ASYNC_USR_MASK)); |
1198 | } else { | 1200 | } else { |
@@ -1208,6 +1210,7 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port, | |||
1208 | rc_change_speed(tty, bp, port); | 1210 | rc_change_speed(tty, bp, port); |
1209 | spin_unlock_irqrestore(&riscom_lock, flags); | 1211 | spin_unlock_irqrestore(&riscom_lock, flags); |
1210 | } | 1212 | } |
1213 | mutex_unlock(&port->port.mutex); | ||
1211 | return 0; | 1214 | return 0; |
1212 | } | 1215 | } |
1213 | 1216 | ||
@@ -1220,12 +1223,15 @@ static int rc_get_serial_info(struct riscom_port *port, | |||
1220 | memset(&tmp, 0, sizeof(tmp)); | 1223 | memset(&tmp, 0, sizeof(tmp)); |
1221 | tmp.type = PORT_CIRRUS; | 1224 | tmp.type = PORT_CIRRUS; |
1222 | tmp.line = port - rc_port; | 1225 | tmp.line = port - rc_port; |
1226 | |||
1227 | mutex_lock(&port->port.mutex); | ||
1223 | tmp.port = bp->base; | 1228 | tmp.port = bp->base; |
1224 | tmp.irq = bp->irq; | 1229 | tmp.irq = bp->irq; |
1225 | tmp.flags = port->port.flags; | 1230 | tmp.flags = port->port.flags; |
1226 | tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC; | 1231 | tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC; |
1227 | tmp.close_delay = port->port.close_delay * HZ/100; | 1232 | tmp.close_delay = port->port.close_delay * HZ/100; |
1228 | tmp.closing_wait = port->port.closing_wait * HZ/100; | 1233 | tmp.closing_wait = port->port.closing_wait * HZ/100; |
1234 | mutex_unlock(&port->port.mutex); | ||
1229 | tmp.xmit_fifo_size = CD180_NFIFO; | 1235 | tmp.xmit_fifo_size = CD180_NFIFO; |
1230 | return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0; | 1236 | return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0; |
1231 | } | 1237 | } |
@@ -1242,14 +1248,10 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp, | |||
1242 | 1248 | ||
1243 | switch (cmd) { | 1249 | switch (cmd) { |
1244 | case TIOCGSERIAL: | 1250 | case TIOCGSERIAL: |
1245 | lock_kernel(); | ||
1246 | retval = rc_get_serial_info(port, argp); | 1251 | retval = rc_get_serial_info(port, argp); |
1247 | unlock_kernel(); | ||
1248 | break; | 1252 | break; |
1249 | case TIOCSSERIAL: | 1253 | case TIOCSSERIAL: |
1250 | lock_kernel(); | ||
1251 | retval = rc_set_serial_info(tty, port, argp); | 1254 | retval = rc_set_serial_info(tty, port, argp); |
1252 | unlock_kernel(); | ||
1253 | break; | 1255 | break; |
1254 | default: | 1256 | default: |
1255 | retval = -ENOIOCTLCMD; | 1257 | retval = -ENOIOCTLCMD; |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 0e29a23ec4c5..79c3bc69165a 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -73,7 +73,6 @@ | |||
73 | #include <linux/tty_driver.h> | 73 | #include <linux/tty_driver.h> |
74 | #include <linux/tty_flip.h> | 74 | #include <linux/tty_flip.h> |
75 | #include <linux/serial.h> | 75 | #include <linux/serial.h> |
76 | #include <linux/smp_lock.h> | ||
77 | #include <linux/string.h> | 76 | #include <linux/string.h> |
78 | #include <linux/fcntl.h> | 77 | #include <linux/fcntl.h> |
79 | #include <linux/ptrace.h> | 78 | #include <linux/ptrace.h> |
@@ -1017,6 +1016,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1017 | if (tty_port_close_start(port, tty, filp) == 0) | 1016 | if (tty_port_close_start(port, tty, filp) == 0) |
1018 | return; | 1017 | return; |
1019 | 1018 | ||
1019 | mutex_lock(&port->mutex); | ||
1020 | cp = &info->channel; | 1020 | cp = &info->channel; |
1021 | /* | 1021 | /* |
1022 | * Before we drop DTR, make sure the UART transmitter | 1022 | * Before we drop DTR, make sure the UART transmitter |
@@ -1060,9 +1060,13 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1060 | info->xmit_buf = NULL; | 1060 | info->xmit_buf = NULL; |
1061 | } | 1061 | } |
1062 | } | 1062 | } |
1063 | spin_lock_irq(&port->lock); | ||
1063 | info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); | 1064 | info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); |
1064 | tty->closing = 0; | 1065 | tty->closing = 0; |
1066 | spin_unlock_irq(&port->lock); | ||
1067 | mutex_unlock(&port->mutex); | ||
1065 | tty_port_tty_set(port, NULL); | 1068 | tty_port_tty_set(port, NULL); |
1069 | |||
1066 | wake_up_interruptible(&port->close_wait); | 1070 | wake_up_interruptible(&port->close_wait); |
1067 | complete_all(&info->close_wait); | 1071 | complete_all(&info->close_wait); |
1068 | atomic_dec(&rp_num_ports_open); | 1072 | atomic_dec(&rp_num_ports_open); |
@@ -1210,11 +1214,13 @@ static int get_config(struct r_port *info, struct rocket_config __user *retinfo) | |||
1210 | if (!retinfo) | 1214 | if (!retinfo) |
1211 | return -EFAULT; | 1215 | return -EFAULT; |
1212 | memset(&tmp, 0, sizeof (tmp)); | 1216 | memset(&tmp, 0, sizeof (tmp)); |
1217 | mutex_lock(&info->port.mutex); | ||
1213 | tmp.line = info->line; | 1218 | tmp.line = info->line; |
1214 | tmp.flags = info->flags; | 1219 | tmp.flags = info->flags; |
1215 | tmp.close_delay = info->port.close_delay; | 1220 | tmp.close_delay = info->port.close_delay; |
1216 | tmp.closing_wait = info->port.closing_wait; | 1221 | tmp.closing_wait = info->port.closing_wait; |
1217 | tmp.port = rcktpt_io_addr[(info->line >> 5) & 3]; | 1222 | tmp.port = rcktpt_io_addr[(info->line >> 5) & 3]; |
1223 | mutex_unlock(&info->port.mutex); | ||
1218 | 1224 | ||
1219 | if (copy_to_user(retinfo, &tmp, sizeof (*retinfo))) | 1225 | if (copy_to_user(retinfo, &tmp, sizeof (*retinfo))) |
1220 | return -EFAULT; | 1226 | return -EFAULT; |
@@ -1229,10 +1235,13 @@ static int set_config(struct tty_struct *tty, struct r_port *info, | |||
1229 | if (copy_from_user(&new_serial, new_info, sizeof (new_serial))) | 1235 | if (copy_from_user(&new_serial, new_info, sizeof (new_serial))) |
1230 | return -EFAULT; | 1236 | return -EFAULT; |
1231 | 1237 | ||
1238 | mutex_lock(&info->port.mutex); | ||
1232 | if (!capable(CAP_SYS_ADMIN)) | 1239 | if (!capable(CAP_SYS_ADMIN)) |
1233 | { | 1240 | { |
1234 | if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) | 1241 | if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) { |
1242 | mutex_unlock(&info->port.mutex); | ||
1235 | return -EPERM; | 1243 | return -EPERM; |
1244 | } | ||
1236 | info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); | 1245 | info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); |
1237 | configure_r_port(tty, info, NULL); | 1246 | configure_r_port(tty, info, NULL); |
1238 | return 0; | 1247 | return 0; |
@@ -1250,6 +1259,7 @@ static int set_config(struct tty_struct *tty, struct r_port *info, | |||
1250 | tty->alt_speed = 230400; | 1259 | tty->alt_speed = 230400; |
1251 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) | 1260 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) |
1252 | tty->alt_speed = 460800; | 1261 | tty->alt_speed = 460800; |
1262 | mutex_unlock(&info->port.mutex); | ||
1253 | 1263 | ||
1254 | configure_r_port(tty, info, NULL); | 1264 | configure_r_port(tty, info, NULL); |
1255 | return 0; | 1265 | return 0; |
@@ -1325,8 +1335,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, | |||
1325 | if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl")) | 1335 | if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl")) |
1326 | return -ENXIO; | 1336 | return -ENXIO; |
1327 | 1337 | ||
1328 | lock_kernel(); | ||
1329 | |||
1330 | switch (cmd) { | 1338 | switch (cmd) { |
1331 | case RCKP_GET_STRUCT: | 1339 | case RCKP_GET_STRUCT: |
1332 | if (copy_to_user(argp, info, sizeof (struct r_port))) | 1340 | if (copy_to_user(argp, info, sizeof (struct r_port))) |
@@ -1350,7 +1358,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, | |||
1350 | default: | 1358 | default: |
1351 | ret = -ENOIOCTLCMD; | 1359 | ret = -ENOIOCTLCMD; |
1352 | } | 1360 | } |
1353 | unlock_kernel(); | ||
1354 | return ret; | 1361 | return ret; |
1355 | } | 1362 | } |
1356 | 1363 | ||
@@ -1471,7 +1478,6 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1471 | jiffies); | 1478 | jiffies); |
1472 | printk(KERN_INFO "cps=%d...\n", info->cps); | 1479 | printk(KERN_INFO "cps=%d...\n", info->cps); |
1473 | #endif | 1480 | #endif |
1474 | lock_kernel(); | ||
1475 | while (1) { | 1481 | while (1) { |
1476 | txcnt = sGetTxCnt(cp); | 1482 | txcnt = sGetTxCnt(cp); |
1477 | if (!txcnt) { | 1483 | if (!txcnt) { |
@@ -1499,7 +1505,6 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1499 | break; | 1505 | break; |
1500 | } | 1506 | } |
1501 | __set_current_state(TASK_RUNNING); | 1507 | __set_current_state(TASK_RUNNING); |
1502 | unlock_kernel(); | ||
1503 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT | 1508 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT |
1504 | printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); | 1509 | printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); |
1505 | #endif | 1510 | #endif |
@@ -1512,6 +1517,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1512 | { | 1517 | { |
1513 | CHANNEL_t *cp; | 1518 | CHANNEL_t *cp; |
1514 | struct r_port *info = tty->driver_data; | 1519 | struct r_port *info = tty->driver_data; |
1520 | unsigned long flags; | ||
1515 | 1521 | ||
1516 | if (rocket_paranoia_check(info, "rp_hangup")) | 1522 | if (rocket_paranoia_check(info, "rp_hangup")) |
1517 | return; | 1523 | return; |
@@ -1520,11 +1526,15 @@ static void rp_hangup(struct tty_struct *tty) | |||
1520 | printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); | 1526 | printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); |
1521 | #endif | 1527 | #endif |
1522 | rp_flush_buffer(tty); | 1528 | rp_flush_buffer(tty); |
1523 | if (info->port.flags & ASYNC_CLOSING) | 1529 | spin_lock_irqsave(&info->port.lock, flags); |
1530 | if (info->port.flags & ASYNC_CLOSING) { | ||
1531 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
1524 | return; | 1532 | return; |
1533 | } | ||
1525 | if (info->port.count) | 1534 | if (info->port.count) |
1526 | atomic_dec(&rp_num_ports_open); | 1535 | atomic_dec(&rp_num_ports_open); |
1527 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); | 1536 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); |
1537 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
1528 | 1538 | ||
1529 | tty_port_hangup(&info->port); | 1539 | tty_port_hangup(&info->port); |
1530 | 1540 | ||
@@ -1535,7 +1545,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1535 | sDisCTSFlowCtl(cp); | 1545 | sDisCTSFlowCtl(cp); |
1536 | sDisTxSoftFlowCtl(cp); | 1546 | sDisTxSoftFlowCtl(cp); |
1537 | sClrTxXOFF(cp); | 1547 | sClrTxXOFF(cp); |
1538 | info->port.flags &= ~ASYNC_INITIALIZED; | 1548 | clear_bit(ASYNCB_INITIALIZED, &info->port.flags); |
1539 | 1549 | ||
1540 | wake_up_interruptible(&info->port.open_wait); | 1550 | wake_up_interruptible(&info->port.open_wait); |
1541 | } | 1551 | } |
diff --git a/drivers/char/selection.c b/drivers/char/selection.c index f97b9e848064..ebae344ce910 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/selection.h> | 26 | #include <linux/selection.h> |
27 | #include <linux/tiocl.h> | 27 | #include <linux/tiocl.h> |
28 | #include <linux/console.h> | 28 | #include <linux/console.h> |
29 | #include <linux/smp_lock.h> | ||
29 | 30 | ||
30 | /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */ | 31 | /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */ |
31 | #define isspace(c) ((c) == ' ') | 32 | #define isspace(c) ((c) == ' ') |
@@ -312,12 +313,20 @@ int paste_selection(struct tty_struct *tty) | |||
312 | struct tty_ldisc *ld; | 313 | struct tty_ldisc *ld; |
313 | DECLARE_WAITQUEUE(wait, current); | 314 | DECLARE_WAITQUEUE(wait, current); |
314 | 315 | ||
316 | /* always called with BTM from vt_ioctl */ | ||
317 | WARN_ON(!tty_locked()); | ||
318 | |||
315 | acquire_console_sem(); | 319 | acquire_console_sem(); |
316 | poke_blanked_console(); | 320 | poke_blanked_console(); |
317 | release_console_sem(); | 321 | release_console_sem(); |
318 | 322 | ||
319 | ld = tty_ldisc_ref_wait(tty); | 323 | ld = tty_ldisc_ref(tty); |
320 | 324 | if (!ld) { | |
325 | tty_unlock(); | ||
326 | ld = tty_ldisc_ref_wait(tty); | ||
327 | tty_lock(); | ||
328 | } | ||
329 | |||
321 | add_wait_queue(&vc->paste_wait, &wait); | 330 | add_wait_queue(&vc->paste_wait, &wait); |
322 | while (sel_buffer && sel_buffer_lth > pasted) { | 331 | while (sel_buffer && sel_buffer_lth > pasted) { |
323 | set_current_state(TASK_INTERRUPTIBLE); | 332 | set_current_state(TASK_INTERRUPTIBLE); |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index ecbe479c7d68..f646725bd567 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
@@ -1505,7 +1505,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
1505 | printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ | 1505 | printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ |
1506 | #endif | 1506 | #endif |
1507 | 1507 | ||
1508 | lock_kernel(); | 1508 | tty_lock(); |
1509 | 1509 | ||
1510 | switch (cmd) { | 1510 | switch (cmd) { |
1511 | case CYGETMON: | 1511 | case CYGETMON: |
@@ -1561,7 +1561,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
1561 | default: | 1561 | default: |
1562 | ret_val = -ENOIOCTLCMD; | 1562 | ret_val = -ENOIOCTLCMD; |
1563 | } | 1563 | } |
1564 | unlock_kernel(); | 1564 | tty_unlock(); |
1565 | 1565 | ||
1566 | #ifdef SERIAL_DEBUG_OTHER | 1566 | #ifdef SERIAL_DEBUG_OTHER |
1567 | printk("cy_ioctl done\n"); | 1567 | printk("cy_ioctl done\n"); |
@@ -1786,7 +1786,9 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
1786 | tty->name, info->count); | 1786 | tty->name, info->count); |
1787 | /**/ | 1787 | /**/ |
1788 | #endif | 1788 | #endif |
1789 | schedule(); | 1789 | tty_unlock(); |
1790 | schedule(); | ||
1791 | tty_lock(); | ||
1790 | } | 1792 | } |
1791 | __set_current_state(TASK_RUNNING); | 1793 | __set_current_state(TASK_RUNNING); |
1792 | remove_wait_queue(&info->open_wait, &wait); | 1794 | remove_wait_queue(&info->open_wait, &wait); |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 2c24fcdc722a..9f8495b4fc8f 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -1365,7 +1365,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
1365 | retval = -ERESTARTSYS; | 1365 | retval = -ERESTARTSYS; |
1366 | break; | 1366 | break; |
1367 | } | 1367 | } |
1368 | tty_unlock(); | ||
1368 | schedule(); | 1369 | schedule(); |
1370 | tty_lock(); | ||
1369 | } | 1371 | } |
1370 | 1372 | ||
1371 | set_current_state(TASK_RUNNING); | 1373 | set_current_state(TASK_RUNNING); |
@@ -1863,8 +1865,7 @@ static int sx_set_serial_info(struct specialix_port *port, | |||
1863 | return -EFAULT; | 1865 | return -EFAULT; |
1864 | } | 1866 | } |
1865 | 1867 | ||
1866 | lock_kernel(); | 1868 | mutex_lock(&port->port.mutex); |
1867 | |||
1868 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != | 1869 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != |
1869 | (tmp.flags & ASYNC_SPD_MASK)); | 1870 | (tmp.flags & ASYNC_SPD_MASK)); |
1870 | change_speed |= (tmp.custom_divisor != port->custom_divisor); | 1871 | change_speed |= (tmp.custom_divisor != port->custom_divisor); |
@@ -1875,7 +1876,7 @@ static int sx_set_serial_info(struct specialix_port *port, | |||
1875 | ((tmp.flags & ~ASYNC_USR_MASK) != | 1876 | ((tmp.flags & ~ASYNC_USR_MASK) != |
1876 | (port->port.flags & ~ASYNC_USR_MASK))) { | 1877 | (port->port.flags & ~ASYNC_USR_MASK))) { |
1877 | func_exit(); | 1878 | func_exit(); |
1878 | unlock_kernel(); | 1879 | mutex_unlock(&port->port.mutex); |
1879 | return -EPERM; | 1880 | return -EPERM; |
1880 | } | 1881 | } |
1881 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | 1882 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | |
@@ -1892,7 +1893,7 @@ static int sx_set_serial_info(struct specialix_port *port, | |||
1892 | sx_change_speed(bp, port); | 1893 | sx_change_speed(bp, port); |
1893 | 1894 | ||
1894 | func_exit(); | 1895 | func_exit(); |
1895 | unlock_kernel(); | 1896 | mutex_unlock(&port->port.mutex); |
1896 | return 0; | 1897 | return 0; |
1897 | } | 1898 | } |
1898 | 1899 | ||
@@ -1906,7 +1907,7 @@ static int sx_get_serial_info(struct specialix_port *port, | |||
1906 | func_enter(); | 1907 | func_enter(); |
1907 | 1908 | ||
1908 | memset(&tmp, 0, sizeof(tmp)); | 1909 | memset(&tmp, 0, sizeof(tmp)); |
1909 | lock_kernel(); | 1910 | mutex_lock(&port->port.mutex); |
1910 | tmp.type = PORT_CIRRUS; | 1911 | tmp.type = PORT_CIRRUS; |
1911 | tmp.line = port - sx_port; | 1912 | tmp.line = port - sx_port; |
1912 | tmp.port = bp->base; | 1913 | tmp.port = bp->base; |
@@ -1917,7 +1918,7 @@ static int sx_get_serial_info(struct specialix_port *port, | |||
1917 | tmp.closing_wait = port->port.closing_wait * HZ/100; | 1918 | tmp.closing_wait = port->port.closing_wait * HZ/100; |
1918 | tmp.custom_divisor = port->custom_divisor; | 1919 | tmp.custom_divisor = port->custom_divisor; |
1919 | tmp.xmit_fifo_size = CD186x_NFIFO; | 1920 | tmp.xmit_fifo_size = CD186x_NFIFO; |
1920 | unlock_kernel(); | 1921 | mutex_unlock(&port->port.mutex); |
1921 | if (copy_to_user(retinfo, &tmp, sizeof(tmp))) { | 1922 | if (copy_to_user(retinfo, &tmp, sizeof(tmp))) { |
1922 | func_exit(); | 1923 | func_exit(); |
1923 | return -EFAULT; | 1924 | return -EFAULT; |
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 6049fd731924..f2167f8e5aab 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -807,7 +807,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) | |||
807 | timeout = HZ; | 807 | timeout = HZ; |
808 | tend = jiffies + timeout; | 808 | tend = jiffies + timeout; |
809 | 809 | ||
810 | lock_kernel(); | ||
811 | while (stl_datastate(portp)) { | 810 | while (stl_datastate(portp)) { |
812 | if (signal_pending(current)) | 811 | if (signal_pending(current)) |
813 | break; | 812 | break; |
@@ -815,7 +814,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) | |||
815 | if (time_after_eq(jiffies, tend)) | 814 | if (time_after_eq(jiffies, tend)) |
816 | break; | 815 | break; |
817 | } | 816 | } |
818 | unlock_kernel(); | ||
819 | } | 817 | } |
820 | 818 | ||
821 | /*****************************************************************************/ | 819 | /*****************************************************************************/ |
@@ -1029,6 +1027,8 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) | |||
1029 | pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp); | 1027 | pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp); |
1030 | 1028 | ||
1031 | memset(&sio, 0, sizeof(struct serial_struct)); | 1029 | memset(&sio, 0, sizeof(struct serial_struct)); |
1030 | |||
1031 | mutex_lock(&portp->port.mutex); | ||
1032 | sio.line = portp->portnr; | 1032 | sio.line = portp->portnr; |
1033 | sio.port = portp->ioaddr; | 1033 | sio.port = portp->ioaddr; |
1034 | sio.flags = portp->port.flags; | 1034 | sio.flags = portp->port.flags; |
@@ -1048,6 +1048,7 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) | |||
1048 | brdp = stl_brds[portp->brdnr]; | 1048 | brdp = stl_brds[portp->brdnr]; |
1049 | if (brdp != NULL) | 1049 | if (brdp != NULL) |
1050 | sio.irq = brdp->irq; | 1050 | sio.irq = brdp->irq; |
1051 | mutex_unlock(&portp->port.mutex); | ||
1051 | 1052 | ||
1052 | return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0; | 1053 | return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0; |
1053 | } | 1054 | } |
@@ -1069,12 +1070,15 @@ static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp | |||
1069 | 1070 | ||
1070 | if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) | 1071 | if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) |
1071 | return -EFAULT; | 1072 | return -EFAULT; |
1073 | mutex_lock(&portp->port.mutex); | ||
1072 | if (!capable(CAP_SYS_ADMIN)) { | 1074 | if (!capable(CAP_SYS_ADMIN)) { |
1073 | if ((sio.baud_base != portp->baud_base) || | 1075 | if ((sio.baud_base != portp->baud_base) || |
1074 | (sio.close_delay != portp->close_delay) || | 1076 | (sio.close_delay != portp->close_delay) || |
1075 | ((sio.flags & ~ASYNC_USR_MASK) != | 1077 | ((sio.flags & ~ASYNC_USR_MASK) != |
1076 | (portp->port.flags & ~ASYNC_USR_MASK))) | 1078 | (portp->port.flags & ~ASYNC_USR_MASK))) { |
1079 | mutex_unlock(&portp->port.mutex); | ||
1077 | return -EPERM; | 1080 | return -EPERM; |
1081 | } | ||
1078 | } | 1082 | } |
1079 | 1083 | ||
1080 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | | 1084 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | |
@@ -1083,6 +1087,7 @@ static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp | |||
1083 | portp->close_delay = sio.close_delay; | 1087 | portp->close_delay = sio.close_delay; |
1084 | portp->closing_wait = sio.closing_wait; | 1088 | portp->closing_wait = sio.closing_wait; |
1085 | portp->custom_divisor = sio.custom_divisor; | 1089 | portp->custom_divisor = sio.custom_divisor; |
1090 | mutex_unlock(&portp->port.mutex); | ||
1086 | stl_setport(portp, tty->termios); | 1091 | stl_setport(portp, tty->termios); |
1087 | return 0; | 1092 | return 0; |
1088 | } | 1093 | } |
@@ -1147,8 +1152,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd | |||
1147 | 1152 | ||
1148 | rc = 0; | 1153 | rc = 0; |
1149 | 1154 | ||
1150 | lock_kernel(); | ||
1151 | |||
1152 | switch (cmd) { | 1155 | switch (cmd) { |
1153 | case TIOCGSERIAL: | 1156 | case TIOCGSERIAL: |
1154 | rc = stl_getserial(portp, argp); | 1157 | rc = stl_getserial(portp, argp); |
@@ -1173,7 +1176,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd | |||
1173 | rc = -ENOIOCTLCMD; | 1176 | rc = -ENOIOCTLCMD; |
1174 | break; | 1177 | break; |
1175 | } | 1178 | } |
1176 | unlock_kernel(); | ||
1177 | return rc; | 1179 | return rc; |
1178 | } | 1180 | } |
1179 | 1181 | ||
@@ -2327,6 +2329,7 @@ static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comst | |||
2327 | return -ENODEV; | 2329 | return -ENODEV; |
2328 | } | 2330 | } |
2329 | 2331 | ||
2332 | mutex_lock(&portp->port.mutex); | ||
2330 | portp->stats.state = portp->istate; | 2333 | portp->stats.state = portp->istate; |
2331 | portp->stats.flags = portp->port.flags; | 2334 | portp->stats.flags = portp->port.flags; |
2332 | portp->stats.hwid = portp->hwid; | 2335 | portp->stats.hwid = portp->hwid; |
@@ -2358,6 +2361,7 @@ static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comst | |||
2358 | (STL_TXBUFSIZE - (tail - head)); | 2361 | (STL_TXBUFSIZE - (tail - head)); |
2359 | 2362 | ||
2360 | portp->stats.signals = (unsigned long) stl_getsignals(portp); | 2363 | portp->stats.signals = (unsigned long) stl_getsignals(portp); |
2364 | mutex_unlock(&portp->port.mutex); | ||
2361 | 2365 | ||
2362 | return copy_to_user(cp, &portp->stats, | 2366 | return copy_to_user(cp, &portp->stats, |
2363 | sizeof(comstats_t)) ? -EFAULT : 0; | 2367 | sizeof(comstats_t)) ? -EFAULT : 0; |
@@ -2382,10 +2386,12 @@ static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp) | |||
2382 | return -ENODEV; | 2386 | return -ENODEV; |
2383 | } | 2387 | } |
2384 | 2388 | ||
2389 | mutex_lock(&portp->port.mutex); | ||
2385 | memset(&portp->stats, 0, sizeof(comstats_t)); | 2390 | memset(&portp->stats, 0, sizeof(comstats_t)); |
2386 | portp->stats.brd = portp->brdnr; | 2391 | portp->stats.brd = portp->brdnr; |
2387 | portp->stats.panel = portp->panelnr; | 2392 | portp->stats.panel = portp->panelnr; |
2388 | portp->stats.port = portp->portnr; | 2393 | portp->stats.port = portp->portnr; |
2394 | mutex_unlock(&portp->port.mutex); | ||
2389 | return copy_to_user(cp, &portp->stats, | 2395 | return copy_to_user(cp, &portp->stats, |
2390 | sizeof(comstats_t)) ? -EFAULT : 0; | 2396 | sizeof(comstats_t)) ? -EFAULT : 0; |
2391 | } | 2397 | } |
@@ -2451,7 +2457,6 @@ static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
2451 | return -ENODEV; | 2457 | return -ENODEV; |
2452 | rc = 0; | 2458 | rc = 0; |
2453 | 2459 | ||
2454 | lock_kernel(); | ||
2455 | switch (cmd) { | 2460 | switch (cmd) { |
2456 | case COM_GETPORTSTATS: | 2461 | case COM_GETPORTSTATS: |
2457 | rc = stl_getportstats(NULL, NULL, argp); | 2462 | rc = stl_getportstats(NULL, NULL, argp); |
@@ -2472,7 +2477,6 @@ static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
2472 | rc = -ENOIOCTLCMD; | 2477 | rc = -ENOIOCTLCMD; |
2473 | break; | 2478 | break; |
2474 | } | 2479 | } |
2475 | unlock_kernel(); | ||
2476 | return rc; | 2480 | return rc; |
2477 | } | 2481 | } |
2478 | 2482 | ||
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index a81ec4fcf6ff..5b24db4ff7f1 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -1699,7 +1699,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, | |||
1699 | if (!capable(CAP_SYS_RAWIO)) | 1699 | if (!capable(CAP_SYS_RAWIO)) |
1700 | return -EPERM; | 1700 | return -EPERM; |
1701 | 1701 | ||
1702 | lock_kernel(); | 1702 | tty_lock(); |
1703 | 1703 | ||
1704 | sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); | 1704 | sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); |
1705 | 1705 | ||
@@ -1848,7 +1848,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, | |||
1848 | break; | 1848 | break; |
1849 | } | 1849 | } |
1850 | out: | 1850 | out: |
1851 | unlock_kernel(); | 1851 | tty_unlock(); |
1852 | func_exit(); | 1852 | func_exit(); |
1853 | return rc; | 1853 | return rc; |
1854 | } | 1854 | } |
@@ -1859,7 +1859,7 @@ static int sx_break(struct tty_struct *tty, int flag) | |||
1859 | int rv; | 1859 | int rv; |
1860 | 1860 | ||
1861 | func_enter(); | 1861 | func_enter(); |
1862 | lock_kernel(); | 1862 | tty_lock(); |
1863 | 1863 | ||
1864 | if (flag) | 1864 | if (flag) |
1865 | rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); | 1865 | rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); |
@@ -1868,7 +1868,7 @@ static int sx_break(struct tty_struct *tty, int flag) | |||
1868 | if (rv != 1) | 1868 | if (rv != 1) |
1869 | printk(KERN_ERR "sx: couldn't send break (%x).\n", | 1869 | printk(KERN_ERR "sx: couldn't send break (%x).\n", |
1870 | read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); | 1870 | read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); |
1871 | unlock_kernel(); | 1871 | tty_unlock(); |
1872 | func_exit(); | 1872 | func_exit(); |
1873 | return 0; | 1873 | return 0; |
1874 | } | 1874 | } |
@@ -1909,7 +1909,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, | |||
1909 | /* func_enter2(); */ | 1909 | /* func_enter2(); */ |
1910 | 1910 | ||
1911 | rc = 0; | 1911 | rc = 0; |
1912 | lock_kernel(); | 1912 | tty_lock(); |
1913 | switch (cmd) { | 1913 | switch (cmd) { |
1914 | case TIOCGSERIAL: | 1914 | case TIOCGSERIAL: |
1915 | rc = gs_getserial(&port->gs, argp); | 1915 | rc = gs_getserial(&port->gs, argp); |
@@ -1921,7 +1921,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, | |||
1921 | rc = -ENOIOCTLCMD; | 1921 | rc = -ENOIOCTLCMD; |
1922 | break; | 1922 | break; |
1923 | } | 1923 | } |
1924 | unlock_kernel(); | 1924 | tty_unlock(); |
1925 | 1925 | ||
1926 | /* func_exit(); */ | 1926 | /* func_exit(); */ |
1927 | return rc; | 1927 | return rc; |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 0658fc548222..a2a58004e188 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -81,7 +81,6 @@ | |||
81 | #include <linux/mm.h> | 81 | #include <linux/mm.h> |
82 | #include <linux/seq_file.h> | 82 | #include <linux/seq_file.h> |
83 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
84 | #include <linux/smp_lock.h> | ||
85 | #include <linux/delay.h> | 84 | #include <linux/delay.h> |
86 | #include <linux/netdevice.h> | 85 | #include <linux/netdevice.h> |
87 | #include <linux/vmalloc.h> | 86 | #include <linux/vmalloc.h> |
@@ -2436,7 +2435,9 @@ static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user * | |||
2436 | if (!user_icount) { | 2435 | if (!user_icount) { |
2437 | memset(&info->icount, 0, sizeof(info->icount)); | 2436 | memset(&info->icount, 0, sizeof(info->icount)); |
2438 | } else { | 2437 | } else { |
2438 | mutex_lock(&info->port.mutex); | ||
2439 | COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); | 2439 | COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); |
2440 | mutex_unlock(&info->port.mutex); | ||
2440 | if (err) | 2441 | if (err) |
2441 | return -EFAULT; | 2442 | return -EFAULT; |
2442 | } | 2443 | } |
@@ -2461,7 +2462,9 @@ static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_p | |||
2461 | printk("%s(%d):mgsl_get_params(%s)\n", | 2462 | printk("%s(%d):mgsl_get_params(%s)\n", |
2462 | __FILE__,__LINE__, info->device_name); | 2463 | __FILE__,__LINE__, info->device_name); |
2463 | 2464 | ||
2465 | mutex_lock(&info->port.mutex); | ||
2464 | COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); | 2466 | COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); |
2467 | mutex_unlock(&info->port.mutex); | ||
2465 | if (err) { | 2468 | if (err) { |
2466 | if ( debug_level >= DEBUG_LEVEL_INFO ) | 2469 | if ( debug_level >= DEBUG_LEVEL_INFO ) |
2467 | printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n", | 2470 | printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n", |
@@ -2501,11 +2504,13 @@ static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_pa | |||
2501 | return -EFAULT; | 2504 | return -EFAULT; |
2502 | } | 2505 | } |
2503 | 2506 | ||
2507 | mutex_lock(&info->port.mutex); | ||
2504 | spin_lock_irqsave(&info->irq_spinlock,flags); | 2508 | spin_lock_irqsave(&info->irq_spinlock,flags); |
2505 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); | 2509 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); |
2506 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | 2510 | spin_unlock_irqrestore(&info->irq_spinlock,flags); |
2507 | 2511 | ||
2508 | mgsl_change_params(info); | 2512 | mgsl_change_params(info); |
2513 | mutex_unlock(&info->port.mutex); | ||
2509 | 2514 | ||
2510 | return 0; | 2515 | return 0; |
2511 | 2516 | ||
@@ -2935,7 +2940,6 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file, | |||
2935 | unsigned int cmd, unsigned long arg) | 2940 | unsigned int cmd, unsigned long arg) |
2936 | { | 2941 | { |
2937 | struct mgsl_struct * info = tty->driver_data; | 2942 | struct mgsl_struct * info = tty->driver_data; |
2938 | int ret; | ||
2939 | 2943 | ||
2940 | if (debug_level >= DEBUG_LEVEL_INFO) | 2944 | if (debug_level >= DEBUG_LEVEL_INFO) |
2941 | printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__, | 2945 | printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__, |
@@ -2950,10 +2954,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file, | |||
2950 | return -EIO; | 2954 | return -EIO; |
2951 | } | 2955 | } |
2952 | 2956 | ||
2953 | lock_kernel(); | 2957 | return mgsl_ioctl_common(info, cmd, arg); |
2954 | ret = mgsl_ioctl_common(info, cmd, arg); | ||
2955 | unlock_kernel(); | ||
2956 | return ret; | ||
2957 | } | 2958 | } |
2958 | 2959 | ||
2959 | static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) | 2960 | static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) |
@@ -3109,12 +3110,14 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp) | |||
3109 | 3110 | ||
3110 | if (tty_port_close_start(&info->port, tty, filp) == 0) | 3111 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
3111 | goto cleanup; | 3112 | goto cleanup; |
3112 | 3113 | ||
3114 | mutex_lock(&info->port.mutex); | ||
3113 | if (info->port.flags & ASYNC_INITIALIZED) | 3115 | if (info->port.flags & ASYNC_INITIALIZED) |
3114 | mgsl_wait_until_sent(tty, info->timeout); | 3116 | mgsl_wait_until_sent(tty, info->timeout); |
3115 | mgsl_flush_buffer(tty); | 3117 | mgsl_flush_buffer(tty); |
3116 | tty_ldisc_flush(tty); | 3118 | tty_ldisc_flush(tty); |
3117 | shutdown(info); | 3119 | shutdown(info); |
3120 | mutex_unlock(&info->port.mutex); | ||
3118 | 3121 | ||
3119 | tty_port_close_end(&info->port, tty); | 3122 | tty_port_close_end(&info->port, tty); |
3120 | info->port.tty = NULL; | 3123 | info->port.tty = NULL; |
@@ -3162,7 +3165,6 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) | |||
3162 | * Note: use tight timings here to satisfy the NIST-PCTS. | 3165 | * Note: use tight timings here to satisfy the NIST-PCTS. |
3163 | */ | 3166 | */ |
3164 | 3167 | ||
3165 | lock_kernel(); | ||
3166 | if ( info->params.data_rate ) { | 3168 | if ( info->params.data_rate ) { |
3167 | char_time = info->timeout/(32 * 5); | 3169 | char_time = info->timeout/(32 * 5); |
3168 | if (!char_time) | 3170 | if (!char_time) |
@@ -3192,7 +3194,6 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) | |||
3192 | break; | 3194 | break; |
3193 | } | 3195 | } |
3194 | } | 3196 | } |
3195 | unlock_kernel(); | ||
3196 | 3197 | ||
3197 | exit: | 3198 | exit: |
3198 | if (debug_level >= DEBUG_LEVEL_INFO) | 3199 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -3348,7 +3349,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
3348 | printk("%s(%d):block_til_ready blocking on %s count=%d\n", | 3349 | printk("%s(%d):block_til_ready blocking on %s count=%d\n", |
3349 | __FILE__,__LINE__, tty->driver->name, port->count ); | 3350 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3350 | 3351 | ||
3352 | tty_unlock(); | ||
3351 | schedule(); | 3353 | schedule(); |
3354 | tty_lock(); | ||
3352 | } | 3355 | } |
3353 | 3356 | ||
3354 | set_current_state(TASK_RUNNING); | 3357 | set_current_state(TASK_RUNNING); |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 334cf5c8c8b6..fef80cfcab5c 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -40,8 +40,8 @@ | |||
40 | #define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt | 40 | #define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt |
41 | #define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt | 41 | #define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt |
42 | #define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label)) | 42 | #define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label)) |
43 | //#define DBGTBUF(info) dump_tbufs(info) | 43 | /*#define DBGTBUF(info) dump_tbufs(info)*/ |
44 | //#define DBGRBUF(info) dump_rbufs(info) | 44 | /*#define DBGRBUF(info) dump_rbufs(info)*/ |
45 | 45 | ||
46 | 46 | ||
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
@@ -62,7 +62,6 @@ | |||
62 | #include <linux/mm.h> | 62 | #include <linux/mm.h> |
63 | #include <linux/seq_file.h> | 63 | #include <linux/seq_file.h> |
64 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
65 | #include <linux/smp_lock.h> | ||
66 | #include <linux/netdevice.h> | 65 | #include <linux/netdevice.h> |
67 | #include <linux/vmalloc.h> | 66 | #include <linux/vmalloc.h> |
68 | #include <linux/init.h> | 67 | #include <linux/init.h> |
@@ -676,12 +675,14 @@ static int open(struct tty_struct *tty, struct file *filp) | |||
676 | goto cleanup; | 675 | goto cleanup; |
677 | } | 676 | } |
678 | 677 | ||
678 | mutex_lock(&info->port.mutex); | ||
679 | info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 679 | info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
680 | 680 | ||
681 | spin_lock_irqsave(&info->netlock, flags); | 681 | spin_lock_irqsave(&info->netlock, flags); |
682 | if (info->netcount) { | 682 | if (info->netcount) { |
683 | retval = -EBUSY; | 683 | retval = -EBUSY; |
684 | spin_unlock_irqrestore(&info->netlock, flags); | 684 | spin_unlock_irqrestore(&info->netlock, flags); |
685 | mutex_unlock(&info->port.mutex); | ||
685 | goto cleanup; | 686 | goto cleanup; |
686 | } | 687 | } |
687 | info->port.count++; | 688 | info->port.count++; |
@@ -693,7 +694,7 @@ static int open(struct tty_struct *tty, struct file *filp) | |||
693 | if (retval < 0) | 694 | if (retval < 0) |
694 | goto cleanup; | 695 | goto cleanup; |
695 | } | 696 | } |
696 | 697 | mutex_unlock(&info->port.mutex); | |
697 | retval = block_til_ready(tty, filp, info); | 698 | retval = block_til_ready(tty, filp, info); |
698 | if (retval) { | 699 | if (retval) { |
699 | DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); | 700 | DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); |
@@ -725,12 +726,14 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
725 | if (tty_port_close_start(&info->port, tty, filp) == 0) | 726 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
726 | goto cleanup; | 727 | goto cleanup; |
727 | 728 | ||
729 | mutex_lock(&info->port.mutex); | ||
728 | if (info->port.flags & ASYNC_INITIALIZED) | 730 | if (info->port.flags & ASYNC_INITIALIZED) |
729 | wait_until_sent(tty, info->timeout); | 731 | wait_until_sent(tty, info->timeout); |
730 | flush_buffer(tty); | 732 | flush_buffer(tty); |
731 | tty_ldisc_flush(tty); | 733 | tty_ldisc_flush(tty); |
732 | 734 | ||
733 | shutdown(info); | 735 | shutdown(info); |
736 | mutex_unlock(&info->port.mutex); | ||
734 | 737 | ||
735 | tty_port_close_end(&info->port, tty); | 738 | tty_port_close_end(&info->port, tty); |
736 | info->port.tty = NULL; | 739 | info->port.tty = NULL; |
@@ -741,17 +744,23 @@ cleanup: | |||
741 | static void hangup(struct tty_struct *tty) | 744 | static void hangup(struct tty_struct *tty) |
742 | { | 745 | { |
743 | struct slgt_info *info = tty->driver_data; | 746 | struct slgt_info *info = tty->driver_data; |
747 | unsigned long flags; | ||
744 | 748 | ||
745 | if (sanity_check(info, tty->name, "hangup")) | 749 | if (sanity_check(info, tty->name, "hangup")) |
746 | return; | 750 | return; |
747 | DBGINFO(("%s hangup\n", info->device_name)); | 751 | DBGINFO(("%s hangup\n", info->device_name)); |
748 | 752 | ||
749 | flush_buffer(tty); | 753 | flush_buffer(tty); |
754 | |||
755 | mutex_lock(&info->port.mutex); | ||
750 | shutdown(info); | 756 | shutdown(info); |
751 | 757 | ||
758 | spin_lock_irqsave(&info->port.lock, flags); | ||
752 | info->port.count = 0; | 759 | info->port.count = 0; |
753 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 760 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
754 | info->port.tty = NULL; | 761 | info->port.tty = NULL; |
762 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
763 | mutex_unlock(&info->port.mutex); | ||
755 | 764 | ||
756 | wake_up_interruptible(&info->port.open_wait); | 765 | wake_up_interruptible(&info->port.open_wait); |
757 | } | 766 | } |
@@ -901,8 +910,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
901 | * Note: use tight timings here to satisfy the NIST-PCTS. | 910 | * Note: use tight timings here to satisfy the NIST-PCTS. |
902 | */ | 911 | */ |
903 | 912 | ||
904 | lock_kernel(); | ||
905 | |||
906 | if (info->params.data_rate) { | 913 | if (info->params.data_rate) { |
907 | char_time = info->timeout/(32 * 5); | 914 | char_time = info->timeout/(32 * 5); |
908 | if (!char_time) | 915 | if (!char_time) |
@@ -920,8 +927,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
920 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | 927 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) |
921 | break; | 928 | break; |
922 | } | 929 | } |
923 | unlock_kernel(); | ||
924 | |||
925 | exit: | 930 | exit: |
926 | DBGINFO(("%s wait_until_sent exit\n", info->device_name)); | 931 | DBGINFO(("%s wait_until_sent exit\n", info->device_name)); |
927 | } | 932 | } |
@@ -1041,8 +1046,37 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1041 | return -EIO; | 1046 | return -EIO; |
1042 | } | 1047 | } |
1043 | 1048 | ||
1044 | lock_kernel(); | 1049 | switch (cmd) { |
1045 | 1050 | case MGSL_IOCWAITEVENT: | |
1051 | return wait_mgsl_event(info, argp); | ||
1052 | case TIOCMIWAIT: | ||
1053 | return modem_input_wait(info,(int)arg); | ||
1054 | case TIOCGICOUNT: | ||
1055 | spin_lock_irqsave(&info->lock,flags); | ||
1056 | cnow = info->icount; | ||
1057 | spin_unlock_irqrestore(&info->lock,flags); | ||
1058 | p_cuser = argp; | ||
1059 | if (put_user(cnow.cts, &p_cuser->cts) || | ||
1060 | put_user(cnow.dsr, &p_cuser->dsr) || | ||
1061 | put_user(cnow.rng, &p_cuser->rng) || | ||
1062 | put_user(cnow.dcd, &p_cuser->dcd) || | ||
1063 | put_user(cnow.rx, &p_cuser->rx) || | ||
1064 | put_user(cnow.tx, &p_cuser->tx) || | ||
1065 | put_user(cnow.frame, &p_cuser->frame) || | ||
1066 | put_user(cnow.overrun, &p_cuser->overrun) || | ||
1067 | put_user(cnow.parity, &p_cuser->parity) || | ||
1068 | put_user(cnow.brk, &p_cuser->brk) || | ||
1069 | put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) | ||
1070 | return -EFAULT; | ||
1071 | return 0; | ||
1072 | case MGSL_IOCSGPIO: | ||
1073 | return set_gpio(info, argp); | ||
1074 | case MGSL_IOCGGPIO: | ||
1075 | return get_gpio(info, argp); | ||
1076 | case MGSL_IOCWAITGPIO: | ||
1077 | return wait_gpio(info, argp); | ||
1078 | } | ||
1079 | mutex_lock(&info->port.mutex); | ||
1046 | switch (cmd) { | 1080 | switch (cmd) { |
1047 | case MGSL_IOCGPARAMS: | 1081 | case MGSL_IOCGPARAMS: |
1048 | ret = get_params(info, argp); | 1082 | ret = get_params(info, argp); |
@@ -1068,50 +1102,16 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1068 | case MGSL_IOCGSTATS: | 1102 | case MGSL_IOCGSTATS: |
1069 | ret = get_stats(info, argp); | 1103 | ret = get_stats(info, argp); |
1070 | break; | 1104 | break; |
1071 | case MGSL_IOCWAITEVENT: | ||
1072 | ret = wait_mgsl_event(info, argp); | ||
1073 | break; | ||
1074 | case TIOCMIWAIT: | ||
1075 | ret = modem_input_wait(info,(int)arg); | ||
1076 | break; | ||
1077 | case MGSL_IOCGIF: | 1105 | case MGSL_IOCGIF: |
1078 | ret = get_interface(info, argp); | 1106 | ret = get_interface(info, argp); |
1079 | break; | 1107 | break; |
1080 | case MGSL_IOCSIF: | 1108 | case MGSL_IOCSIF: |
1081 | ret = set_interface(info,(int)arg); | 1109 | ret = set_interface(info,(int)arg); |
1082 | break; | 1110 | break; |
1083 | case MGSL_IOCSGPIO: | ||
1084 | ret = set_gpio(info, argp); | ||
1085 | break; | ||
1086 | case MGSL_IOCGGPIO: | ||
1087 | ret = get_gpio(info, argp); | ||
1088 | break; | ||
1089 | case MGSL_IOCWAITGPIO: | ||
1090 | ret = wait_gpio(info, argp); | ||
1091 | break; | ||
1092 | case TIOCGICOUNT: | ||
1093 | spin_lock_irqsave(&info->lock,flags); | ||
1094 | cnow = info->icount; | ||
1095 | spin_unlock_irqrestore(&info->lock,flags); | ||
1096 | p_cuser = argp; | ||
1097 | if (put_user(cnow.cts, &p_cuser->cts) || | ||
1098 | put_user(cnow.dsr, &p_cuser->dsr) || | ||
1099 | put_user(cnow.rng, &p_cuser->rng) || | ||
1100 | put_user(cnow.dcd, &p_cuser->dcd) || | ||
1101 | put_user(cnow.rx, &p_cuser->rx) || | ||
1102 | put_user(cnow.tx, &p_cuser->tx) || | ||
1103 | put_user(cnow.frame, &p_cuser->frame) || | ||
1104 | put_user(cnow.overrun, &p_cuser->overrun) || | ||
1105 | put_user(cnow.parity, &p_cuser->parity) || | ||
1106 | put_user(cnow.brk, &p_cuser->brk) || | ||
1107 | put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) | ||
1108 | ret = -EFAULT; | ||
1109 | ret = 0; | ||
1110 | break; | ||
1111 | default: | 1111 | default: |
1112 | ret = -ENOIOCTLCMD; | 1112 | ret = -ENOIOCTLCMD; |
1113 | } | 1113 | } |
1114 | unlock_kernel(); | 1114 | mutex_unlock(&info->port.mutex); |
1115 | return ret; | 1115 | return ret; |
1116 | } | 1116 | } |
1117 | 1117 | ||
@@ -3244,7 +3244,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3244 | } | 3244 | } |
3245 | 3245 | ||
3246 | DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); | 3246 | DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); |
3247 | tty_unlock(); | ||
3247 | schedule(); | 3248 | schedule(); |
3249 | tty_lock(); | ||
3248 | } | 3250 | } |
3249 | 3251 | ||
3250 | set_current_state(TASK_RUNNING); | 3252 | set_current_state(TASK_RUNNING); |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 2b18adc4ee19..e56caf7d82aa 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <linux/mm.h> | 52 | #include <linux/mm.h> |
53 | #include <linux/seq_file.h> | 53 | #include <linux/seq_file.h> |
54 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
55 | #include <linux/smp_lock.h> | ||
56 | #include <linux/netdevice.h> | 55 | #include <linux/netdevice.h> |
57 | #include <linux/vmalloc.h> | 56 | #include <linux/vmalloc.h> |
58 | #include <linux/init.h> | 57 | #include <linux/init.h> |
@@ -813,13 +812,15 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
813 | 812 | ||
814 | if (tty_port_close_start(&info->port, tty, filp) == 0) | 813 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
815 | goto cleanup; | 814 | goto cleanup; |
816 | 815 | ||
816 | mutex_lock(&info->port.mutex); | ||
817 | if (info->port.flags & ASYNC_INITIALIZED) | 817 | if (info->port.flags & ASYNC_INITIALIZED) |
818 | wait_until_sent(tty, info->timeout); | 818 | wait_until_sent(tty, info->timeout); |
819 | 819 | ||
820 | flush_buffer(tty); | 820 | flush_buffer(tty); |
821 | tty_ldisc_flush(tty); | 821 | tty_ldisc_flush(tty); |
822 | shutdown(info); | 822 | shutdown(info); |
823 | mutex_unlock(&info->port.mutex); | ||
823 | 824 | ||
824 | tty_port_close_end(&info->port, tty); | 825 | tty_port_close_end(&info->port, tty); |
825 | info->port.tty = NULL; | 826 | info->port.tty = NULL; |
@@ -835,6 +836,7 @@ cleanup: | |||
835 | static void hangup(struct tty_struct *tty) | 836 | static void hangup(struct tty_struct *tty) |
836 | { | 837 | { |
837 | SLMP_INFO *info = tty->driver_data; | 838 | SLMP_INFO *info = tty->driver_data; |
839 | unsigned long flags; | ||
838 | 840 | ||
839 | if (debug_level >= DEBUG_LEVEL_INFO) | 841 | if (debug_level >= DEBUG_LEVEL_INFO) |
840 | printk("%s(%d):%s hangup()\n", | 842 | printk("%s(%d):%s hangup()\n", |
@@ -843,12 +845,16 @@ static void hangup(struct tty_struct *tty) | |||
843 | if (sanity_check(info, tty->name, "hangup")) | 845 | if (sanity_check(info, tty->name, "hangup")) |
844 | return; | 846 | return; |
845 | 847 | ||
848 | mutex_lock(&info->port.mutex); | ||
846 | flush_buffer(tty); | 849 | flush_buffer(tty); |
847 | shutdown(info); | 850 | shutdown(info); |
848 | 851 | ||
852 | spin_lock_irqsave(&info->port.lock, flags); | ||
849 | info->port.count = 0; | 853 | info->port.count = 0; |
850 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 854 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
851 | info->port.tty = NULL; | 855 | info->port.tty = NULL; |
856 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
857 | mutex_unlock(&info->port.mutex); | ||
852 | 858 | ||
853 | wake_up_interruptible(&info->port.open_wait); | 859 | wake_up_interruptible(&info->port.open_wait); |
854 | } | 860 | } |
@@ -1062,9 +1068,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
1062 | if (sanity_check(info, tty->name, "wait_until_sent")) | 1068 | if (sanity_check(info, tty->name, "wait_until_sent")) |
1063 | return; | 1069 | return; |
1064 | 1070 | ||
1065 | lock_kernel(); | 1071 | if (!test_bit(ASYNCB_INITIALIZED, &info->port.flags)) |
1066 | |||
1067 | if (!(info->port.flags & ASYNC_INITIALIZED)) | ||
1068 | goto exit; | 1072 | goto exit; |
1069 | 1073 | ||
1070 | orig_jiffies = jiffies; | 1074 | orig_jiffies = jiffies; |
@@ -1094,8 +1098,10 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
1094 | break; | 1098 | break; |
1095 | } | 1099 | } |
1096 | } else { | 1100 | } else { |
1097 | //TODO: determine if there is something similar to USC16C32 | 1101 | /* |
1098 | // TXSTATUS_ALL_SENT status | 1102 | * TODO: determine if there is something similar to USC16C32 |
1103 | * TXSTATUS_ALL_SENT status | ||
1104 | */ | ||
1099 | while ( info->tx_active && info->tx_enabled) { | 1105 | while ( info->tx_active && info->tx_enabled) { |
1100 | msleep_interruptible(jiffies_to_msecs(char_time)); | 1106 | msleep_interruptible(jiffies_to_msecs(char_time)); |
1101 | if (signal_pending(current)) | 1107 | if (signal_pending(current)) |
@@ -1106,7 +1112,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
1106 | } | 1112 | } |
1107 | 1113 | ||
1108 | exit: | 1114 | exit: |
1109 | unlock_kernel(); | ||
1110 | if (debug_level >= DEBUG_LEVEL_INFO) | 1115 | if (debug_level >= DEBUG_LEVEL_INFO) |
1111 | printk("%s(%d):%s wait_until_sent() exit\n", | 1116 | printk("%s(%d):%s wait_until_sent() exit\n", |
1112 | __FILE__,__LINE__, info->device_name ); | 1117 | __FILE__,__LINE__, info->device_name ); |
@@ -1122,7 +1127,6 @@ static int write_room(struct tty_struct *tty) | |||
1122 | if (sanity_check(info, tty->name, "write_room")) | 1127 | if (sanity_check(info, tty->name, "write_room")) |
1123 | return 0; | 1128 | return 0; |
1124 | 1129 | ||
1125 | lock_kernel(); | ||
1126 | if (info->params.mode == MGSL_MODE_HDLC) { | 1130 | if (info->params.mode == MGSL_MODE_HDLC) { |
1127 | ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; | 1131 | ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; |
1128 | } else { | 1132 | } else { |
@@ -1130,7 +1134,6 @@ static int write_room(struct tty_struct *tty) | |||
1130 | if (ret < 0) | 1134 | if (ret < 0) |
1131 | ret = 0; | 1135 | ret = 0; |
1132 | } | 1136 | } |
1133 | unlock_kernel(); | ||
1134 | 1137 | ||
1135 | if (debug_level >= DEBUG_LEVEL_INFO) | 1138 | if (debug_level >= DEBUG_LEVEL_INFO) |
1136 | printk("%s(%d):%s write_room()=%d\n", | 1139 | printk("%s(%d):%s write_room()=%d\n", |
@@ -1251,7 +1254,7 @@ static void tx_release(struct tty_struct *tty) | |||
1251 | * | 1254 | * |
1252 | * Return Value: 0 if success, otherwise error code | 1255 | * Return Value: 0 if success, otherwise error code |
1253 | */ | 1256 | */ |
1254 | static int do_ioctl(struct tty_struct *tty, struct file *file, | 1257 | static int ioctl(struct tty_struct *tty, struct file *file, |
1255 | unsigned int cmd, unsigned long arg) | 1258 | unsigned int cmd, unsigned long arg) |
1256 | { | 1259 | { |
1257 | SLMP_INFO *info = tty->driver_data; | 1260 | SLMP_INFO *info = tty->driver_data; |
@@ -1341,16 +1344,6 @@ static int do_ioctl(struct tty_struct *tty, struct file *file, | |||
1341 | return 0; | 1344 | return 0; |
1342 | } | 1345 | } |
1343 | 1346 | ||
1344 | static int ioctl(struct tty_struct *tty, struct file *file, | ||
1345 | unsigned int cmd, unsigned long arg) | ||
1346 | { | ||
1347 | int ret; | ||
1348 | lock_kernel(); | ||
1349 | ret = do_ioctl(tty, file, cmd, arg); | ||
1350 | unlock_kernel(); | ||
1351 | return ret; | ||
1352 | } | ||
1353 | |||
1354 | /* | 1347 | /* |
1355 | * /proc fs routines.... | 1348 | * /proc fs routines.... |
1356 | */ | 1349 | */ |
@@ -2883,7 +2876,9 @@ static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount) | |||
2883 | if (!user_icount) { | 2876 | if (!user_icount) { |
2884 | memset(&info->icount, 0, sizeof(info->icount)); | 2877 | memset(&info->icount, 0, sizeof(info->icount)); |
2885 | } else { | 2878 | } else { |
2879 | mutex_lock(&info->port.mutex); | ||
2886 | COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); | 2880 | COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); |
2881 | mutex_unlock(&info->port.mutex); | ||
2887 | if (err) | 2882 | if (err) |
2888 | return -EFAULT; | 2883 | return -EFAULT; |
2889 | } | 2884 | } |
@@ -2898,7 +2893,9 @@ static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params) | |||
2898 | printk("%s(%d):%s get_params()\n", | 2893 | printk("%s(%d):%s get_params()\n", |
2899 | __FILE__,__LINE__, info->device_name); | 2894 | __FILE__,__LINE__, info->device_name); |
2900 | 2895 | ||
2896 | mutex_lock(&info->port.mutex); | ||
2901 | COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); | 2897 | COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); |
2898 | mutex_unlock(&info->port.mutex); | ||
2902 | if (err) { | 2899 | if (err) { |
2903 | if ( debug_level >= DEBUG_LEVEL_INFO ) | 2900 | if ( debug_level >= DEBUG_LEVEL_INFO ) |
2904 | printk( "%s(%d):%s get_params() user buffer copy failed\n", | 2901 | printk( "%s(%d):%s get_params() user buffer copy failed\n", |
@@ -2926,11 +2923,13 @@ static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params) | |||
2926 | return -EFAULT; | 2923 | return -EFAULT; |
2927 | } | 2924 | } |
2928 | 2925 | ||
2926 | mutex_lock(&info->port.mutex); | ||
2929 | spin_lock_irqsave(&info->lock,flags); | 2927 | spin_lock_irqsave(&info->lock,flags); |
2930 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); | 2928 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); |
2931 | spin_unlock_irqrestore(&info->lock,flags); | 2929 | spin_unlock_irqrestore(&info->lock,flags); |
2932 | 2930 | ||
2933 | change_params(info); | 2931 | change_params(info); |
2932 | mutex_unlock(&info->port.mutex); | ||
2934 | 2933 | ||
2935 | return 0; | 2934 | return 0; |
2936 | } | 2935 | } |
@@ -3366,7 +3365,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3366 | printk("%s(%d):%s block_til_ready() count=%d\n", | 3365 | printk("%s(%d):%s block_til_ready() count=%d\n", |
3367 | __FILE__,__LINE__, tty->driver->name, port->count ); | 3366 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3368 | 3367 | ||
3368 | tty_unlock(); | ||
3369 | schedule(); | 3369 | schedule(); |
3370 | tty_lock(); | ||
3370 | } | 3371 | } |
3371 | 3372 | ||
3372 | set_current_state(TASK_RUNNING); | 3373 | set_current_state(TASK_RUNNING); |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 507441ac6edb..0350c42375a2 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -149,6 +149,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, | |||
149 | #else | 149 | #else |
150 | #define tty_compat_ioctl NULL | 150 | #define tty_compat_ioctl NULL |
151 | #endif | 151 | #endif |
152 | static int __tty_fasync(int fd, struct file *filp, int on); | ||
152 | static int tty_fasync(int fd, struct file *filp, int on); | 153 | static int tty_fasync(int fd, struct file *filp, int on); |
153 | static void release_tty(struct tty_struct *tty, int idx); | 154 | static void release_tty(struct tty_struct *tty, int idx); |
154 | static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); | 155 | static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); |
@@ -470,7 +471,7 @@ void tty_wakeup(struct tty_struct *tty) | |||
470 | EXPORT_SYMBOL_GPL(tty_wakeup); | 471 | EXPORT_SYMBOL_GPL(tty_wakeup); |
471 | 472 | ||
472 | /** | 473 | /** |
473 | * do_tty_hangup - actual handler for hangup events | 474 | * __tty_hangup - actual handler for hangup events |
474 | * @work: tty device | 475 | * @work: tty device |
475 | * | 476 | * |
476 | * This can be called by the "eventd" kernel thread. That is process | 477 | * This can be called by the "eventd" kernel thread. That is process |
@@ -483,7 +484,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup); | |||
483 | * remains intact. | 484 | * remains intact. |
484 | * | 485 | * |
485 | * Locking: | 486 | * Locking: |
486 | * BKL | 487 | * BTM |
487 | * redirect lock for undoing redirection | 488 | * redirect lock for undoing redirection |
488 | * file list lock for manipulating list of ttys | 489 | * file list lock for manipulating list of ttys |
489 | * tty_ldisc_lock from called functions | 490 | * tty_ldisc_lock from called functions |
@@ -491,10 +492,8 @@ EXPORT_SYMBOL_GPL(tty_wakeup); | |||
491 | * tasklist_lock to walk task list for hangup event | 492 | * tasklist_lock to walk task list for hangup event |
492 | * ->siglock to protect ->signal/->sighand | 493 | * ->siglock to protect ->signal/->sighand |
493 | */ | 494 | */ |
494 | static void do_tty_hangup(struct work_struct *work) | 495 | void __tty_hangup(struct tty_struct *tty) |
495 | { | 496 | { |
496 | struct tty_struct *tty = | ||
497 | container_of(work, struct tty_struct, hangup_work); | ||
498 | struct file *cons_filp = NULL; | 497 | struct file *cons_filp = NULL; |
499 | struct file *filp, *f = NULL; | 498 | struct file *filp, *f = NULL; |
500 | struct task_struct *p; | 499 | struct task_struct *p; |
@@ -513,9 +512,12 @@ static void do_tty_hangup(struct work_struct *work) | |||
513 | } | 512 | } |
514 | spin_unlock(&redirect_lock); | 513 | spin_unlock(&redirect_lock); |
515 | 514 | ||
516 | /* inuse_filps is protected by the single kernel lock */ | 515 | tty_lock(); |
517 | lock_kernel(); | 516 | |
518 | check_tty_count(tty, "do_tty_hangup"); | 517 | /* inuse_filps is protected by the single tty lock, |
518 | this really needs to change if we want to flush the | ||
519 | workqueue with the lock held */ | ||
520 | check_tty_count(tty, "tty_hangup"); | ||
519 | 521 | ||
520 | file_list_lock(); | 522 | file_list_lock(); |
521 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ | 523 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ |
@@ -525,7 +527,7 @@ static void do_tty_hangup(struct work_struct *work) | |||
525 | if (filp->f_op->write != tty_write) | 527 | if (filp->f_op->write != tty_write) |
526 | continue; | 528 | continue; |
527 | closecount++; | 529 | closecount++; |
528 | tty_fasync(-1, filp, 0); /* can't block */ | 530 | __tty_fasync(-1, filp, 0); /* can't block */ |
529 | filp->f_op = &hung_up_tty_fops; | 531 | filp->f_op = &hung_up_tty_fops; |
530 | } | 532 | } |
531 | file_list_unlock(); | 533 | file_list_unlock(); |
@@ -594,11 +596,21 @@ static void do_tty_hangup(struct work_struct *work) | |||
594 | */ | 596 | */ |
595 | set_bit(TTY_HUPPED, &tty->flags); | 597 | set_bit(TTY_HUPPED, &tty->flags); |
596 | tty_ldisc_enable(tty); | 598 | tty_ldisc_enable(tty); |
597 | unlock_kernel(); | 599 | |
600 | tty_unlock(); | ||
601 | |||
598 | if (f) | 602 | if (f) |
599 | fput(f); | 603 | fput(f); |
600 | } | 604 | } |
601 | 605 | ||
606 | static void do_tty_hangup(struct work_struct *work) | ||
607 | { | ||
608 | struct tty_struct *tty = | ||
609 | container_of(work, struct tty_struct, hangup_work); | ||
610 | |||
611 | __tty_hangup(tty); | ||
612 | } | ||
613 | |||
602 | /** | 614 | /** |
603 | * tty_hangup - trigger a hangup event | 615 | * tty_hangup - trigger a hangup event |
604 | * @tty: tty to hangup | 616 | * @tty: tty to hangup |
@@ -634,11 +646,12 @@ void tty_vhangup(struct tty_struct *tty) | |||
634 | 646 | ||
635 | printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); | 647 | printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); |
636 | #endif | 648 | #endif |
637 | do_tty_hangup(&tty->hangup_work); | 649 | __tty_hangup(tty); |
638 | } | 650 | } |
639 | 651 | ||
640 | EXPORT_SYMBOL(tty_vhangup); | 652 | EXPORT_SYMBOL(tty_vhangup); |
641 | 653 | ||
654 | |||
642 | /** | 655 | /** |
643 | * tty_vhangup_self - process vhangup for own ctty | 656 | * tty_vhangup_self - process vhangup for own ctty |
644 | * | 657 | * |
@@ -696,7 +709,8 @@ static void session_clear_tty(struct pid *session) | |||
696 | * exiting; it is 0 if called by the ioctl TIOCNOTTY. | 709 | * exiting; it is 0 if called by the ioctl TIOCNOTTY. |
697 | * | 710 | * |
698 | * Locking: | 711 | * Locking: |
699 | * BKL is taken for hysterical raisins | 712 | * BTM is taken for hysterical raisins, and held when |
713 | * called from no_tty(). | ||
700 | * tty_mutex is taken to protect tty | 714 | * tty_mutex is taken to protect tty |
701 | * ->siglock is taken to protect ->signal/->sighand | 715 | * ->siglock is taken to protect ->signal/->sighand |
702 | * tasklist_lock is taken to walk process list for sessions | 716 | * tasklist_lock is taken to walk process list for sessions |
@@ -714,10 +728,10 @@ void disassociate_ctty(int on_exit) | |||
714 | tty = get_current_tty(); | 728 | tty = get_current_tty(); |
715 | if (tty) { | 729 | if (tty) { |
716 | tty_pgrp = get_pid(tty->pgrp); | 730 | tty_pgrp = get_pid(tty->pgrp); |
717 | lock_kernel(); | 731 | if (on_exit) { |
718 | if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) | 732 | if (tty->driver->type != TTY_DRIVER_TYPE_PTY) |
719 | tty_vhangup(tty); | 733 | tty_vhangup(tty); |
720 | unlock_kernel(); | 734 | } |
721 | tty_kref_put(tty); | 735 | tty_kref_put(tty); |
722 | } else if (on_exit) { | 736 | } else if (on_exit) { |
723 | struct pid *old_pgrp; | 737 | struct pid *old_pgrp; |
@@ -774,9 +788,9 @@ void disassociate_ctty(int on_exit) | |||
774 | void no_tty(void) | 788 | void no_tty(void) |
775 | { | 789 | { |
776 | struct task_struct *tsk = current; | 790 | struct task_struct *tsk = current; |
777 | lock_kernel(); | 791 | tty_lock(); |
778 | disassociate_ctty(0); | 792 | disassociate_ctty(0); |
779 | unlock_kernel(); | 793 | tty_unlock(); |
780 | proc_clear_tty(tsk); | 794 | proc_clear_tty(tsk); |
781 | } | 795 | } |
782 | 796 | ||
@@ -879,7 +893,7 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, | |||
879 | struct inode *inode; | 893 | struct inode *inode; |
880 | struct tty_ldisc *ld; | 894 | struct tty_ldisc *ld; |
881 | 895 | ||
882 | tty = (struct tty_struct *)file->private_data; | 896 | tty = file->private_data; |
883 | inode = file->f_path.dentry->d_inode; | 897 | inode = file->f_path.dentry->d_inode; |
884 | if (tty_paranoia_check(tty, inode, "tty_read")) | 898 | if (tty_paranoia_check(tty, inode, "tty_read")) |
885 | return -EIO; | 899 | return -EIO; |
@@ -1013,19 +1027,19 @@ out: | |||
1013 | * We don't put it into the syslog queue right now maybe in the future if | 1027 | * We don't put it into the syslog queue right now maybe in the future if |
1014 | * really needed. | 1028 | * really needed. |
1015 | * | 1029 | * |
1016 | * We must still hold the BKL and test the CLOSING flag for the moment. | 1030 | * We must still hold the BTM and test the CLOSING flag for the moment. |
1017 | */ | 1031 | */ |
1018 | 1032 | ||
1019 | void tty_write_message(struct tty_struct *tty, char *msg) | 1033 | void tty_write_message(struct tty_struct *tty, char *msg) |
1020 | { | 1034 | { |
1021 | if (tty) { | 1035 | if (tty) { |
1022 | mutex_lock(&tty->atomic_write_lock); | 1036 | mutex_lock(&tty->atomic_write_lock); |
1023 | lock_kernel(); | 1037 | tty_lock(); |
1024 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { | 1038 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { |
1025 | unlock_kernel(); | 1039 | tty_unlock(); |
1026 | tty->ops->write(tty, msg, strlen(msg)); | 1040 | tty->ops->write(tty, msg, strlen(msg)); |
1027 | } else | 1041 | } else |
1028 | unlock_kernel(); | 1042 | tty_unlock(); |
1029 | tty_write_unlock(tty); | 1043 | tty_write_unlock(tty); |
1030 | } | 1044 | } |
1031 | return; | 1045 | return; |
@@ -1056,7 +1070,7 @@ static ssize_t tty_write(struct file *file, const char __user *buf, | |||
1056 | ssize_t ret; | 1070 | ssize_t ret; |
1057 | struct tty_ldisc *ld; | 1071 | struct tty_ldisc *ld; |
1058 | 1072 | ||
1059 | tty = (struct tty_struct *)file->private_data; | 1073 | tty = file->private_data; |
1060 | if (tty_paranoia_check(tty, inode, "tty_write")) | 1074 | if (tty_paranoia_check(tty, inode, "tty_write")) |
1061 | return -EIO; | 1075 | return -EIO; |
1062 | if (!tty || !tty->ops->write || | 1076 | if (!tty || !tty->ops->write || |
@@ -1208,18 +1222,14 @@ static int tty_driver_install_tty(struct tty_driver *driver, | |||
1208 | int ret; | 1222 | int ret; |
1209 | 1223 | ||
1210 | if (driver->ops->install) { | 1224 | if (driver->ops->install) { |
1211 | lock_kernel(); | ||
1212 | ret = driver->ops->install(driver, tty); | 1225 | ret = driver->ops->install(driver, tty); |
1213 | unlock_kernel(); | ||
1214 | return ret; | 1226 | return ret; |
1215 | } | 1227 | } |
1216 | 1228 | ||
1217 | if (tty_init_termios(tty) == 0) { | 1229 | if (tty_init_termios(tty) == 0) { |
1218 | lock_kernel(); | ||
1219 | tty_driver_kref_get(driver); | 1230 | tty_driver_kref_get(driver); |
1220 | tty->count++; | 1231 | tty->count++; |
1221 | driver->ttys[idx] = tty; | 1232 | driver->ttys[idx] = tty; |
1222 | unlock_kernel(); | ||
1223 | return 0; | 1233 | return 0; |
1224 | } | 1234 | } |
1225 | return -ENOMEM; | 1235 | return -ENOMEM; |
@@ -1312,14 +1322,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
1312 | struct tty_struct *tty; | 1322 | struct tty_struct *tty; |
1313 | int retval; | 1323 | int retval; |
1314 | 1324 | ||
1315 | lock_kernel(); | ||
1316 | /* Check if pty master is being opened multiple times */ | 1325 | /* Check if pty master is being opened multiple times */ |
1317 | if (driver->subtype == PTY_TYPE_MASTER && | 1326 | if (driver->subtype == PTY_TYPE_MASTER && |
1318 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { | 1327 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { |
1319 | unlock_kernel(); | ||
1320 | return ERR_PTR(-EIO); | 1328 | return ERR_PTR(-EIO); |
1321 | } | 1329 | } |
1322 | unlock_kernel(); | ||
1323 | 1330 | ||
1324 | /* | 1331 | /* |
1325 | * First time open is complex, especially for PTY devices. | 1332 | * First time open is complex, especially for PTY devices. |
@@ -1363,9 +1370,7 @@ release_mem_out: | |||
1363 | if (printk_ratelimit()) | 1370 | if (printk_ratelimit()) |
1364 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " | 1371 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " |
1365 | "clearing slot %d\n", idx); | 1372 | "clearing slot %d\n", idx); |
1366 | lock_kernel(); | ||
1367 | release_tty(tty, idx); | 1373 | release_tty(tty, idx); |
1368 | unlock_kernel(); | ||
1369 | return ERR_PTR(retval); | 1374 | return ERR_PTR(retval); |
1370 | } | 1375 | } |
1371 | 1376 | ||
@@ -1508,14 +1513,14 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1508 | int idx; | 1513 | int idx; |
1509 | char buf[64]; | 1514 | char buf[64]; |
1510 | 1515 | ||
1511 | tty = (struct tty_struct *)filp->private_data; | 1516 | tty = filp->private_data; |
1512 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) | 1517 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) |
1513 | return 0; | 1518 | return 0; |
1514 | 1519 | ||
1515 | lock_kernel(); | 1520 | tty_lock(); |
1516 | check_tty_count(tty, "tty_release_dev"); | 1521 | check_tty_count(tty, "tty_release_dev"); |
1517 | 1522 | ||
1518 | tty_fasync(-1, filp, 0); | 1523 | __tty_fasync(-1, filp, 0); |
1519 | 1524 | ||
1520 | idx = tty->index; | 1525 | idx = tty->index; |
1521 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1526 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
@@ -1527,18 +1532,18 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1527 | if (idx < 0 || idx >= tty->driver->num) { | 1532 | if (idx < 0 || idx >= tty->driver->num) { |
1528 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " | 1533 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " |
1529 | "free (%s)\n", tty->name); | 1534 | "free (%s)\n", tty->name); |
1530 | unlock_kernel(); | 1535 | tty_unlock(); |
1531 | return 0; | 1536 | return 0; |
1532 | } | 1537 | } |
1533 | if (!devpts) { | 1538 | if (!devpts) { |
1534 | if (tty != tty->driver->ttys[idx]) { | 1539 | if (tty != tty->driver->ttys[idx]) { |
1535 | unlock_kernel(); | 1540 | tty_unlock(); |
1536 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " | 1541 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " |
1537 | "for (%s)\n", idx, tty->name); | 1542 | "for (%s)\n", idx, tty->name); |
1538 | return 0; | 1543 | return 0; |
1539 | } | 1544 | } |
1540 | if (tty->termios != tty->driver->termios[idx]) { | 1545 | if (tty->termios != tty->driver->termios[idx]) { |
1541 | unlock_kernel(); | 1546 | tty_unlock(); |
1542 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " | 1547 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " |
1543 | "for (%s)\n", | 1548 | "for (%s)\n", |
1544 | idx, tty->name); | 1549 | idx, tty->name); |
@@ -1556,21 +1561,21 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1556 | if (tty->driver->other && | 1561 | if (tty->driver->other && |
1557 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | 1562 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { |
1558 | if (o_tty != tty->driver->other->ttys[idx]) { | 1563 | if (o_tty != tty->driver->other->ttys[idx]) { |
1559 | unlock_kernel(); | 1564 | tty_unlock(); |
1560 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " | 1565 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " |
1561 | "not o_tty for (%s)\n", | 1566 | "not o_tty for (%s)\n", |
1562 | idx, tty->name); | 1567 | idx, tty->name); |
1563 | return 0 ; | 1568 | return 0 ; |
1564 | } | 1569 | } |
1565 | if (o_tty->termios != tty->driver->other->termios[idx]) { | 1570 | if (o_tty->termios != tty->driver->other->termios[idx]) { |
1566 | unlock_kernel(); | 1571 | tty_unlock(); |
1567 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " | 1572 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " |
1568 | "not o_termios for (%s)\n", | 1573 | "not o_termios for (%s)\n", |
1569 | idx, tty->name); | 1574 | idx, tty->name); |
1570 | return 0; | 1575 | return 0; |
1571 | } | 1576 | } |
1572 | if (o_tty->link != tty) { | 1577 | if (o_tty->link != tty) { |
1573 | unlock_kernel(); | 1578 | tty_unlock(); |
1574 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); | 1579 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); |
1575 | return 0; | 1580 | return 0; |
1576 | } | 1581 | } |
@@ -1579,7 +1584,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1579 | if (tty->ops->close) | 1584 | if (tty->ops->close) |
1580 | tty->ops->close(tty, filp); | 1585 | tty->ops->close(tty, filp); |
1581 | 1586 | ||
1582 | unlock_kernel(); | 1587 | tty_unlock(); |
1583 | /* | 1588 | /* |
1584 | * Sanity check: if tty->count is going to zero, there shouldn't be | 1589 | * Sanity check: if tty->count is going to zero, there shouldn't be |
1585 | * any waiters on tty->read_wait or tty->write_wait. We test the | 1590 | * any waiters on tty->read_wait or tty->write_wait. We test the |
@@ -1602,7 +1607,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1602 | opens on /dev/tty */ | 1607 | opens on /dev/tty */ |
1603 | 1608 | ||
1604 | mutex_lock(&tty_mutex); | 1609 | mutex_lock(&tty_mutex); |
1605 | lock_kernel(); | 1610 | tty_lock(); |
1606 | tty_closing = tty->count <= 1; | 1611 | tty_closing = tty->count <= 1; |
1607 | o_tty_closing = o_tty && | 1612 | o_tty_closing = o_tty && |
1608 | (o_tty->count <= (pty_master ? 1 : 0)); | 1613 | (o_tty->count <= (pty_master ? 1 : 0)); |
@@ -1633,7 +1638,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1633 | 1638 | ||
1634 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " | 1639 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " |
1635 | "active!\n", tty_name(tty, buf)); | 1640 | "active!\n", tty_name(tty, buf)); |
1636 | unlock_kernel(); | 1641 | tty_unlock(); |
1637 | mutex_unlock(&tty_mutex); | 1642 | mutex_unlock(&tty_mutex); |
1638 | schedule(); | 1643 | schedule(); |
1639 | } | 1644 | } |
@@ -1698,7 +1703,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1698 | 1703 | ||
1699 | /* check whether both sides are closing ... */ | 1704 | /* check whether both sides are closing ... */ |
1700 | if (!tty_closing || (o_tty && !o_tty_closing)) { | 1705 | if (!tty_closing || (o_tty && !o_tty_closing)) { |
1701 | unlock_kernel(); | 1706 | tty_unlock(); |
1702 | return 0; | 1707 | return 0; |
1703 | } | 1708 | } |
1704 | 1709 | ||
@@ -1718,7 +1723,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1718 | /* Make this pty number available for reallocation */ | 1723 | /* Make this pty number available for reallocation */ |
1719 | if (devpts) | 1724 | if (devpts) |
1720 | devpts_kill_index(inode, idx); | 1725 | devpts_kill_index(inode, idx); |
1721 | unlock_kernel(); | 1726 | tty_unlock(); |
1722 | return 0; | 1727 | return 0; |
1723 | } | 1728 | } |
1724 | 1729 | ||
@@ -1760,12 +1765,12 @@ retry_open: | |||
1760 | retval = 0; | 1765 | retval = 0; |
1761 | 1766 | ||
1762 | mutex_lock(&tty_mutex); | 1767 | mutex_lock(&tty_mutex); |
1763 | lock_kernel(); | 1768 | tty_lock(); |
1764 | 1769 | ||
1765 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { | 1770 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { |
1766 | tty = get_current_tty(); | 1771 | tty = get_current_tty(); |
1767 | if (!tty) { | 1772 | if (!tty) { |
1768 | unlock_kernel(); | 1773 | tty_unlock(); |
1769 | mutex_unlock(&tty_mutex); | 1774 | mutex_unlock(&tty_mutex); |
1770 | return -ENXIO; | 1775 | return -ENXIO; |
1771 | } | 1776 | } |
@@ -1797,14 +1802,14 @@ retry_open: | |||
1797 | goto got_driver; | 1802 | goto got_driver; |
1798 | } | 1803 | } |
1799 | } | 1804 | } |
1800 | unlock_kernel(); | 1805 | tty_unlock(); |
1801 | mutex_unlock(&tty_mutex); | 1806 | mutex_unlock(&tty_mutex); |
1802 | return -ENODEV; | 1807 | return -ENODEV; |
1803 | } | 1808 | } |
1804 | 1809 | ||
1805 | driver = get_tty_driver(device, &index); | 1810 | driver = get_tty_driver(device, &index); |
1806 | if (!driver) { | 1811 | if (!driver) { |
1807 | unlock_kernel(); | 1812 | tty_unlock(); |
1808 | mutex_unlock(&tty_mutex); | 1813 | mutex_unlock(&tty_mutex); |
1809 | return -ENODEV; | 1814 | return -ENODEV; |
1810 | } | 1815 | } |
@@ -1814,7 +1819,7 @@ got_driver: | |||
1814 | tty = tty_driver_lookup_tty(driver, inode, index); | 1819 | tty = tty_driver_lookup_tty(driver, inode, index); |
1815 | 1820 | ||
1816 | if (IS_ERR(tty)) { | 1821 | if (IS_ERR(tty)) { |
1817 | unlock_kernel(); | 1822 | tty_unlock(); |
1818 | mutex_unlock(&tty_mutex); | 1823 | mutex_unlock(&tty_mutex); |
1819 | return PTR_ERR(tty); | 1824 | return PTR_ERR(tty); |
1820 | } | 1825 | } |
@@ -1830,7 +1835,7 @@ got_driver: | |||
1830 | mutex_unlock(&tty_mutex); | 1835 | mutex_unlock(&tty_mutex); |
1831 | tty_driver_kref_put(driver); | 1836 | tty_driver_kref_put(driver); |
1832 | if (IS_ERR(tty)) { | 1837 | if (IS_ERR(tty)) { |
1833 | unlock_kernel(); | 1838 | tty_unlock(); |
1834 | return PTR_ERR(tty); | 1839 | return PTR_ERR(tty); |
1835 | } | 1840 | } |
1836 | 1841 | ||
@@ -1860,29 +1865,29 @@ got_driver: | |||
1860 | printk(KERN_DEBUG "error %d in opening %s...", retval, | 1865 | printk(KERN_DEBUG "error %d in opening %s...", retval, |
1861 | tty->name); | 1866 | tty->name); |
1862 | #endif | 1867 | #endif |
1868 | tty_unlock(); /* need to call tty_release without BTM */ | ||
1863 | tty_release(inode, filp); | 1869 | tty_release(inode, filp); |
1864 | if (retval != -ERESTARTSYS) { | 1870 | if (retval != -ERESTARTSYS) |
1865 | unlock_kernel(); | ||
1866 | return retval; | 1871 | return retval; |
1867 | } | 1872 | |
1868 | if (signal_pending(current)) { | 1873 | if (signal_pending(current)) |
1869 | unlock_kernel(); | ||
1870 | return retval; | 1874 | return retval; |
1871 | } | 1875 | |
1872 | schedule(); | 1876 | schedule(); |
1873 | /* | 1877 | /* |
1874 | * Need to reset f_op in case a hangup happened. | 1878 | * Need to reset f_op in case a hangup happened. |
1875 | */ | 1879 | */ |
1880 | tty_lock(); | ||
1876 | if (filp->f_op == &hung_up_tty_fops) | 1881 | if (filp->f_op == &hung_up_tty_fops) |
1877 | filp->f_op = &tty_fops; | 1882 | filp->f_op = &tty_fops; |
1878 | unlock_kernel(); | 1883 | tty_unlock(); |
1879 | goto retry_open; | 1884 | goto retry_open; |
1880 | } | 1885 | } |
1881 | unlock_kernel(); | 1886 | tty_unlock(); |
1882 | 1887 | ||
1883 | 1888 | ||
1884 | mutex_lock(&tty_mutex); | 1889 | mutex_lock(&tty_mutex); |
1885 | lock_kernel(); | 1890 | tty_lock(); |
1886 | spin_lock_irq(¤t->sighand->siglock); | 1891 | spin_lock_irq(¤t->sighand->siglock); |
1887 | if (!noctty && | 1892 | if (!noctty && |
1888 | current->signal->leader && | 1893 | current->signal->leader && |
@@ -1890,7 +1895,7 @@ got_driver: | |||
1890 | tty->session == NULL) | 1895 | tty->session == NULL) |
1891 | __proc_set_tty(current, tty); | 1896 | __proc_set_tty(current, tty); |
1892 | spin_unlock_irq(¤t->sighand->siglock); | 1897 | spin_unlock_irq(¤t->sighand->siglock); |
1893 | unlock_kernel(); | 1898 | tty_unlock(); |
1894 | mutex_unlock(&tty_mutex); | 1899 | mutex_unlock(&tty_mutex); |
1895 | return 0; | 1900 | return 0; |
1896 | } | 1901 | } |
@@ -1915,7 +1920,7 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) | |||
1915 | struct tty_ldisc *ld; | 1920 | struct tty_ldisc *ld; |
1916 | int ret = 0; | 1921 | int ret = 0; |
1917 | 1922 | ||
1918 | tty = (struct tty_struct *)filp->private_data; | 1923 | tty = filp->private_data; |
1919 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll")) | 1924 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll")) |
1920 | return 0; | 1925 | return 0; |
1921 | 1926 | ||
@@ -1926,14 +1931,13 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) | |||
1926 | return ret; | 1931 | return ret; |
1927 | } | 1932 | } |
1928 | 1933 | ||
1929 | static int tty_fasync(int fd, struct file *filp, int on) | 1934 | static int __tty_fasync(int fd, struct file *filp, int on) |
1930 | { | 1935 | { |
1931 | struct tty_struct *tty; | 1936 | struct tty_struct *tty; |
1932 | unsigned long flags; | 1937 | unsigned long flags; |
1933 | int retval = 0; | 1938 | int retval = 0; |
1934 | 1939 | ||
1935 | lock_kernel(); | 1940 | tty = filp->private_data; |
1936 | tty = (struct tty_struct *)filp->private_data; | ||
1937 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) | 1941 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) |
1938 | goto out; | 1942 | goto out; |
1939 | 1943 | ||
@@ -1966,7 +1970,15 @@ static int tty_fasync(int fd, struct file *filp, int on) | |||
1966 | } | 1970 | } |
1967 | retval = 0; | 1971 | retval = 0; |
1968 | out: | 1972 | out: |
1969 | unlock_kernel(); | 1973 | return retval; |
1974 | } | ||
1975 | |||
1976 | static int tty_fasync(int fd, struct file *filp, int on) | ||
1977 | { | ||
1978 | int retval; | ||
1979 | tty_lock(); | ||
1980 | retval = __tty_fasync(fd, filp, on); | ||
1981 | tty_unlock(); | ||
1970 | return retval; | 1982 | return retval; |
1971 | } | 1983 | } |
1972 | 1984 | ||
@@ -2485,7 +2497,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2485 | struct tty_ldisc *ld; | 2497 | struct tty_ldisc *ld; |
2486 | struct inode *inode = file->f_dentry->d_inode; | 2498 | struct inode *inode = file->f_dentry->d_inode; |
2487 | 2499 | ||
2488 | tty = (struct tty_struct *)file->private_data; | 2500 | tty = file->private_data; |
2489 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) | 2501 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) |
2490 | return -EINVAL; | 2502 | return -EINVAL; |
2491 | 2503 | ||
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 6bd5f8866c74..0c1889971459 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -517,19 +517,25 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) | |||
517 | 517 | ||
518 | /* See if packet mode change of state. */ | 518 | /* See if packet mode change of state. */ |
519 | if (tty->link && tty->link->packet) { | 519 | if (tty->link && tty->link->packet) { |
520 | int extproc = (old_termios.c_lflag & EXTPROC) | | ||
521 | (tty->termios->c_lflag & EXTPROC); | ||
520 | int old_flow = ((old_termios.c_iflag & IXON) && | 522 | int old_flow = ((old_termios.c_iflag & IXON) && |
521 | (old_termios.c_cc[VSTOP] == '\023') && | 523 | (old_termios.c_cc[VSTOP] == '\023') && |
522 | (old_termios.c_cc[VSTART] == '\021')); | 524 | (old_termios.c_cc[VSTART] == '\021')); |
523 | int new_flow = (I_IXON(tty) && | 525 | int new_flow = (I_IXON(tty) && |
524 | STOP_CHAR(tty) == '\023' && | 526 | STOP_CHAR(tty) == '\023' && |
525 | START_CHAR(tty) == '\021'); | 527 | START_CHAR(tty) == '\021'); |
526 | if (old_flow != new_flow) { | 528 | if ((old_flow != new_flow) || extproc) { |
527 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 529 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
528 | tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); | 530 | if (old_flow != new_flow) { |
529 | if (new_flow) | 531 | tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); |
530 | tty->ctrl_status |= TIOCPKT_DOSTOP; | 532 | if (new_flow) |
531 | else | 533 | tty->ctrl_status |= TIOCPKT_DOSTOP; |
532 | tty->ctrl_status |= TIOCPKT_NOSTOP; | 534 | else |
535 | tty->ctrl_status |= TIOCPKT_NOSTOP; | ||
536 | } | ||
537 | if (extproc) | ||
538 | tty->ctrl_status |= TIOCPKT_IOCTL; | ||
533 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 539 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
534 | wake_up_interruptible(&tty->link->read_wait); | 540 | wake_up_interruptible(&tty->link->read_wait); |
535 | } | 541 | } |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 500e740ec5e4..412f9775d19c 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
@@ -440,6 +440,8 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
440 | * | 440 | * |
441 | * A helper opening method. Also a convenient debugging and check | 441 | * A helper opening method. Also a convenient debugging and check |
442 | * point. | 442 | * point. |
443 | * | ||
444 | * Locking: always called with BTM already held. | ||
443 | */ | 445 | */ |
444 | 446 | ||
445 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | 447 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) |
@@ -447,10 +449,9 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | |||
447 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); | 449 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); |
448 | if (ld->ops->open) { | 450 | if (ld->ops->open) { |
449 | int ret; | 451 | int ret; |
450 | /* BKL here locks verus a hangup event */ | 452 | /* BTM here locks versus a hangup event */ |
451 | lock_kernel(); | 453 | WARN_ON(!tty_locked()); |
452 | ret = ld->ops->open(tty); | 454 | ret = ld->ops->open(tty); |
453 | unlock_kernel(); | ||
454 | return ret; | 455 | return ret; |
455 | } | 456 | } |
456 | return 0; | 457 | return 0; |
@@ -553,7 +554,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
553 | if (IS_ERR(new_ldisc)) | 554 | if (IS_ERR(new_ldisc)) |
554 | return PTR_ERR(new_ldisc); | 555 | return PTR_ERR(new_ldisc); |
555 | 556 | ||
556 | lock_kernel(); | 557 | tty_lock(); |
557 | /* | 558 | /* |
558 | * We need to look at the tty locking here for pty/tty pairs | 559 | * We need to look at the tty locking here for pty/tty pairs |
559 | * when both sides try to change in parallel. | 560 | * when both sides try to change in parallel. |
@@ -567,12 +568,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
567 | */ | 568 | */ |
568 | 569 | ||
569 | if (tty->ldisc->ops->num == ldisc) { | 570 | if (tty->ldisc->ops->num == ldisc) { |
570 | unlock_kernel(); | 571 | tty_unlock(); |
571 | tty_ldisc_put(new_ldisc); | 572 | tty_ldisc_put(new_ldisc); |
572 | return 0; | 573 | return 0; |
573 | } | 574 | } |
574 | 575 | ||
575 | unlock_kernel(); | 576 | tty_unlock(); |
576 | /* | 577 | /* |
577 | * Problem: What do we do if this blocks ? | 578 | * Problem: What do we do if this blocks ? |
578 | * We could deadlock here | 579 | * We could deadlock here |
@@ -580,6 +581,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
580 | 581 | ||
581 | tty_wait_until_sent(tty, 0); | 582 | tty_wait_until_sent(tty, 0); |
582 | 583 | ||
584 | tty_lock(); | ||
583 | mutex_lock(&tty->ldisc_mutex); | 585 | mutex_lock(&tty->ldisc_mutex); |
584 | 586 | ||
585 | /* | 587 | /* |
@@ -589,13 +591,13 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
589 | 591 | ||
590 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | 592 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { |
591 | mutex_unlock(&tty->ldisc_mutex); | 593 | mutex_unlock(&tty->ldisc_mutex); |
594 | tty_unlock(); | ||
592 | wait_event(tty_ldisc_wait, | 595 | wait_event(tty_ldisc_wait, |
593 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | 596 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); |
597 | tty_lock(); | ||
594 | mutex_lock(&tty->ldisc_mutex); | 598 | mutex_lock(&tty->ldisc_mutex); |
595 | } | 599 | } |
596 | 600 | ||
597 | lock_kernel(); | ||
598 | |||
599 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | 601 | set_bit(TTY_LDISC_CHANGING, &tty->flags); |
600 | 602 | ||
601 | /* | 603 | /* |
@@ -607,7 +609,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
607 | 609 | ||
608 | o_ldisc = tty->ldisc; | 610 | o_ldisc = tty->ldisc; |
609 | 611 | ||
610 | unlock_kernel(); | 612 | tty_unlock(); |
611 | /* | 613 | /* |
612 | * Make sure we don't change while someone holds a | 614 | * Make sure we don't change while someone holds a |
613 | * reference to the line discipline. The TTY_LDISC bit | 615 | * reference to the line discipline. The TTY_LDISC bit |
@@ -632,15 +634,15 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
632 | 634 | ||
633 | flush_scheduled_work(); | 635 | flush_scheduled_work(); |
634 | 636 | ||
637 | tty_lock(); | ||
635 | mutex_lock(&tty->ldisc_mutex); | 638 | mutex_lock(&tty->ldisc_mutex); |
636 | lock_kernel(); | ||
637 | if (test_bit(TTY_HUPPED, &tty->flags)) { | 639 | if (test_bit(TTY_HUPPED, &tty->flags)) { |
638 | /* We were raced by the hangup method. It will have stomped | 640 | /* We were raced by the hangup method. It will have stomped |
639 | the ldisc data and closed the ldisc down */ | 641 | the ldisc data and closed the ldisc down */ |
640 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 642 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); |
641 | mutex_unlock(&tty->ldisc_mutex); | 643 | mutex_unlock(&tty->ldisc_mutex); |
642 | tty_ldisc_put(new_ldisc); | 644 | tty_ldisc_put(new_ldisc); |
643 | unlock_kernel(); | 645 | tty_unlock(); |
644 | return -EIO; | 646 | return -EIO; |
645 | } | 647 | } |
646 | 648 | ||
@@ -682,7 +684,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
682 | if (o_work) | 684 | if (o_work) |
683 | schedule_delayed_work(&o_tty->buf.work, 1); | 685 | schedule_delayed_work(&o_tty->buf.work, 1); |
684 | mutex_unlock(&tty->ldisc_mutex); | 686 | mutex_unlock(&tty->ldisc_mutex); |
685 | unlock_kernel(); | 687 | tty_unlock(); |
686 | return retval; | 688 | return retval; |
687 | } | 689 | } |
688 | 690 | ||
@@ -780,7 +782,20 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
780 | * Avoid racing set_ldisc or tty_ldisc_release | 782 | * Avoid racing set_ldisc or tty_ldisc_release |
781 | */ | 783 | */ |
782 | mutex_lock(&tty->ldisc_mutex); | 784 | mutex_lock(&tty->ldisc_mutex); |
783 | tty_ldisc_halt(tty); | 785 | |
786 | /* | ||
787 | * this is like tty_ldisc_halt, but we need to give up | ||
788 | * the BTM before calling cancel_delayed_work_sync, | ||
789 | * which may need to wait for another function taking the BTM | ||
790 | */ | ||
791 | clear_bit(TTY_LDISC, &tty->flags); | ||
792 | tty_unlock(); | ||
793 | cancel_delayed_work_sync(&tty->buf.work); | ||
794 | mutex_unlock(&tty->ldisc_mutex); | ||
795 | |||
796 | tty_lock(); | ||
797 | mutex_lock(&tty->ldisc_mutex); | ||
798 | |||
784 | /* At this point we have a closed ldisc and we want to | 799 | /* At this point we have a closed ldisc and we want to |
785 | reopen it. We could defer this to the next open but | 800 | reopen it. We could defer this to the next open but |
786 | it means auditing a lot of other paths so this is | 801 | it means auditing a lot of other paths so this is |
@@ -851,8 +866,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
851 | * race with the set_ldisc code path. | 866 | * race with the set_ldisc code path. |
852 | */ | 867 | */ |
853 | 868 | ||
869 | tty_unlock(); | ||
854 | tty_ldisc_halt(tty); | 870 | tty_ldisc_halt(tty); |
855 | flush_scheduled_work(); | 871 | flush_scheduled_work(); |
872 | tty_lock(); | ||
856 | 873 | ||
857 | mutex_lock(&tty->ldisc_mutex); | 874 | mutex_lock(&tty->ldisc_mutex); |
858 | /* | 875 | /* |
diff --git a/drivers/char/tty_mutex.c b/drivers/char/tty_mutex.c new file mode 100644 index 000000000000..133697540c73 --- /dev/null +++ b/drivers/char/tty_mutex.c | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * drivers/char/tty_lock.c | ||
3 | */ | ||
4 | #include <linux/tty.h> | ||
5 | #include <linux/module.h> | ||
6 | #include <linux/kallsyms.h> | ||
7 | #include <linux/semaphore.h> | ||
8 | #include <linux/sched.h> | ||
9 | |||
10 | /* | ||
11 | * The 'big tty mutex' | ||
12 | * | ||
13 | * This mutex is taken and released by tty_lock() and tty_unlock(), | ||
14 | * replacing the older big kernel lock. | ||
15 | * It can no longer be taken recursively, and does not get | ||
16 | * released implicitly while sleeping. | ||
17 | * | ||
18 | * Don't use in new code. | ||
19 | */ | ||
20 | static DEFINE_MUTEX(big_tty_mutex); | ||
21 | struct task_struct *__big_tty_mutex_owner; | ||
22 | EXPORT_SYMBOL_GPL(__big_tty_mutex_owner); | ||
23 | |||
24 | /* | ||
25 | * Getting the big tty mutex. | ||
26 | */ | ||
27 | void __lockfunc tty_lock(void) | ||
28 | { | ||
29 | struct task_struct *task = current; | ||
30 | |||
31 | WARN_ON(__big_tty_mutex_owner == task); | ||
32 | |||
33 | mutex_lock(&big_tty_mutex); | ||
34 | __big_tty_mutex_owner = task; | ||
35 | } | ||
36 | EXPORT_SYMBOL(tty_lock); | ||
37 | |||
38 | void __lockfunc tty_unlock(void) | ||
39 | { | ||
40 | struct task_struct *task = current; | ||
41 | |||
42 | WARN_ON(__big_tty_mutex_owner != task); | ||
43 | __big_tty_mutex_owner = NULL; | ||
44 | |||
45 | mutex_unlock(&big_tty_mutex); | ||
46 | } | ||
47 | EXPORT_SYMBOL(tty_unlock); | ||
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index a3bd1d0b66cf..33d37d230f8f 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
@@ -231,7 +231,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
231 | 231 | ||
232 | /* block if port is in the process of being closed */ | 232 | /* block if port is in the process of being closed */ |
233 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { | 233 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
234 | wait_event_interruptible(port->close_wait, | 234 | wait_event_interruptible_tty(port->close_wait, |
235 | !(port->flags & ASYNC_CLOSING)); | 235 | !(port->flags & ASYNC_CLOSING)); |
236 | if (port->flags & ASYNC_HUP_NOTIFY) | 236 | if (port->flags & ASYNC_HUP_NOTIFY) |
237 | return -EAGAIN; | 237 | return -EAGAIN; |
@@ -294,7 +294,9 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
294 | retval = -ERESTARTSYS; | 294 | retval = -ERESTARTSYS; |
295 | break; | 295 | break; |
296 | } | 296 | } |
297 | tty_unlock(); | ||
297 | schedule(); | 298 | schedule(); |
299 | tty_lock(); | ||
298 | } | 300 | } |
299 | finish_wait(&port->open_wait, &wait); | 301 | finish_wait(&port->open_wait, &wait); |
300 | 302 | ||
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index c1791a63d99d..bcce46c96b88 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c | |||
@@ -463,10 +463,10 @@ vcs_open(struct inode *inode, struct file *filp) | |||
463 | unsigned int currcons = iminor(inode) & 127; | 463 | unsigned int currcons = iminor(inode) & 127; |
464 | int ret = 0; | 464 | int ret = 0; |
465 | 465 | ||
466 | lock_kernel(); | 466 | tty_lock(); |
467 | if(currcons && !vc_cons_allocated(currcons-1)) | 467 | if(currcons && !vc_cons_allocated(currcons-1)) |
468 | ret = -ENXIO; | 468 | ret = -ENXIO; |
469 | unlock_kernel(); | 469 | tty_unlock(); |
470 | return ret; | 470 | return ret; |
471 | } | 471 | } |
472 | 472 | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 4a9eb3044e52..c734f9b1263a 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -105,6 +105,7 @@ | |||
105 | #include <asm/system.h> | 105 | #include <asm/system.h> |
106 | #include <linux/uaccess.h> | 106 | #include <linux/uaccess.h> |
107 | #include <linux/kdb.h> | 107 | #include <linux/kdb.h> |
108 | #include <linux/ctype.h> | ||
108 | 109 | ||
109 | #define MAX_NR_CON_DRIVER 16 | 110 | #define MAX_NR_CON_DRIVER 16 |
110 | 111 | ||
@@ -286,8 +287,12 @@ static inline unsigned short *screenpos(struct vc_data *vc, int offset, int view | |||
286 | return p; | 287 | return p; |
287 | } | 288 | } |
288 | 289 | ||
290 | /* Called from the keyboard irq path.. */ | ||
289 | static inline void scrolldelta(int lines) | 291 | static inline void scrolldelta(int lines) |
290 | { | 292 | { |
293 | /* FIXME */ | ||
294 | /* scrolldelta needs some kind of consistency lock, but the BKL was | ||
295 | and still is not protecting versus the scheduled back end */ | ||
291 | scrollback_delta += lines; | 296 | scrollback_delta += lines; |
292 | schedule_console_callback(); | 297 | schedule_console_callback(); |
293 | } | 298 | } |
@@ -704,7 +709,10 @@ void redraw_screen(struct vc_data *vc, int is_switch) | |||
704 | update_attr(vc); | 709 | update_attr(vc); |
705 | clear_buffer_attributes(vc); | 710 | clear_buffer_attributes(vc); |
706 | } | 711 | } |
707 | if (update && vc->vc_mode != KD_GRAPHICS) | 712 | |
713 | /* Forcibly update if we're panicing */ | ||
714 | if ((update && vc->vc_mode != KD_GRAPHICS) || | ||
715 | vt_force_oops_output(vc)) | ||
708 | do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2); | 716 | do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2); |
709 | } | 717 | } |
710 | set_cursor(vc); | 718 | set_cursor(vc); |
@@ -742,6 +750,7 @@ static void visual_init(struct vc_data *vc, int num, int init) | |||
742 | vc->vc_hi_font_mask = 0; | 750 | vc->vc_hi_font_mask = 0; |
743 | vc->vc_complement_mask = 0; | 751 | vc->vc_complement_mask = 0; |
744 | vc->vc_can_do_color = 0; | 752 | vc->vc_can_do_color = 0; |
753 | vc->vc_panic_force_write = false; | ||
745 | vc->vc_sw->con_init(vc, init); | 754 | vc->vc_sw->con_init(vc, init); |
746 | if (!vc->vc_complement_mask) | 755 | if (!vc->vc_complement_mask) |
747 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; | 756 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; |
@@ -774,6 +783,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ | |||
774 | if (!vc) | 783 | if (!vc) |
775 | return -ENOMEM; | 784 | return -ENOMEM; |
776 | vc_cons[currcons].d = vc; | 785 | vc_cons[currcons].d = vc; |
786 | tty_port_init(&vc->port); | ||
777 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); | 787 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); |
778 | visual_init(vc, currcons, 1); | 788 | visual_init(vc, currcons, 1); |
779 | if (!*vc->vc_uni_pagedir_loc) | 789 | if (!*vc->vc_uni_pagedir_loc) |
@@ -837,9 +847,10 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, | |||
837 | unsigned int cols, unsigned int lines) | 847 | unsigned int cols, unsigned int lines) |
838 | { | 848 | { |
839 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; | 849 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; |
850 | unsigned long end; | ||
840 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; | 851 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; |
841 | unsigned int new_cols, new_rows, new_row_size, new_screen_size; | 852 | unsigned int new_cols, new_rows, new_row_size, new_screen_size; |
842 | unsigned int end, user; | 853 | unsigned int user; |
843 | unsigned short *newscreen; | 854 | unsigned short *newscreen; |
844 | 855 | ||
845 | WARN_CONSOLE_UNLOCKED(); | 856 | WARN_CONSOLE_UNLOCKED(); |
@@ -962,12 +973,12 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, | |||
962 | * Resize a virtual console as seen from the console end of things. We | 973 | * Resize a virtual console as seen from the console end of things. We |
963 | * use the common vc_do_resize methods to update the structures. The | 974 | * use the common vc_do_resize methods to update the structures. The |
964 | * caller must hold the console sem to protect console internals and | 975 | * caller must hold the console sem to protect console internals and |
965 | * vc->vc_tty | 976 | * vc->port.tty |
966 | */ | 977 | */ |
967 | 978 | ||
968 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) | 979 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) |
969 | { | 980 | { |
970 | return vc_do_resize(vc->vc_tty, vc, cols, rows); | 981 | return vc_do_resize(vc->port.tty, vc, cols, rows); |
971 | } | 982 | } |
972 | 983 | ||
973 | /** | 984 | /** |
@@ -1795,8 +1806,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) | |||
1795 | vc->vc_state = ESnormal; | 1806 | vc->vc_state = ESnormal; |
1796 | return; | 1807 | return; |
1797 | case ESpalette: | 1808 | case ESpalette: |
1798 | if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) { | 1809 | if (isxdigit(c)) { |
1799 | vc->vc_par[vc->vc_npar++] = (c > '9' ? (c & 0xDF) - 'A' + 10 : c - '0'); | 1810 | vc->vc_par[vc->vc_npar++] = hex_to_bin(c); |
1800 | if (vc->vc_npar == 7) { | 1811 | if (vc->vc_npar == 7) { |
1801 | int i = vc->vc_par[0] * 3, j = 1; | 1812 | int i = vc->vc_par[0] * 3, j = 1; |
1802 | vc->vc_palette[i] = 16 * vc->vc_par[j++]; | 1813 | vc->vc_palette[i] = 16 * vc->vc_par[j++]; |
@@ -2504,7 +2515,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) | |||
2504 | goto quit; | 2515 | goto quit; |
2505 | } | 2516 | } |
2506 | 2517 | ||
2507 | if (vc->vc_mode != KD_TEXT) | 2518 | if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc)) |
2508 | goto quit; | 2519 | goto quit; |
2509 | 2520 | ||
2510 | /* undraw cursor first */ | 2521 | /* undraw cursor first */ |
@@ -2610,8 +2621,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) | |||
2610 | return -EFAULT; | 2621 | return -EFAULT; |
2611 | ret = 0; | 2622 | ret = 0; |
2612 | 2623 | ||
2613 | lock_kernel(); | ||
2614 | |||
2615 | switch (type) | 2624 | switch (type) |
2616 | { | 2625 | { |
2617 | case TIOCL_SETSEL: | 2626 | case TIOCL_SETSEL: |
@@ -2686,7 +2695,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) | |||
2686 | ret = -EINVAL; | 2695 | ret = -EINVAL; |
2687 | break; | 2696 | break; |
2688 | } | 2697 | } |
2689 | unlock_kernel(); | ||
2690 | return ret; | 2698 | return ret; |
2691 | } | 2699 | } |
2692 | 2700 | ||
@@ -2799,12 +2807,12 @@ static int con_open(struct tty_struct *tty, struct file *filp) | |||
2799 | struct vc_data *vc = vc_cons[currcons].d; | 2807 | struct vc_data *vc = vc_cons[currcons].d; |
2800 | 2808 | ||
2801 | /* Still being freed */ | 2809 | /* Still being freed */ |
2802 | if (vc->vc_tty) { | 2810 | if (vc->port.tty) { |
2803 | release_console_sem(); | 2811 | release_console_sem(); |
2804 | return -ERESTARTSYS; | 2812 | return -ERESTARTSYS; |
2805 | } | 2813 | } |
2806 | tty->driver_data = vc; | 2814 | tty->driver_data = vc; |
2807 | vc->vc_tty = tty; | 2815 | vc->port.tty = tty; |
2808 | 2816 | ||
2809 | if (!tty->winsize.ws_row && !tty->winsize.ws_col) { | 2817 | if (!tty->winsize.ws_row && !tty->winsize.ws_col) { |
2810 | tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; | 2818 | tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; |
@@ -2832,7 +2840,7 @@ static void con_shutdown(struct tty_struct *tty) | |||
2832 | struct vc_data *vc = tty->driver_data; | 2840 | struct vc_data *vc = tty->driver_data; |
2833 | BUG_ON(vc == NULL); | 2841 | BUG_ON(vc == NULL); |
2834 | acquire_console_sem(); | 2842 | acquire_console_sem(); |
2835 | vc->vc_tty = NULL; | 2843 | vc->port.tty = NULL; |
2836 | release_console_sem(); | 2844 | release_console_sem(); |
2837 | tty_shutdown(tty); | 2845 | tty_shutdown(tty); |
2838 | } | 2846 | } |
@@ -2914,6 +2922,7 @@ static int __init con_init(void) | |||
2914 | for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { | 2922 | for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { |
2915 | vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); | 2923 | vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); |
2916 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); | 2924 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); |
2925 | tty_port_init(&vc->port); | ||
2917 | visual_init(vc, currcons, 1); | 2926 | visual_init(vc, currcons, 1); |
2918 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); | 2927 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); |
2919 | vc_init(vc, vc->vc_rows, vc->vc_cols, | 2928 | vc_init(vc, vc->vc_rows, vc->vc_cols, |
@@ -3065,7 +3074,8 @@ static int bind_con_driver(const struct consw *csw, int first, int last, | |||
3065 | 3074 | ||
3066 | old_was_color = vc->vc_can_do_color; | 3075 | old_was_color = vc->vc_can_do_color; |
3067 | vc->vc_sw->con_deinit(vc); | 3076 | vc->vc_sw->con_deinit(vc); |
3068 | vc->vc_origin = (unsigned long)vc->vc_screenbuf; | 3077 | if (!vc->vc_origin) |
3078 | vc->vc_origin = (unsigned long)vc->vc_screenbuf; | ||
3069 | visual_init(vc, i, 0); | 3079 | visual_init(vc, i, 0); |
3070 | set_origin(vc); | 3080 | set_origin(vc); |
3071 | update_attr(vc); | 3081 | update_attr(vc); |
@@ -3781,7 +3791,8 @@ void do_unblank_screen(int leaving_gfx) | |||
3781 | return; | 3791 | return; |
3782 | } | 3792 | } |
3783 | vc = vc_cons[fg_console].d; | 3793 | vc = vc_cons[fg_console].d; |
3784 | if (vc->vc_mode != KD_TEXT) | 3794 | /* Try to unblank in oops case too */ |
3795 | if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc)) | ||
3785 | return; /* but leave console_blanked != 0 */ | 3796 | return; /* but leave console_blanked != 0 */ |
3786 | 3797 | ||
3787 | if (blankinterval) { | 3798 | if (blankinterval) { |
@@ -3790,7 +3801,7 @@ void do_unblank_screen(int leaving_gfx) | |||
3790 | } | 3801 | } |
3791 | 3802 | ||
3792 | console_blanked = 0; | 3803 | console_blanked = 0; |
3793 | if (vc->vc_sw->con_blank(vc, 0, leaving_gfx)) | 3804 | if (vc->vc_sw->con_blank(vc, 0, leaving_gfx) || vt_force_oops_output(vc)) |
3794 | /* Low-level driver cannot restore -> do it ourselves */ | 3805 | /* Low-level driver cannot restore -> do it ourselves */ |
3795 | update_screen(vc); | 3806 | update_screen(vc); |
3796 | if (console_blank_hook) | 3807 | if (console_blank_hook) |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index cb19dbc52136..2bbeaaea46e9 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -133,7 +133,7 @@ static void vt_event_wait(struct vt_event_wait *vw) | |||
133 | list_add(&vw->list, &vt_events); | 133 | list_add(&vw->list, &vt_events); |
134 | spin_unlock_irqrestore(&vt_event_lock, flags); | 134 | spin_unlock_irqrestore(&vt_event_lock, flags); |
135 | /* Wait for it to pass */ | 135 | /* Wait for it to pass */ |
136 | wait_event_interruptible(vt_event_waitqueue, vw->done); | 136 | wait_event_interruptible_tty(vt_event_waitqueue, vw->done); |
137 | /* Dequeue it */ | 137 | /* Dequeue it */ |
138 | spin_lock_irqsave(&vt_event_lock, flags); | 138 | spin_lock_irqsave(&vt_event_lock, flags); |
139 | list_del(&vw->list); | 139 | list_del(&vw->list); |
@@ -509,7 +509,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
509 | 509 | ||
510 | console = vc->vc_num; | 510 | console = vc->vc_num; |
511 | 511 | ||
512 | lock_kernel(); | 512 | tty_lock(); |
513 | 513 | ||
514 | if (!vc_cons_allocated(console)) { /* impossible? */ | 514 | if (!vc_cons_allocated(console)) { /* impossible? */ |
515 | ret = -ENOIOCTLCMD; | 515 | ret = -ENOIOCTLCMD; |
@@ -1336,7 +1336,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
1336 | ret = -ENOIOCTLCMD; | 1336 | ret = -ENOIOCTLCMD; |
1337 | } | 1337 | } |
1338 | out: | 1338 | out: |
1339 | unlock_kernel(); | 1339 | tty_unlock(); |
1340 | return ret; | 1340 | return ret; |
1341 | eperm: | 1341 | eperm: |
1342 | ret = -EPERM; | 1342 | ret = -EPERM; |
@@ -1369,7 +1369,7 @@ void vc_SAK(struct work_struct *work) | |||
1369 | acquire_console_sem(); | 1369 | acquire_console_sem(); |
1370 | vc = vc_con->d; | 1370 | vc = vc_con->d; |
1371 | if (vc) { | 1371 | if (vc) { |
1372 | tty = vc->vc_tty; | 1372 | tty = vc->port.tty; |
1373 | /* | 1373 | /* |
1374 | * SAK should also work in all raw modes and reset | 1374 | * SAK should also work in all raw modes and reset |
1375 | * them properly. | 1375 | * them properly. |
@@ -1503,7 +1503,7 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, | |||
1503 | 1503 | ||
1504 | console = vc->vc_num; | 1504 | console = vc->vc_num; |
1505 | 1505 | ||
1506 | lock_kernel(); | 1506 | tty_lock(); |
1507 | 1507 | ||
1508 | if (!vc_cons_allocated(console)) { /* impossible? */ | 1508 | if (!vc_cons_allocated(console)) { /* impossible? */ |
1509 | ret = -ENOIOCTLCMD; | 1509 | ret = -ENOIOCTLCMD; |
@@ -1571,11 +1571,11 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, | |||
1571 | goto fallback; | 1571 | goto fallback; |
1572 | } | 1572 | } |
1573 | out: | 1573 | out: |
1574 | unlock_kernel(); | 1574 | tty_unlock(); |
1575 | return ret; | 1575 | return ret; |
1576 | 1576 | ||
1577 | fallback: | 1577 | fallback: |
1578 | unlock_kernel(); | 1578 | tty_unlock(); |
1579 | return vt_ioctl(tty, file, cmd, arg); | 1579 | return vt_ioctl(tty, file, cmd, arg); |
1580 | } | 1580 | } |
1581 | 1581 | ||
@@ -1761,10 +1761,13 @@ int vt_move_to_console(unsigned int vt, int alloc) | |||
1761 | return -EIO; | 1761 | return -EIO; |
1762 | } | 1762 | } |
1763 | release_console_sem(); | 1763 | release_console_sem(); |
1764 | tty_lock(); | ||
1764 | if (vt_waitactive(vt + 1)) { | 1765 | if (vt_waitactive(vt + 1)) { |
1765 | pr_debug("Suspend: Can't switch VCs."); | 1766 | pr_debug("Suspend: Can't switch VCs."); |
1767 | tty_unlock(); | ||
1766 | return -EINTR; | 1768 | return -EINTR; |
1767 | } | 1769 | } |
1770 | tty_unlock(); | ||
1768 | return prev; | 1771 | return prev; |
1769 | } | 1772 | } |
1770 | 1773 | ||
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index dbefe15bd582..a50710843378 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -74,6 +74,17 @@ static void cpuidle_idle_call(void) | |||
74 | */ | 74 | */ |
75 | hrtimer_peek_ahead_timers(); | 75 | hrtimer_peek_ahead_timers(); |
76 | #endif | 76 | #endif |
77 | |||
78 | /* | ||
79 | * Call the device's prepare function before calling the | ||
80 | * governor's select function. ->prepare gives the device's | ||
81 | * cpuidle driver a chance to update any dynamic information | ||
82 | * of its cpuidle states for the current idle period, e.g. | ||
83 | * state availability, latencies, residencies, etc. | ||
84 | */ | ||
85 | if (dev->prepare) | ||
86 | dev->prepare(dev); | ||
87 | |||
77 | /* ask the governor for the next state */ | 88 | /* ask the governor for the next state */ |
78 | next_state = cpuidle_curr_governor->select(dev); | 89 | next_state = cpuidle_curr_governor->select(dev); |
79 | if (need_resched()) { | 90 | if (need_resched()) { |
@@ -282,6 +293,26 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) | |||
282 | 293 | ||
283 | poll_idle_init(dev); | 294 | poll_idle_init(dev); |
284 | 295 | ||
296 | /* | ||
297 | * cpuidle driver should set the dev->power_specified bit | ||
298 | * before registering the device if the driver provides | ||
299 | * power_usage numbers. | ||
300 | * | ||
301 | * For those devices whose ->power_specified is not set, | ||
302 | * we fill in power_usage with decreasing values as the | ||
303 | * cpuidle code has an implicit assumption that state Cn | ||
304 | * uses less power than C(n-1). | ||
305 | * | ||
306 | * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned | ||
307 | * an power value of -1. So we use -2, -3, etc, for other | ||
308 | * c-states. | ||
309 | */ | ||
310 | if (!dev->power_specified) { | ||
311 | int i; | ||
312 | for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) | ||
313 | dev->states[i].power_usage = -1 - i; | ||
314 | } | ||
315 | |||
285 | per_cpu(cpuidle_devices, dev->cpu) = dev; | 316 | per_cpu(cpuidle_devices, dev->cpu) = dev; |
286 | list_add(&dev->device_list, &cpuidle_detected_devices); | 317 | list_add(&dev->device_list, &cpuidle_detected_devices); |
287 | if ((ret = cpuidle_add_sysfs(sys_dev))) { | 318 | if ((ret = cpuidle_add_sysfs(sys_dev))) { |
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 1b128702d300..c2408bbe9c2e 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -234,6 +234,7 @@ static int menu_select(struct cpuidle_device *dev) | |||
234 | { | 234 | { |
235 | struct menu_device *data = &__get_cpu_var(menu_devices); | 235 | struct menu_device *data = &__get_cpu_var(menu_devices); |
236 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); | 236 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); |
237 | unsigned int power_usage = -1; | ||
237 | int i; | 238 | int i; |
238 | int multiplier; | 239 | int multiplier; |
239 | 240 | ||
@@ -278,19 +279,27 @@ static int menu_select(struct cpuidle_device *dev) | |||
278 | if (data->expected_us > 5) | 279 | if (data->expected_us > 5) |
279 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START; | 280 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START; |
280 | 281 | ||
281 | 282 | /* | |
282 | /* find the deepest idle state that satisfies our constraints */ | 283 | * Find the idle state with the lowest power while satisfying |
284 | * our constraints. | ||
285 | */ | ||
283 | for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) { | 286 | for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) { |
284 | struct cpuidle_state *s = &dev->states[i]; | 287 | struct cpuidle_state *s = &dev->states[i]; |
285 | 288 | ||
289 | if (s->flags & CPUIDLE_FLAG_IGNORE) | ||
290 | continue; | ||
286 | if (s->target_residency > data->predicted_us) | 291 | if (s->target_residency > data->predicted_us) |
287 | break; | 292 | continue; |
288 | if (s->exit_latency > latency_req) | 293 | if (s->exit_latency > latency_req) |
289 | break; | 294 | continue; |
290 | if (s->exit_latency * multiplier > data->predicted_us) | 295 | if (s->exit_latency * multiplier > data->predicted_us) |
291 | break; | 296 | continue; |
292 | data->exit_us = s->exit_latency; | 297 | |
293 | data->last_state_idx = i; | 298 | if (s->power_usage < power_usage) { |
299 | power_usage = s->power_usage; | ||
300 | data->last_state_idx = i; | ||
301 | data->exit_us = s->exit_latency; | ||
302 | } | ||
294 | } | 303 | } |
295 | 304 | ||
296 | return data->last_state_idx; | 305 | return data->last_state_idx; |
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 9e01e96fee94..fed57634b6c1 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -33,6 +33,19 @@ if DMADEVICES | |||
33 | 33 | ||
34 | comment "DMA Devices" | 34 | comment "DMA Devices" |
35 | 35 | ||
36 | config INTEL_MID_DMAC | ||
37 | tristate "Intel MID DMA support for Peripheral DMA controllers" | ||
38 | depends on PCI && X86 | ||
39 | select DMA_ENGINE | ||
40 | default n | ||
41 | help | ||
42 | Enable support for the Intel(R) MID DMA engine present | ||
43 | in Intel MID chipsets. | ||
44 | |||
45 | Say Y here if you have such a chipset. | ||
46 | |||
47 | If unsure, say N. | ||
48 | |||
36 | config ASYNC_TX_DISABLE_CHANNEL_SWITCH | 49 | config ASYNC_TX_DISABLE_CHANNEL_SWITCH |
37 | bool | 50 | bool |
38 | 51 | ||
@@ -175,6 +188,13 @@ config PL330_DMA | |||
175 | You need to provide platform specific settings via | 188 | You need to provide platform specific settings via |
176 | platform_data for a dma-pl330 device. | 189 | platform_data for a dma-pl330 device. |
177 | 190 | ||
191 | config PCH_DMA | ||
192 | tristate "Topcliff PCH DMA support" | ||
193 | depends on PCI && X86 | ||
194 | select DMA_ENGINE | ||
195 | help | ||
196 | Enable support for the Topcliff PCH DMA engine. | ||
197 | |||
178 | config DMA_ENGINE | 198 | config DMA_ENGINE |
179 | bool | 199 | bool |
180 | 200 | ||
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 0fe5ebbfda5d..72bd70384d8a 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile | |||
@@ -7,6 +7,7 @@ endif | |||
7 | 7 | ||
8 | obj-$(CONFIG_DMA_ENGINE) += dmaengine.o | 8 | obj-$(CONFIG_DMA_ENGINE) += dmaengine.o |
9 | obj-$(CONFIG_NET_DMA) += iovlock.o | 9 | obj-$(CONFIG_NET_DMA) += iovlock.o |
10 | obj-$(CONFIG_INTEL_MID_DMAC) += intel_mid_dma.o | ||
10 | obj-$(CONFIG_DMATEST) += dmatest.o | 11 | obj-$(CONFIG_DMATEST) += dmatest.o |
11 | obj-$(CONFIG_INTEL_IOATDMA) += ioat/ | 12 | obj-$(CONFIG_INTEL_IOATDMA) += ioat/ |
12 | obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o | 13 | obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o |
@@ -23,3 +24,4 @@ obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/ | |||
23 | obj-$(CONFIG_TIMB_DMA) += timb_dma.o | 24 | obj-$(CONFIG_TIMB_DMA) += timb_dma.o |
24 | obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o | 25 | obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o |
25 | obj-$(CONFIG_PL330_DMA) += pl330.o | 26 | obj-$(CONFIG_PL330_DMA) += pl330.o |
27 | obj-$(CONFIG_PCH_DMA) += pch_dma.o | ||
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index e88076022a7a..a0f3e6a06e06 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c | |||
@@ -790,12 +790,12 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | |||
790 | list_splice_init(&atchan->queue, &list); | 790 | list_splice_init(&atchan->queue, &list); |
791 | list_splice_init(&atchan->active_list, &list); | 791 | list_splice_init(&atchan->active_list, &list); |
792 | 792 | ||
793 | spin_unlock_bh(&atchan->lock); | ||
794 | |||
795 | /* Flush all pending and queued descriptors */ | 793 | /* Flush all pending and queued descriptors */ |
796 | list_for_each_entry_safe(desc, _desc, &list, desc_node) | 794 | list_for_each_entry_safe(desc, _desc, &list, desc_node) |
797 | atc_chain_complete(atchan, desc); | 795 | atc_chain_complete(atchan, desc); |
798 | 796 | ||
797 | spin_unlock_bh(&atchan->lock); | ||
798 | |||
799 | return 0; | 799 | return 0; |
800 | } | 800 | } |
801 | 801 | ||
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index a724e6be1b4d..557e2272e5b3 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c | |||
@@ -72,6 +72,9 @@ struct coh901318_chan { | |||
72 | unsigned long nbr_active_done; | 72 | unsigned long nbr_active_done; |
73 | unsigned long busy; | 73 | unsigned long busy; |
74 | 74 | ||
75 | u32 runtime_addr; | ||
76 | u32 runtime_ctrl; | ||
77 | |||
75 | struct coh901318_base *base; | 78 | struct coh901318_base *base; |
76 | }; | 79 | }; |
77 | 80 | ||
@@ -190,6 +193,9 @@ static inline struct coh901318_chan *to_coh901318_chan(struct dma_chan *chan) | |||
190 | static inline dma_addr_t | 193 | static inline dma_addr_t |
191 | cohc_dev_addr(struct coh901318_chan *cohc) | 194 | cohc_dev_addr(struct coh901318_chan *cohc) |
192 | { | 195 | { |
196 | /* Runtime supplied address will take precedence */ | ||
197 | if (cohc->runtime_addr) | ||
198 | return cohc->runtime_addr; | ||
193 | return cohc->base->platform->chan_conf[cohc->id].dev_addr; | 199 | return cohc->base->platform->chan_conf[cohc->id].dev_addr; |
194 | } | 200 | } |
195 | 201 | ||
@@ -1055,6 +1061,14 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
1055 | 1061 | ||
1056 | params = cohc_chan_param(cohc); | 1062 | params = cohc_chan_param(cohc); |
1057 | config = params->config; | 1063 | config = params->config; |
1064 | /* | ||
1065 | * Add runtime-specific control on top, make | ||
1066 | * sure the bits you set per peripheral channel are | ||
1067 | * cleared in the default config from the platform. | ||
1068 | */ | ||
1069 | ctrl_chained |= cohc->runtime_ctrl; | ||
1070 | ctrl_last |= cohc->runtime_ctrl; | ||
1071 | ctrl |= cohc->runtime_ctrl; | ||
1058 | 1072 | ||
1059 | if (direction == DMA_TO_DEVICE) { | 1073 | if (direction == DMA_TO_DEVICE) { |
1060 | u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE | | 1074 | u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE | |
@@ -1113,6 +1127,12 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
1113 | if (ret) | 1127 | if (ret) |
1114 | goto err_lli_fill; | 1128 | goto err_lli_fill; |
1115 | 1129 | ||
1130 | /* | ||
1131 | * Set the default ctrl for the channel to the one from the lli, | ||
1132 | * things may have changed due to odd buffer alignment etc. | ||
1133 | */ | ||
1134 | coh901318_set_ctrl(cohc, lli->control); | ||
1135 | |||
1116 | COH_DBG(coh901318_list_print(cohc, lli)); | 1136 | COH_DBG(coh901318_list_print(cohc, lli)); |
1117 | 1137 | ||
1118 | /* Pick a descriptor to handle this transfer */ | 1138 | /* Pick a descriptor to handle this transfer */ |
@@ -1175,6 +1195,146 @@ coh901318_issue_pending(struct dma_chan *chan) | |||
1175 | spin_unlock_irqrestore(&cohc->lock, flags); | 1195 | spin_unlock_irqrestore(&cohc->lock, flags); |
1176 | } | 1196 | } |
1177 | 1197 | ||
1198 | /* | ||
1199 | * Here we wrap in the runtime dma control interface | ||
1200 | */ | ||
1201 | struct burst_table { | ||
1202 | int burst_8bit; | ||
1203 | int burst_16bit; | ||
1204 | int burst_32bit; | ||
1205 | u32 reg; | ||
1206 | }; | ||
1207 | |||
1208 | static const struct burst_table burst_sizes[] = { | ||
1209 | { | ||
1210 | .burst_8bit = 64, | ||
1211 | .burst_16bit = 32, | ||
1212 | .burst_32bit = 16, | ||
1213 | .reg = COH901318_CX_CTRL_BURST_COUNT_64_BYTES, | ||
1214 | }, | ||
1215 | { | ||
1216 | .burst_8bit = 48, | ||
1217 | .burst_16bit = 24, | ||
1218 | .burst_32bit = 12, | ||
1219 | .reg = COH901318_CX_CTRL_BURST_COUNT_48_BYTES, | ||
1220 | }, | ||
1221 | { | ||
1222 | .burst_8bit = 32, | ||
1223 | .burst_16bit = 16, | ||
1224 | .burst_32bit = 8, | ||
1225 | .reg = COH901318_CX_CTRL_BURST_COUNT_32_BYTES, | ||
1226 | }, | ||
1227 | { | ||
1228 | .burst_8bit = 16, | ||
1229 | .burst_16bit = 8, | ||
1230 | .burst_32bit = 4, | ||
1231 | .reg = COH901318_CX_CTRL_BURST_COUNT_16_BYTES, | ||
1232 | }, | ||
1233 | { | ||
1234 | .burst_8bit = 8, | ||
1235 | .burst_16bit = 4, | ||
1236 | .burst_32bit = 2, | ||
1237 | .reg = COH901318_CX_CTRL_BURST_COUNT_8_BYTES, | ||
1238 | }, | ||
1239 | { | ||
1240 | .burst_8bit = 4, | ||
1241 | .burst_16bit = 2, | ||
1242 | .burst_32bit = 1, | ||
1243 | .reg = COH901318_CX_CTRL_BURST_COUNT_4_BYTES, | ||
1244 | }, | ||
1245 | { | ||
1246 | .burst_8bit = 2, | ||
1247 | .burst_16bit = 1, | ||
1248 | .burst_32bit = 0, | ||
1249 | .reg = COH901318_CX_CTRL_BURST_COUNT_2_BYTES, | ||
1250 | }, | ||
1251 | { | ||
1252 | .burst_8bit = 1, | ||
1253 | .burst_16bit = 0, | ||
1254 | .burst_32bit = 0, | ||
1255 | .reg = COH901318_CX_CTRL_BURST_COUNT_1_BYTE, | ||
1256 | }, | ||
1257 | }; | ||
1258 | |||
1259 | static void coh901318_dma_set_runtimeconfig(struct dma_chan *chan, | ||
1260 | struct dma_slave_config *config) | ||
1261 | { | ||
1262 | struct coh901318_chan *cohc = to_coh901318_chan(chan); | ||
1263 | dma_addr_t addr; | ||
1264 | enum dma_slave_buswidth addr_width; | ||
1265 | u32 maxburst; | ||
1266 | u32 runtime_ctrl = 0; | ||
1267 | int i = 0; | ||
1268 | |||
1269 | /* We only support mem to per or per to mem transfers */ | ||
1270 | if (config->direction == DMA_FROM_DEVICE) { | ||
1271 | addr = config->src_addr; | ||
1272 | addr_width = config->src_addr_width; | ||
1273 | maxburst = config->src_maxburst; | ||
1274 | } else if (config->direction == DMA_TO_DEVICE) { | ||
1275 | addr = config->dst_addr; | ||
1276 | addr_width = config->dst_addr_width; | ||
1277 | maxburst = config->dst_maxburst; | ||
1278 | } else { | ||
1279 | dev_err(COHC_2_DEV(cohc), "illegal channel mode\n"); | ||
1280 | return; | ||
1281 | } | ||
1282 | |||
1283 | dev_dbg(COHC_2_DEV(cohc), "configure channel for %d byte transfers\n", | ||
1284 | addr_width); | ||
1285 | switch (addr_width) { | ||
1286 | case DMA_SLAVE_BUSWIDTH_1_BYTE: | ||
1287 | runtime_ctrl |= | ||
1288 | COH901318_CX_CTRL_SRC_BUS_SIZE_8_BITS | | ||
1289 | COH901318_CX_CTRL_DST_BUS_SIZE_8_BITS; | ||
1290 | |||
1291 | while (i < ARRAY_SIZE(burst_sizes)) { | ||
1292 | if (burst_sizes[i].burst_8bit <= maxburst) | ||
1293 | break; | ||
1294 | i++; | ||
1295 | } | ||
1296 | |||
1297 | break; | ||
1298 | case DMA_SLAVE_BUSWIDTH_2_BYTES: | ||
1299 | runtime_ctrl |= | ||
1300 | COH901318_CX_CTRL_SRC_BUS_SIZE_16_BITS | | ||
1301 | COH901318_CX_CTRL_DST_BUS_SIZE_16_BITS; | ||
1302 | |||
1303 | while (i < ARRAY_SIZE(burst_sizes)) { | ||
1304 | if (burst_sizes[i].burst_16bit <= maxburst) | ||
1305 | break; | ||
1306 | i++; | ||
1307 | } | ||
1308 | |||
1309 | break; | ||
1310 | case DMA_SLAVE_BUSWIDTH_4_BYTES: | ||
1311 | /* Direction doesn't matter here, it's 32/32 bits */ | ||
1312 | runtime_ctrl |= | ||
1313 | COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | | ||
1314 | COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS; | ||
1315 | |||
1316 | while (i < ARRAY_SIZE(burst_sizes)) { | ||
1317 | if (burst_sizes[i].burst_32bit <= maxburst) | ||
1318 | break; | ||
1319 | i++; | ||
1320 | } | ||
1321 | |||
1322 | break; | ||
1323 | default: | ||
1324 | dev_err(COHC_2_DEV(cohc), | ||
1325 | "bad runtimeconfig: alien address width\n"); | ||
1326 | return; | ||
1327 | } | ||
1328 | |||
1329 | runtime_ctrl |= burst_sizes[i].reg; | ||
1330 | dev_dbg(COHC_2_DEV(cohc), | ||
1331 | "selected burst size %d bytes for address width %d bytes, maxburst %d\n", | ||
1332 | burst_sizes[i].burst_8bit, addr_width, maxburst); | ||
1333 | |||
1334 | cohc->runtime_addr = addr; | ||
1335 | cohc->runtime_ctrl = runtime_ctrl; | ||
1336 | } | ||
1337 | |||
1178 | static int | 1338 | static int |
1179 | coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | 1339 | coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, |
1180 | unsigned long arg) | 1340 | unsigned long arg) |
@@ -1184,6 +1344,14 @@ coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | |||
1184 | struct coh901318_desc *cohd; | 1344 | struct coh901318_desc *cohd; |
1185 | void __iomem *virtbase = cohc->base->virtbase; | 1345 | void __iomem *virtbase = cohc->base->virtbase; |
1186 | 1346 | ||
1347 | if (cmd == DMA_SLAVE_CONFIG) { | ||
1348 | struct dma_slave_config *config = | ||
1349 | (struct dma_slave_config *) arg; | ||
1350 | |||
1351 | coh901318_dma_set_runtimeconfig(chan, config); | ||
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1187 | if (cmd == DMA_PAUSE) { | 1355 | if (cmd == DMA_PAUSE) { |
1188 | coh901318_pause(chan); | 1356 | coh901318_pause(chan); |
1189 | return 0; | 1357 | return 0; |
@@ -1240,6 +1408,7 @@ coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | |||
1240 | 1408 | ||
1241 | return 0; | 1409 | return 0; |
1242 | } | 1410 | } |
1411 | |||
1243 | void coh901318_base_init(struct dma_device *dma, const int *pick_chans, | 1412 | void coh901318_base_init(struct dma_device *dma, const int *pick_chans, |
1244 | struct coh901318_base *base) | 1413 | struct coh901318_base *base) |
1245 | { | 1414 | { |
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 68d58c414cf0..5589358b684d 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c | |||
@@ -540,7 +540,7 @@ static int dmatest_add_channel(struct dma_chan *chan) | |||
540 | struct dmatest_chan *dtc; | 540 | struct dmatest_chan *dtc; |
541 | struct dma_device *dma_dev = chan->device; | 541 | struct dma_device *dma_dev = chan->device; |
542 | unsigned int thread_count = 0; | 542 | unsigned int thread_count = 0; |
543 | unsigned int cnt; | 543 | int cnt; |
544 | 544 | ||
545 | dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); | 545 | dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); |
546 | if (!dtc) { | 546 | if (!dtc) { |
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c new file mode 100644 index 000000000000..c2591e8d9b6e --- /dev/null +++ b/drivers/dma/intel_mid_dma.c | |||
@@ -0,0 +1,1143 @@ | |||
1 | /* | ||
2 | * intel_mid_dma.c - Intel Langwell DMA Drivers | ||
3 | * | ||
4 | * Copyright (C) 2008-10 Intel Corp | ||
5 | * Author: Vinod Koul <vinod.koul@intel.com> | ||
6 | * The driver design is based on dw_dmac driver | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
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 as published by | ||
11 | * the Free Software Foundation; version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
21 | * | ||
22 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
23 | * | ||
24 | * | ||
25 | */ | ||
26 | #include <linux/pci.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/intel_mid_dma.h> | ||
29 | |||
30 | #define MAX_CHAN 4 /*max ch across controllers*/ | ||
31 | #include "intel_mid_dma_regs.h" | ||
32 | |||
33 | #define INTEL_MID_DMAC1_ID 0x0814 | ||
34 | #define INTEL_MID_DMAC2_ID 0x0813 | ||
35 | #define INTEL_MID_GP_DMAC2_ID 0x0827 | ||
36 | #define INTEL_MFLD_DMAC1_ID 0x0830 | ||
37 | #define LNW_PERIPHRAL_MASK_BASE 0xFFAE8008 | ||
38 | #define LNW_PERIPHRAL_MASK_SIZE 0x10 | ||
39 | #define LNW_PERIPHRAL_STATUS 0x0 | ||
40 | #define LNW_PERIPHRAL_MASK 0x8 | ||
41 | |||
42 | struct intel_mid_dma_probe_info { | ||
43 | u8 max_chan; | ||
44 | u8 ch_base; | ||
45 | u16 block_size; | ||
46 | u32 pimr_mask; | ||
47 | }; | ||
48 | |||
49 | #define INFO(_max_chan, _ch_base, _block_size, _pimr_mask) \ | ||
50 | ((kernel_ulong_t)&(struct intel_mid_dma_probe_info) { \ | ||
51 | .max_chan = (_max_chan), \ | ||
52 | .ch_base = (_ch_base), \ | ||
53 | .block_size = (_block_size), \ | ||
54 | .pimr_mask = (_pimr_mask), \ | ||
55 | }) | ||
56 | |||
57 | /***************************************************************************** | ||
58 | Utility Functions*/ | ||
59 | /** | ||
60 | * get_ch_index - convert status to channel | ||
61 | * @status: status mask | ||
62 | * @base: dma ch base value | ||
63 | * | ||
64 | * Modify the status mask and return the channel index needing | ||
65 | * attention (or -1 if neither) | ||
66 | */ | ||
67 | static int get_ch_index(int *status, unsigned int base) | ||
68 | { | ||
69 | int i; | ||
70 | for (i = 0; i < MAX_CHAN; i++) { | ||
71 | if (*status & (1 << (i + base))) { | ||
72 | *status = *status & ~(1 << (i + base)); | ||
73 | pr_debug("MDMA: index %d New status %x\n", i, *status); | ||
74 | return i; | ||
75 | } | ||
76 | } | ||
77 | return -1; | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * get_block_ts - calculates dma transaction length | ||
82 | * @len: dma transfer length | ||
83 | * @tx_width: dma transfer src width | ||
84 | * @block_size: dma controller max block size | ||
85 | * | ||
86 | * Based on src width calculate the DMA trsaction length in data items | ||
87 | * return data items or FFFF if exceeds max length for block | ||
88 | */ | ||
89 | static int get_block_ts(int len, int tx_width, int block_size) | ||
90 | { | ||
91 | int byte_width = 0, block_ts = 0; | ||
92 | |||
93 | switch (tx_width) { | ||
94 | case LNW_DMA_WIDTH_8BIT: | ||
95 | byte_width = 1; | ||
96 | break; | ||
97 | case LNW_DMA_WIDTH_16BIT: | ||
98 | byte_width = 2; | ||
99 | break; | ||
100 | case LNW_DMA_WIDTH_32BIT: | ||
101 | default: | ||
102 | byte_width = 4; | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | block_ts = len/byte_width; | ||
107 | if (block_ts > block_size) | ||
108 | block_ts = 0xFFFF; | ||
109 | return block_ts; | ||
110 | } | ||
111 | |||
112 | /***************************************************************************** | ||
113 | DMAC1 interrupt Functions*/ | ||
114 | |||
115 | /** | ||
116 | * dmac1_mask_periphral_intr - mask the periphral interrupt | ||
117 | * @midc: dma channel for which masking is required | ||
118 | * | ||
119 | * Masks the DMA periphral interrupt | ||
120 | * this is valid for DMAC1 family controllers only | ||
121 | * This controller should have periphral mask registers already mapped | ||
122 | */ | ||
123 | static void dmac1_mask_periphral_intr(struct intel_mid_dma_chan *midc) | ||
124 | { | ||
125 | u32 pimr; | ||
126 | struct middma_device *mid = to_middma_device(midc->chan.device); | ||
127 | |||
128 | if (mid->pimr_mask) { | ||
129 | pimr = readl(mid->mask_reg + LNW_PERIPHRAL_MASK); | ||
130 | pimr |= mid->pimr_mask; | ||
131 | writel(pimr, mid->mask_reg + LNW_PERIPHRAL_MASK); | ||
132 | } | ||
133 | return; | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * dmac1_unmask_periphral_intr - unmask the periphral interrupt | ||
138 | * @midc: dma channel for which masking is required | ||
139 | * | ||
140 | * UnMasks the DMA periphral interrupt, | ||
141 | * this is valid for DMAC1 family controllers only | ||
142 | * This controller should have periphral mask registers already mapped | ||
143 | */ | ||
144 | static void dmac1_unmask_periphral_intr(struct intel_mid_dma_chan *midc) | ||
145 | { | ||
146 | u32 pimr; | ||
147 | struct middma_device *mid = to_middma_device(midc->chan.device); | ||
148 | |||
149 | if (mid->pimr_mask) { | ||
150 | pimr = readl(mid->mask_reg + LNW_PERIPHRAL_MASK); | ||
151 | pimr &= ~mid->pimr_mask; | ||
152 | writel(pimr, mid->mask_reg + LNW_PERIPHRAL_MASK); | ||
153 | } | ||
154 | return; | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * enable_dma_interrupt - enable the periphral interrupt | ||
159 | * @midc: dma channel for which enable interrupt is required | ||
160 | * | ||
161 | * Enable the DMA periphral interrupt, | ||
162 | * this is valid for DMAC1 family controllers only | ||
163 | * This controller should have periphral mask registers already mapped | ||
164 | */ | ||
165 | static void enable_dma_interrupt(struct intel_mid_dma_chan *midc) | ||
166 | { | ||
167 | dmac1_unmask_periphral_intr(midc); | ||
168 | |||
169 | /*en ch interrupts*/ | ||
170 | iowrite32(UNMASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_TFR); | ||
171 | iowrite32(UNMASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_ERR); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * disable_dma_interrupt - disable the periphral interrupt | ||
177 | * @midc: dma channel for which disable interrupt is required | ||
178 | * | ||
179 | * Disable the DMA periphral interrupt, | ||
180 | * this is valid for DMAC1 family controllers only | ||
181 | * This controller should have periphral mask registers already mapped | ||
182 | */ | ||
183 | static void disable_dma_interrupt(struct intel_mid_dma_chan *midc) | ||
184 | { | ||
185 | /*Check LPE PISR, make sure fwd is disabled*/ | ||
186 | dmac1_mask_periphral_intr(midc); | ||
187 | iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_BLOCK); | ||
188 | iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_TFR); | ||
189 | iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_ERR); | ||
190 | return; | ||
191 | } | ||
192 | |||
193 | /***************************************************************************** | ||
194 | DMA channel helper Functions*/ | ||
195 | /** | ||
196 | * mid_desc_get - get a descriptor | ||
197 | * @midc: dma channel for which descriptor is required | ||
198 | * | ||
199 | * Obtain a descriptor for the channel. Returns NULL if none are free. | ||
200 | * Once the descriptor is returned it is private until put on another | ||
201 | * list or freed | ||
202 | */ | ||
203 | static struct intel_mid_dma_desc *midc_desc_get(struct intel_mid_dma_chan *midc) | ||
204 | { | ||
205 | struct intel_mid_dma_desc *desc, *_desc; | ||
206 | struct intel_mid_dma_desc *ret = NULL; | ||
207 | |||
208 | spin_lock_bh(&midc->lock); | ||
209 | list_for_each_entry_safe(desc, _desc, &midc->free_list, desc_node) { | ||
210 | if (async_tx_test_ack(&desc->txd)) { | ||
211 | list_del(&desc->desc_node); | ||
212 | ret = desc; | ||
213 | break; | ||
214 | } | ||
215 | } | ||
216 | spin_unlock_bh(&midc->lock); | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * mid_desc_put - put a descriptor | ||
222 | * @midc: dma channel for which descriptor is required | ||
223 | * @desc: descriptor to put | ||
224 | * | ||
225 | * Return a descriptor from lwn_desc_get back to the free pool | ||
226 | */ | ||
227 | static void midc_desc_put(struct intel_mid_dma_chan *midc, | ||
228 | struct intel_mid_dma_desc *desc) | ||
229 | { | ||
230 | if (desc) { | ||
231 | spin_lock_bh(&midc->lock); | ||
232 | list_add_tail(&desc->desc_node, &midc->free_list); | ||
233 | spin_unlock_bh(&midc->lock); | ||
234 | } | ||
235 | } | ||
236 | /** | ||
237 | * midc_dostart - begin a DMA transaction | ||
238 | * @midc: channel for which txn is to be started | ||
239 | * @first: first descriptor of series | ||
240 | * | ||
241 | * Load a transaction into the engine. This must be called with midc->lock | ||
242 | * held and bh disabled. | ||
243 | */ | ||
244 | static void midc_dostart(struct intel_mid_dma_chan *midc, | ||
245 | struct intel_mid_dma_desc *first) | ||
246 | { | ||
247 | struct middma_device *mid = to_middma_device(midc->chan.device); | ||
248 | |||
249 | /* channel is idle */ | ||
250 | if (midc->in_use && test_ch_en(midc->dma_base, midc->ch_id)) { | ||
251 | /*error*/ | ||
252 | pr_err("ERR_MDMA: channel is busy in start\n"); | ||
253 | /* The tasklet will hopefully advance the queue... */ | ||
254 | return; | ||
255 | } | ||
256 | |||
257 | /*write registers and en*/ | ||
258 | iowrite32(first->sar, midc->ch_regs + SAR); | ||
259 | iowrite32(first->dar, midc->ch_regs + DAR); | ||
260 | iowrite32(first->cfg_hi, midc->ch_regs + CFG_HIGH); | ||
261 | iowrite32(first->cfg_lo, midc->ch_regs + CFG_LOW); | ||
262 | iowrite32(first->ctl_lo, midc->ch_regs + CTL_LOW); | ||
263 | iowrite32(first->ctl_hi, midc->ch_regs + CTL_HIGH); | ||
264 | pr_debug("MDMA:TX SAR %x,DAR %x,CFGL %x,CFGH %x,CTLH %x, CTLL %x\n", | ||
265 | (int)first->sar, (int)first->dar, first->cfg_hi, | ||
266 | first->cfg_lo, first->ctl_hi, first->ctl_lo); | ||
267 | |||
268 | iowrite32(ENABLE_CHANNEL(midc->ch_id), mid->dma_base + DMA_CHAN_EN); | ||
269 | first->status = DMA_IN_PROGRESS; | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * midc_descriptor_complete - process completed descriptor | ||
274 | * @midc: channel owning the descriptor | ||
275 | * @desc: the descriptor itself | ||
276 | * | ||
277 | * Process a completed descriptor and perform any callbacks upon | ||
278 | * the completion. The completion handling drops the lock during the | ||
279 | * callbacks but must be called with the lock held. | ||
280 | */ | ||
281 | static void midc_descriptor_complete(struct intel_mid_dma_chan *midc, | ||
282 | struct intel_mid_dma_desc *desc) | ||
283 | { | ||
284 | struct dma_async_tx_descriptor *txd = &desc->txd; | ||
285 | dma_async_tx_callback callback_txd = NULL; | ||
286 | void *param_txd = NULL; | ||
287 | |||
288 | midc->completed = txd->cookie; | ||
289 | callback_txd = txd->callback; | ||
290 | param_txd = txd->callback_param; | ||
291 | |||
292 | list_move(&desc->desc_node, &midc->free_list); | ||
293 | |||
294 | spin_unlock_bh(&midc->lock); | ||
295 | if (callback_txd) { | ||
296 | pr_debug("MDMA: TXD callback set ... calling\n"); | ||
297 | callback_txd(param_txd); | ||
298 | spin_lock_bh(&midc->lock); | ||
299 | return; | ||
300 | } | ||
301 | spin_lock_bh(&midc->lock); | ||
302 | |||
303 | } | ||
304 | /** | ||
305 | * midc_scan_descriptors - check the descriptors in channel | ||
306 | * mark completed when tx is completete | ||
307 | * @mid: device | ||
308 | * @midc: channel to scan | ||
309 | * | ||
310 | * Walk the descriptor chain for the device and process any entries | ||
311 | * that are complete. | ||
312 | */ | ||
313 | static void midc_scan_descriptors(struct middma_device *mid, | ||
314 | struct intel_mid_dma_chan *midc) | ||
315 | { | ||
316 | struct intel_mid_dma_desc *desc = NULL, *_desc = NULL; | ||
317 | |||
318 | /*tx is complete*/ | ||
319 | list_for_each_entry_safe(desc, _desc, &midc->active_list, desc_node) { | ||
320 | if (desc->status == DMA_IN_PROGRESS) { | ||
321 | desc->status = DMA_SUCCESS; | ||
322 | midc_descriptor_complete(midc, desc); | ||
323 | } | ||
324 | } | ||
325 | return; | ||
326 | } | ||
327 | |||
328 | /***************************************************************************** | ||
329 | DMA engine callback Functions*/ | ||
330 | /** | ||
331 | * intel_mid_dma_tx_submit - callback to submit DMA transaction | ||
332 | * @tx: dma engine descriptor | ||
333 | * | ||
334 | * Submit the DMA trasaction for this descriptor, start if ch idle | ||
335 | */ | ||
336 | static dma_cookie_t intel_mid_dma_tx_submit(struct dma_async_tx_descriptor *tx) | ||
337 | { | ||
338 | struct intel_mid_dma_desc *desc = to_intel_mid_dma_desc(tx); | ||
339 | struct intel_mid_dma_chan *midc = to_intel_mid_dma_chan(tx->chan); | ||
340 | dma_cookie_t cookie; | ||
341 | |||
342 | spin_lock_bh(&midc->lock); | ||
343 | cookie = midc->chan.cookie; | ||
344 | |||
345 | if (++cookie < 0) | ||
346 | cookie = 1; | ||
347 | |||
348 | midc->chan.cookie = cookie; | ||
349 | desc->txd.cookie = cookie; | ||
350 | |||
351 | |||
352 | if (list_empty(&midc->active_list)) { | ||
353 | midc_dostart(midc, desc); | ||
354 | list_add_tail(&desc->desc_node, &midc->active_list); | ||
355 | } else { | ||
356 | list_add_tail(&desc->desc_node, &midc->queue); | ||
357 | } | ||
358 | spin_unlock_bh(&midc->lock); | ||
359 | |||
360 | return cookie; | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * intel_mid_dma_issue_pending - callback to issue pending txn | ||
365 | * @chan: chan where pending trascation needs to be checked and submitted | ||
366 | * | ||
367 | * Call for scan to issue pending descriptors | ||
368 | */ | ||
369 | static void intel_mid_dma_issue_pending(struct dma_chan *chan) | ||
370 | { | ||
371 | struct intel_mid_dma_chan *midc = to_intel_mid_dma_chan(chan); | ||
372 | |||
373 | spin_lock_bh(&midc->lock); | ||
374 | if (!list_empty(&midc->queue)) | ||
375 | midc_scan_descriptors(to_middma_device(chan->device), midc); | ||
376 | spin_unlock_bh(&midc->lock); | ||
377 | } | ||
378 | |||
379 | /** | ||
380 | * intel_mid_dma_tx_status - Return status of txn | ||
381 | * @chan: chan for where status needs to be checked | ||
382 | * @cookie: cookie for txn | ||
383 | * @txstate: DMA txn state | ||
384 | * | ||
385 | * Return status of DMA txn | ||
386 | */ | ||
387 | static enum dma_status intel_mid_dma_tx_status(struct dma_chan *chan, | ||
388 | dma_cookie_t cookie, | ||
389 | struct dma_tx_state *txstate) | ||
390 | { | ||
391 | struct intel_mid_dma_chan *midc = to_intel_mid_dma_chan(chan); | ||
392 | dma_cookie_t last_used; | ||
393 | dma_cookie_t last_complete; | ||
394 | int ret; | ||
395 | |||
396 | last_complete = midc->completed; | ||
397 | last_used = chan->cookie; | ||
398 | |||
399 | ret = dma_async_is_complete(cookie, last_complete, last_used); | ||
400 | if (ret != DMA_SUCCESS) { | ||
401 | midc_scan_descriptors(to_middma_device(chan->device), midc); | ||
402 | |||
403 | last_complete = midc->completed; | ||
404 | last_used = chan->cookie; | ||
405 | |||
406 | ret = dma_async_is_complete(cookie, last_complete, last_used); | ||
407 | } | ||
408 | |||
409 | if (txstate) { | ||
410 | txstate->last = last_complete; | ||
411 | txstate->used = last_used; | ||
412 | txstate->residue = 0; | ||
413 | } | ||
414 | return ret; | ||
415 | } | ||
416 | |||
417 | /** | ||
418 | * intel_mid_dma_device_control - DMA device control | ||
419 | * @chan: chan for DMA control | ||
420 | * @cmd: control cmd | ||
421 | * @arg: cmd arg value | ||
422 | * | ||
423 | * Perform DMA control command | ||
424 | */ | ||
425 | static int intel_mid_dma_device_control(struct dma_chan *chan, | ||
426 | enum dma_ctrl_cmd cmd, unsigned long arg) | ||
427 | { | ||
428 | struct intel_mid_dma_chan *midc = to_intel_mid_dma_chan(chan); | ||
429 | struct middma_device *mid = to_middma_device(chan->device); | ||
430 | struct intel_mid_dma_desc *desc, *_desc; | ||
431 | LIST_HEAD(list); | ||
432 | |||
433 | if (cmd != DMA_TERMINATE_ALL) | ||
434 | return -ENXIO; | ||
435 | |||
436 | spin_lock_bh(&midc->lock); | ||
437 | if (midc->in_use == false) { | ||
438 | spin_unlock_bh(&midc->lock); | ||
439 | return 0; | ||
440 | } | ||
441 | list_splice_init(&midc->free_list, &list); | ||
442 | midc->descs_allocated = 0; | ||
443 | midc->slave = NULL; | ||
444 | |||
445 | /* Disable interrupts */ | ||
446 | disable_dma_interrupt(midc); | ||
447 | |||
448 | spin_unlock_bh(&midc->lock); | ||
449 | list_for_each_entry_safe(desc, _desc, &list, desc_node) { | ||
450 | pr_debug("MDMA: freeing descriptor %p\n", desc); | ||
451 | pci_pool_free(mid->dma_pool, desc, desc->txd.phys); | ||
452 | } | ||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | /** | ||
457 | * intel_mid_dma_prep_slave_sg - Prep slave sg txn | ||
458 | * @chan: chan for DMA transfer | ||
459 | * @sgl: scatter gather list | ||
460 | * @sg_len: length of sg txn | ||
461 | * @direction: DMA transfer dirtn | ||
462 | * @flags: DMA flags | ||
463 | * | ||
464 | * Do DMA sg txn: NOT supported now | ||
465 | */ | ||
466 | static struct dma_async_tx_descriptor *intel_mid_dma_prep_slave_sg( | ||
467 | struct dma_chan *chan, struct scatterlist *sgl, | ||
468 | unsigned int sg_len, enum dma_data_direction direction, | ||
469 | unsigned long flags) | ||
470 | { | ||
471 | /*not supported now*/ | ||
472 | return NULL; | ||
473 | } | ||
474 | |||
475 | /** | ||
476 | * intel_mid_dma_prep_memcpy - Prep memcpy txn | ||
477 | * @chan: chan for DMA transfer | ||
478 | * @dest: destn address | ||
479 | * @src: src address | ||
480 | * @len: DMA transfer len | ||
481 | * @flags: DMA flags | ||
482 | * | ||
483 | * Perform a DMA memcpy. Note we support slave periphral DMA transfers only | ||
484 | * The periphral txn details should be filled in slave structure properly | ||
485 | * Returns the descriptor for this txn | ||
486 | */ | ||
487 | static struct dma_async_tx_descriptor *intel_mid_dma_prep_memcpy( | ||
488 | struct dma_chan *chan, dma_addr_t dest, | ||
489 | dma_addr_t src, size_t len, unsigned long flags) | ||
490 | { | ||
491 | struct intel_mid_dma_chan *midc; | ||
492 | struct intel_mid_dma_desc *desc = NULL; | ||
493 | struct intel_mid_dma_slave *mids; | ||
494 | union intel_mid_dma_ctl_lo ctl_lo; | ||
495 | union intel_mid_dma_ctl_hi ctl_hi; | ||
496 | union intel_mid_dma_cfg_lo cfg_lo; | ||
497 | union intel_mid_dma_cfg_hi cfg_hi; | ||
498 | enum intel_mid_dma_width width = 0; | ||
499 | |||
500 | pr_debug("MDMA: Prep for memcpy\n"); | ||
501 | WARN_ON(!chan); | ||
502 | if (!len) | ||
503 | return NULL; | ||
504 | |||
505 | mids = chan->private; | ||
506 | WARN_ON(!mids); | ||
507 | |||
508 | midc = to_intel_mid_dma_chan(chan); | ||
509 | WARN_ON(!midc); | ||
510 | |||
511 | pr_debug("MDMA:called for DMA %x CH %d Length %zu\n", | ||
512 | midc->dma->pci_id, midc->ch_id, len); | ||
513 | pr_debug("MDMA:Cfg passed Mode %x, Dirn %x, HS %x, Width %x\n", | ||
514 | mids->cfg_mode, mids->dirn, mids->hs_mode, mids->src_width); | ||
515 | |||
516 | /*calculate CFG_LO*/ | ||
517 | if (mids->hs_mode == LNW_DMA_SW_HS) { | ||
518 | cfg_lo.cfg_lo = 0; | ||
519 | cfg_lo.cfgx.hs_sel_dst = 1; | ||
520 | cfg_lo.cfgx.hs_sel_src = 1; | ||
521 | } else if (mids->hs_mode == LNW_DMA_HW_HS) | ||
522 | cfg_lo.cfg_lo = 0x00000; | ||
523 | |||
524 | /*calculate CFG_HI*/ | ||
525 | if (mids->cfg_mode == LNW_DMA_MEM_TO_MEM) { | ||
526 | /*SW HS only*/ | ||
527 | cfg_hi.cfg_hi = 0; | ||
528 | } else { | ||
529 | cfg_hi.cfg_hi = 0; | ||
530 | if (midc->dma->pimr_mask) { | ||
531 | cfg_hi.cfgx.protctl = 0x0; /*default value*/ | ||
532 | cfg_hi.cfgx.fifo_mode = 1; | ||
533 | if (mids->dirn == DMA_TO_DEVICE) { | ||
534 | cfg_hi.cfgx.src_per = 0; | ||
535 | if (mids->device_instance == 0) | ||
536 | cfg_hi.cfgx.dst_per = 3; | ||
537 | if (mids->device_instance == 1) | ||
538 | cfg_hi.cfgx.dst_per = 1; | ||
539 | } else if (mids->dirn == DMA_FROM_DEVICE) { | ||
540 | if (mids->device_instance == 0) | ||
541 | cfg_hi.cfgx.src_per = 2; | ||
542 | if (mids->device_instance == 1) | ||
543 | cfg_hi.cfgx.src_per = 0; | ||
544 | cfg_hi.cfgx.dst_per = 0; | ||
545 | } | ||
546 | } else { | ||
547 | cfg_hi.cfgx.protctl = 0x1; /*default value*/ | ||
548 | cfg_hi.cfgx.src_per = cfg_hi.cfgx.dst_per = | ||
549 | midc->ch_id - midc->dma->chan_base; | ||
550 | } | ||
551 | } | ||
552 | |||
553 | /*calculate CTL_HI*/ | ||
554 | ctl_hi.ctlx.reser = 0; | ||
555 | width = mids->src_width; | ||
556 | |||
557 | ctl_hi.ctlx.block_ts = get_block_ts(len, width, midc->dma->block_size); | ||
558 | pr_debug("MDMA:calc len %d for block size %d\n", | ||
559 | ctl_hi.ctlx.block_ts, midc->dma->block_size); | ||
560 | /*calculate CTL_LO*/ | ||
561 | ctl_lo.ctl_lo = 0; | ||
562 | ctl_lo.ctlx.int_en = 1; | ||
563 | ctl_lo.ctlx.dst_tr_width = mids->dst_width; | ||
564 | ctl_lo.ctlx.src_tr_width = mids->src_width; | ||
565 | ctl_lo.ctlx.dst_msize = mids->src_msize; | ||
566 | ctl_lo.ctlx.src_msize = mids->dst_msize; | ||
567 | |||
568 | if (mids->cfg_mode == LNW_DMA_MEM_TO_MEM) { | ||
569 | ctl_lo.ctlx.tt_fc = 0; | ||
570 | ctl_lo.ctlx.sinc = 0; | ||
571 | ctl_lo.ctlx.dinc = 0; | ||
572 | } else { | ||
573 | if (mids->dirn == DMA_TO_DEVICE) { | ||
574 | ctl_lo.ctlx.sinc = 0; | ||
575 | ctl_lo.ctlx.dinc = 2; | ||
576 | ctl_lo.ctlx.tt_fc = 1; | ||
577 | } else if (mids->dirn == DMA_FROM_DEVICE) { | ||
578 | ctl_lo.ctlx.sinc = 2; | ||
579 | ctl_lo.ctlx.dinc = 0; | ||
580 | ctl_lo.ctlx.tt_fc = 2; | ||
581 | } | ||
582 | } | ||
583 | |||
584 | pr_debug("MDMA:Calc CTL LO %x, CTL HI %x, CFG LO %x, CFG HI %x\n", | ||
585 | ctl_lo.ctl_lo, ctl_hi.ctl_hi, cfg_lo.cfg_lo, cfg_hi.cfg_hi); | ||
586 | |||
587 | enable_dma_interrupt(midc); | ||
588 | |||
589 | desc = midc_desc_get(midc); | ||
590 | if (desc == NULL) | ||
591 | goto err_desc_get; | ||
592 | desc->sar = src; | ||
593 | desc->dar = dest ; | ||
594 | desc->len = len; | ||
595 | desc->cfg_hi = cfg_hi.cfg_hi; | ||
596 | desc->cfg_lo = cfg_lo.cfg_lo; | ||
597 | desc->ctl_lo = ctl_lo.ctl_lo; | ||
598 | desc->ctl_hi = ctl_hi.ctl_hi; | ||
599 | desc->width = width; | ||
600 | desc->dirn = mids->dirn; | ||
601 | return &desc->txd; | ||
602 | |||
603 | err_desc_get: | ||
604 | pr_err("ERR_MDMA: Failed to get desc\n"); | ||
605 | midc_desc_put(midc, desc); | ||
606 | return NULL; | ||
607 | } | ||
608 | |||
609 | /** | ||
610 | * intel_mid_dma_free_chan_resources - Frees dma resources | ||
611 | * @chan: chan requiring attention | ||
612 | * | ||
613 | * Frees the allocated resources on this DMA chan | ||
614 | */ | ||
615 | static void intel_mid_dma_free_chan_resources(struct dma_chan *chan) | ||
616 | { | ||
617 | struct intel_mid_dma_chan *midc = to_intel_mid_dma_chan(chan); | ||
618 | struct middma_device *mid = to_middma_device(chan->device); | ||
619 | struct intel_mid_dma_desc *desc, *_desc; | ||
620 | |||
621 | if (true == midc->in_use) { | ||
622 | /*trying to free ch in use!!!!!*/ | ||
623 | pr_err("ERR_MDMA: trying to free ch in use\n"); | ||
624 | } | ||
625 | |||
626 | spin_lock_bh(&midc->lock); | ||
627 | midc->descs_allocated = 0; | ||
628 | list_for_each_entry_safe(desc, _desc, &midc->active_list, desc_node) { | ||
629 | list_del(&desc->desc_node); | ||
630 | pci_pool_free(mid->dma_pool, desc, desc->txd.phys); | ||
631 | } | ||
632 | list_for_each_entry_safe(desc, _desc, &midc->free_list, desc_node) { | ||
633 | list_del(&desc->desc_node); | ||
634 | pci_pool_free(mid->dma_pool, desc, desc->txd.phys); | ||
635 | } | ||
636 | list_for_each_entry_safe(desc, _desc, &midc->queue, desc_node) { | ||
637 | list_del(&desc->desc_node); | ||
638 | pci_pool_free(mid->dma_pool, desc, desc->txd.phys); | ||
639 | } | ||
640 | spin_unlock_bh(&midc->lock); | ||
641 | midc->in_use = false; | ||
642 | /* Disable CH interrupts */ | ||
643 | iowrite32(MASK_INTR_REG(midc->ch_id), mid->dma_base + MASK_BLOCK); | ||
644 | iowrite32(MASK_INTR_REG(midc->ch_id), mid->dma_base + MASK_ERR); | ||
645 | } | ||
646 | |||
647 | /** | ||
648 | * intel_mid_dma_alloc_chan_resources - Allocate dma resources | ||
649 | * @chan: chan requiring attention | ||
650 | * | ||
651 | * Allocates DMA resources on this chan | ||
652 | * Return the descriptors allocated | ||
653 | */ | ||
654 | static int intel_mid_dma_alloc_chan_resources(struct dma_chan *chan) | ||
655 | { | ||
656 | struct intel_mid_dma_chan *midc = to_intel_mid_dma_chan(chan); | ||
657 | struct middma_device *mid = to_middma_device(chan->device); | ||
658 | struct intel_mid_dma_desc *desc; | ||
659 | dma_addr_t phys; | ||
660 | int i = 0; | ||
661 | |||
662 | |||
663 | /* ASSERT: channel is idle */ | ||
664 | if (test_ch_en(mid->dma_base, midc->ch_id)) { | ||
665 | /*ch is not idle*/ | ||
666 | pr_err("ERR_MDMA: ch not idle\n"); | ||
667 | return -EIO; | ||
668 | } | ||
669 | midc->completed = chan->cookie = 1; | ||
670 | |||
671 | spin_lock_bh(&midc->lock); | ||
672 | while (midc->descs_allocated < DESCS_PER_CHANNEL) { | ||
673 | spin_unlock_bh(&midc->lock); | ||
674 | desc = pci_pool_alloc(mid->dma_pool, GFP_KERNEL, &phys); | ||
675 | if (!desc) { | ||
676 | pr_err("ERR_MDMA: desc failed\n"); | ||
677 | return -ENOMEM; | ||
678 | /*check*/ | ||
679 | } | ||
680 | dma_async_tx_descriptor_init(&desc->txd, chan); | ||
681 | desc->txd.tx_submit = intel_mid_dma_tx_submit; | ||
682 | desc->txd.flags = DMA_CTRL_ACK; | ||
683 | desc->txd.phys = phys; | ||
684 | spin_lock_bh(&midc->lock); | ||
685 | i = ++midc->descs_allocated; | ||
686 | list_add_tail(&desc->desc_node, &midc->free_list); | ||
687 | } | ||
688 | spin_unlock_bh(&midc->lock); | ||
689 | midc->in_use = false; | ||
690 | pr_debug("MID_DMA: Desc alloc done ret: %d desc\n", i); | ||
691 | return i; | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * midc_handle_error - Handle DMA txn error | ||
696 | * @mid: controller where error occured | ||
697 | * @midc: chan where error occured | ||
698 | * | ||
699 | * Scan the descriptor for error | ||
700 | */ | ||
701 | static void midc_handle_error(struct middma_device *mid, | ||
702 | struct intel_mid_dma_chan *midc) | ||
703 | { | ||
704 | midc_scan_descriptors(mid, midc); | ||
705 | } | ||
706 | |||
707 | /** | ||
708 | * dma_tasklet - DMA interrupt tasklet | ||
709 | * @data: tasklet arg (the controller structure) | ||
710 | * | ||
711 | * Scan the controller for interrupts for completion/error | ||
712 | * Clear the interrupt and call for handling completion/error | ||
713 | */ | ||
714 | static void dma_tasklet(unsigned long data) | ||
715 | { | ||
716 | struct middma_device *mid = NULL; | ||
717 | struct intel_mid_dma_chan *midc = NULL; | ||
718 | u32 status; | ||
719 | int i; | ||
720 | |||
721 | mid = (struct middma_device *)data; | ||
722 | if (mid == NULL) { | ||
723 | pr_err("ERR_MDMA: tasklet Null param\n"); | ||
724 | return; | ||
725 | } | ||
726 | pr_debug("MDMA: in tasklet for device %x\n", mid->pci_id); | ||
727 | status = ioread32(mid->dma_base + RAW_TFR); | ||
728 | pr_debug("MDMA:RAW_TFR %x\n", status); | ||
729 | status &= mid->intr_mask; | ||
730 | while (status) { | ||
731 | /*txn interrupt*/ | ||
732 | i = get_ch_index(&status, mid->chan_base); | ||
733 | if (i < 0) { | ||
734 | pr_err("ERR_MDMA:Invalid ch index %x\n", i); | ||
735 | return; | ||
736 | } | ||
737 | midc = &mid->ch[i]; | ||
738 | if (midc == NULL) { | ||
739 | pr_err("ERR_MDMA:Null param midc\n"); | ||
740 | return; | ||
741 | } | ||
742 | pr_debug("MDMA:Tx complete interrupt %x, Ch No %d Index %d\n", | ||
743 | status, midc->ch_id, i); | ||
744 | /*clearing this interrupts first*/ | ||
745 | iowrite32((1 << midc->ch_id), mid->dma_base + CLEAR_TFR); | ||
746 | iowrite32((1 << midc->ch_id), mid->dma_base + CLEAR_BLOCK); | ||
747 | |||
748 | spin_lock_bh(&midc->lock); | ||
749 | midc_scan_descriptors(mid, midc); | ||
750 | pr_debug("MDMA:Scan of desc... complete, unmasking\n"); | ||
751 | iowrite32(UNMASK_INTR_REG(midc->ch_id), | ||
752 | mid->dma_base + MASK_TFR); | ||
753 | spin_unlock_bh(&midc->lock); | ||
754 | } | ||
755 | |||
756 | status = ioread32(mid->dma_base + RAW_ERR); | ||
757 | status &= mid->intr_mask; | ||
758 | while (status) { | ||
759 | /*err interrupt*/ | ||
760 | i = get_ch_index(&status, mid->chan_base); | ||
761 | if (i < 0) { | ||
762 | pr_err("ERR_MDMA:Invalid ch index %x\n", i); | ||
763 | return; | ||
764 | } | ||
765 | midc = &mid->ch[i]; | ||
766 | if (midc == NULL) { | ||
767 | pr_err("ERR_MDMA:Null param midc\n"); | ||
768 | return; | ||
769 | } | ||
770 | pr_debug("MDMA:Tx complete interrupt %x, Ch No %d Index %d\n", | ||
771 | status, midc->ch_id, i); | ||
772 | |||
773 | iowrite32((1 << midc->ch_id), mid->dma_base + CLEAR_ERR); | ||
774 | spin_lock_bh(&midc->lock); | ||
775 | midc_handle_error(mid, midc); | ||
776 | iowrite32(UNMASK_INTR_REG(midc->ch_id), | ||
777 | mid->dma_base + MASK_ERR); | ||
778 | spin_unlock_bh(&midc->lock); | ||
779 | } | ||
780 | pr_debug("MDMA:Exiting takslet...\n"); | ||
781 | return; | ||
782 | } | ||
783 | |||
784 | static void dma_tasklet1(unsigned long data) | ||
785 | { | ||
786 | pr_debug("MDMA:in takslet1...\n"); | ||
787 | return dma_tasklet(data); | ||
788 | } | ||
789 | |||
790 | static void dma_tasklet2(unsigned long data) | ||
791 | { | ||
792 | pr_debug("MDMA:in takslet2...\n"); | ||
793 | return dma_tasklet(data); | ||
794 | } | ||
795 | |||
796 | /** | ||
797 | * intel_mid_dma_interrupt - DMA ISR | ||
798 | * @irq: IRQ where interrupt occurred | ||
799 | * @data: ISR cllback data (the controller structure) | ||
800 | * | ||
801 | * See if this is our interrupt if so then schedule the tasklet | ||
802 | * otherwise ignore | ||
803 | */ | ||
804 | static irqreturn_t intel_mid_dma_interrupt(int irq, void *data) | ||
805 | { | ||
806 | struct middma_device *mid = data; | ||
807 | u32 status; | ||
808 | int call_tasklet = 0; | ||
809 | |||
810 | /*DMA Interrupt*/ | ||
811 | pr_debug("MDMA:Got an interrupt on irq %d\n", irq); | ||
812 | if (!mid) { | ||
813 | pr_err("ERR_MDMA:null pointer mid\n"); | ||
814 | return -EINVAL; | ||
815 | } | ||
816 | |||
817 | status = ioread32(mid->dma_base + RAW_TFR); | ||
818 | pr_debug("MDMA: Status %x, Mask %x\n", status, mid->intr_mask); | ||
819 | status &= mid->intr_mask; | ||
820 | if (status) { | ||
821 | /*need to disable intr*/ | ||
822 | iowrite32((status << 8), mid->dma_base + MASK_TFR); | ||
823 | pr_debug("MDMA: Calling tasklet %x\n", status); | ||
824 | call_tasklet = 1; | ||
825 | } | ||
826 | status = ioread32(mid->dma_base + RAW_ERR); | ||
827 | status &= mid->intr_mask; | ||
828 | if (status) { | ||
829 | iowrite32(MASK_INTR_REG(status), mid->dma_base + MASK_ERR); | ||
830 | call_tasklet = 1; | ||
831 | } | ||
832 | if (call_tasklet) | ||
833 | tasklet_schedule(&mid->tasklet); | ||
834 | |||
835 | return IRQ_HANDLED; | ||
836 | } | ||
837 | |||
838 | static irqreturn_t intel_mid_dma_interrupt1(int irq, void *data) | ||
839 | { | ||
840 | return intel_mid_dma_interrupt(irq, data); | ||
841 | } | ||
842 | |||
843 | static irqreturn_t intel_mid_dma_interrupt2(int irq, void *data) | ||
844 | { | ||
845 | return intel_mid_dma_interrupt(irq, data); | ||
846 | } | ||
847 | |||
848 | /** | ||
849 | * mid_setup_dma - Setup the DMA controller | ||
850 | * @pdev: Controller PCI device structure | ||
851 | * | ||
852 | * Initilize the DMA controller, channels, registers with DMA engine, | ||
853 | * ISR. Initilize DMA controller channels. | ||
854 | */ | ||
855 | static int mid_setup_dma(struct pci_dev *pdev) | ||
856 | { | ||
857 | struct middma_device *dma = pci_get_drvdata(pdev); | ||
858 | int err, i; | ||
859 | unsigned int irq_level; | ||
860 | |||
861 | /* DMA coherent memory pool for DMA descriptor allocations */ | ||
862 | dma->dma_pool = pci_pool_create("intel_mid_dma_desc_pool", pdev, | ||
863 | sizeof(struct intel_mid_dma_desc), | ||
864 | 32, 0); | ||
865 | if (NULL == dma->dma_pool) { | ||
866 | pr_err("ERR_MDMA:pci_pool_create failed\n"); | ||
867 | err = -ENOMEM; | ||
868 | kfree(dma); | ||
869 | goto err_dma_pool; | ||
870 | } | ||
871 | |||
872 | INIT_LIST_HEAD(&dma->common.channels); | ||
873 | dma->pci_id = pdev->device; | ||
874 | if (dma->pimr_mask) { | ||
875 | dma->mask_reg = ioremap(LNW_PERIPHRAL_MASK_BASE, | ||
876 | LNW_PERIPHRAL_MASK_SIZE); | ||
877 | if (dma->mask_reg == NULL) { | ||
878 | pr_err("ERR_MDMA:Cant map periphral intr space !!\n"); | ||
879 | return -ENOMEM; | ||
880 | } | ||
881 | } else | ||
882 | dma->mask_reg = NULL; | ||
883 | |||
884 | pr_debug("MDMA:Adding %d channel for this controller\n", dma->max_chan); | ||
885 | /*init CH structures*/ | ||
886 | dma->intr_mask = 0; | ||
887 | for (i = 0; i < dma->max_chan; i++) { | ||
888 | struct intel_mid_dma_chan *midch = &dma->ch[i]; | ||
889 | |||
890 | midch->chan.device = &dma->common; | ||
891 | midch->chan.cookie = 1; | ||
892 | midch->chan.chan_id = i; | ||
893 | midch->ch_id = dma->chan_base + i; | ||
894 | pr_debug("MDMA:Init CH %d, ID %d\n", i, midch->ch_id); | ||
895 | |||
896 | midch->dma_base = dma->dma_base; | ||
897 | midch->ch_regs = dma->dma_base + DMA_CH_SIZE * midch->ch_id; | ||
898 | midch->dma = dma; | ||
899 | dma->intr_mask |= 1 << (dma->chan_base + i); | ||
900 | spin_lock_init(&midch->lock); | ||
901 | |||
902 | INIT_LIST_HEAD(&midch->active_list); | ||
903 | INIT_LIST_HEAD(&midch->queue); | ||
904 | INIT_LIST_HEAD(&midch->free_list); | ||
905 | /*mask interrupts*/ | ||
906 | iowrite32(MASK_INTR_REG(midch->ch_id), | ||
907 | dma->dma_base + MASK_BLOCK); | ||
908 | iowrite32(MASK_INTR_REG(midch->ch_id), | ||
909 | dma->dma_base + MASK_SRC_TRAN); | ||
910 | iowrite32(MASK_INTR_REG(midch->ch_id), | ||
911 | dma->dma_base + MASK_DST_TRAN); | ||
912 | iowrite32(MASK_INTR_REG(midch->ch_id), | ||
913 | dma->dma_base + MASK_ERR); | ||
914 | iowrite32(MASK_INTR_REG(midch->ch_id), | ||
915 | dma->dma_base + MASK_TFR); | ||
916 | |||
917 | disable_dma_interrupt(midch); | ||
918 | list_add_tail(&midch->chan.device_node, &dma->common.channels); | ||
919 | } | ||
920 | pr_debug("MDMA: Calc Mask as %x for this controller\n", dma->intr_mask); | ||
921 | |||
922 | /*init dma structure*/ | ||
923 | dma_cap_zero(dma->common.cap_mask); | ||
924 | dma_cap_set(DMA_MEMCPY, dma->common.cap_mask); | ||
925 | dma_cap_set(DMA_SLAVE, dma->common.cap_mask); | ||
926 | dma_cap_set(DMA_PRIVATE, dma->common.cap_mask); | ||
927 | dma->common.dev = &pdev->dev; | ||
928 | dma->common.chancnt = dma->max_chan; | ||
929 | |||
930 | dma->common.device_alloc_chan_resources = | ||
931 | intel_mid_dma_alloc_chan_resources; | ||
932 | dma->common.device_free_chan_resources = | ||
933 | intel_mid_dma_free_chan_resources; | ||
934 | |||
935 | dma->common.device_tx_status = intel_mid_dma_tx_status; | ||
936 | dma->common.device_prep_dma_memcpy = intel_mid_dma_prep_memcpy; | ||
937 | dma->common.device_issue_pending = intel_mid_dma_issue_pending; | ||
938 | dma->common.device_prep_slave_sg = intel_mid_dma_prep_slave_sg; | ||
939 | dma->common.device_control = intel_mid_dma_device_control; | ||
940 | |||
941 | /*enable dma cntrl*/ | ||
942 | iowrite32(REG_BIT0, dma->dma_base + DMA_CFG); | ||
943 | |||
944 | /*register irq */ | ||
945 | if (dma->pimr_mask) { | ||
946 | irq_level = IRQF_SHARED; | ||
947 | pr_debug("MDMA:Requesting irq shared for DMAC1\n"); | ||
948 | err = request_irq(pdev->irq, intel_mid_dma_interrupt1, | ||
949 | IRQF_SHARED, "INTEL_MID_DMAC1", dma); | ||
950 | if (0 != err) | ||
951 | goto err_irq; | ||
952 | } else { | ||
953 | dma->intr_mask = 0x03; | ||
954 | irq_level = 0; | ||
955 | pr_debug("MDMA:Requesting irq for DMAC2\n"); | ||
956 | err = request_irq(pdev->irq, intel_mid_dma_interrupt2, | ||
957 | 0, "INTEL_MID_DMAC2", dma); | ||
958 | if (0 != err) | ||
959 | goto err_irq; | ||
960 | } | ||
961 | /*register device w/ engine*/ | ||
962 | err = dma_async_device_register(&dma->common); | ||
963 | if (0 != err) { | ||
964 | pr_err("ERR_MDMA:device_register failed: %d\n", err); | ||
965 | goto err_engine; | ||
966 | } | ||
967 | if (dma->pimr_mask) { | ||
968 | pr_debug("setting up tasklet1 for DMAC1\n"); | ||
969 | tasklet_init(&dma->tasklet, dma_tasklet1, (unsigned long)dma); | ||
970 | } else { | ||
971 | pr_debug("setting up tasklet2 for DMAC2\n"); | ||
972 | tasklet_init(&dma->tasklet, dma_tasklet2, (unsigned long)dma); | ||
973 | } | ||
974 | return 0; | ||
975 | |||
976 | err_engine: | ||
977 | free_irq(pdev->irq, dma); | ||
978 | err_irq: | ||
979 | pci_pool_destroy(dma->dma_pool); | ||
980 | kfree(dma); | ||
981 | err_dma_pool: | ||
982 | pr_err("ERR_MDMA:setup_dma failed: %d\n", err); | ||
983 | return err; | ||
984 | |||
985 | } | ||
986 | |||
987 | /** | ||
988 | * middma_shutdown - Shutdown the DMA controller | ||
989 | * @pdev: Controller PCI device structure | ||
990 | * | ||
991 | * Called by remove | ||
992 | * Unregister DMa controller, clear all structures and free interrupt | ||
993 | */ | ||
994 | static void middma_shutdown(struct pci_dev *pdev) | ||
995 | { | ||
996 | struct middma_device *device = pci_get_drvdata(pdev); | ||
997 | |||
998 | dma_async_device_unregister(&device->common); | ||
999 | pci_pool_destroy(device->dma_pool); | ||
1000 | if (device->mask_reg) | ||
1001 | iounmap(device->mask_reg); | ||
1002 | if (device->dma_base) | ||
1003 | iounmap(device->dma_base); | ||
1004 | free_irq(pdev->irq, device); | ||
1005 | return; | ||
1006 | } | ||
1007 | |||
1008 | /** | ||
1009 | * intel_mid_dma_probe - PCI Probe | ||
1010 | * @pdev: Controller PCI device structure | ||
1011 | * @id: pci device id structure | ||
1012 | * | ||
1013 | * Initilize the PCI device, map BARs, query driver data. | ||
1014 | * Call setup_dma to complete contoller and chan initilzation | ||
1015 | */ | ||
1016 | static int __devinit intel_mid_dma_probe(struct pci_dev *pdev, | ||
1017 | const struct pci_device_id *id) | ||
1018 | { | ||
1019 | struct middma_device *device; | ||
1020 | u32 base_addr, bar_size; | ||
1021 | struct intel_mid_dma_probe_info *info; | ||
1022 | int err; | ||
1023 | |||
1024 | pr_debug("MDMA: probe for %x\n", pdev->device); | ||
1025 | info = (void *)id->driver_data; | ||
1026 | pr_debug("MDMA: CH %d, base %d, block len %d, Periphral mask %x\n", | ||
1027 | info->max_chan, info->ch_base, | ||
1028 | info->block_size, info->pimr_mask); | ||
1029 | |||
1030 | err = pci_enable_device(pdev); | ||
1031 | if (err) | ||
1032 | goto err_enable_device; | ||
1033 | |||
1034 | err = pci_request_regions(pdev, "intel_mid_dmac"); | ||
1035 | if (err) | ||
1036 | goto err_request_regions; | ||
1037 | |||
1038 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
1039 | if (err) | ||
1040 | goto err_set_dma_mask; | ||
1041 | |||
1042 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
1043 | if (err) | ||
1044 | goto err_set_dma_mask; | ||
1045 | |||
1046 | device = kzalloc(sizeof(*device), GFP_KERNEL); | ||
1047 | if (!device) { | ||
1048 | pr_err("ERR_MDMA:kzalloc failed probe\n"); | ||
1049 | err = -ENOMEM; | ||
1050 | goto err_kzalloc; | ||
1051 | } | ||
1052 | device->pdev = pci_dev_get(pdev); | ||
1053 | |||
1054 | base_addr = pci_resource_start(pdev, 0); | ||
1055 | bar_size = pci_resource_len(pdev, 0); | ||
1056 | device->dma_base = ioremap_nocache(base_addr, DMA_REG_SIZE); | ||
1057 | if (!device->dma_base) { | ||
1058 | pr_err("ERR_MDMA:ioremap failed\n"); | ||
1059 | err = -ENOMEM; | ||
1060 | goto err_ioremap; | ||
1061 | } | ||
1062 | pci_set_drvdata(pdev, device); | ||
1063 | pci_set_master(pdev); | ||
1064 | device->max_chan = info->max_chan; | ||
1065 | device->chan_base = info->ch_base; | ||
1066 | device->block_size = info->block_size; | ||
1067 | device->pimr_mask = info->pimr_mask; | ||
1068 | |||
1069 | err = mid_setup_dma(pdev); | ||
1070 | if (err) | ||
1071 | goto err_dma; | ||
1072 | |||
1073 | return 0; | ||
1074 | |||
1075 | err_dma: | ||
1076 | iounmap(device->dma_base); | ||
1077 | err_ioremap: | ||
1078 | pci_dev_put(pdev); | ||
1079 | kfree(device); | ||
1080 | err_kzalloc: | ||
1081 | err_set_dma_mask: | ||
1082 | pci_release_regions(pdev); | ||
1083 | pci_disable_device(pdev); | ||
1084 | err_request_regions: | ||
1085 | err_enable_device: | ||
1086 | pr_err("ERR_MDMA:Probe failed %d\n", err); | ||
1087 | return err; | ||
1088 | } | ||
1089 | |||
1090 | /** | ||
1091 | * intel_mid_dma_remove - PCI remove | ||
1092 | * @pdev: Controller PCI device structure | ||
1093 | * | ||
1094 | * Free up all resources and data | ||
1095 | * Call shutdown_dma to complete contoller and chan cleanup | ||
1096 | */ | ||
1097 | static void __devexit intel_mid_dma_remove(struct pci_dev *pdev) | ||
1098 | { | ||
1099 | struct middma_device *device = pci_get_drvdata(pdev); | ||
1100 | middma_shutdown(pdev); | ||
1101 | pci_dev_put(pdev); | ||
1102 | kfree(device); | ||
1103 | pci_release_regions(pdev); | ||
1104 | pci_disable_device(pdev); | ||
1105 | } | ||
1106 | |||
1107 | /****************************************************************************** | ||
1108 | * PCI stuff | ||
1109 | */ | ||
1110 | static struct pci_device_id intel_mid_dma_ids[] = { | ||
1111 | { PCI_VDEVICE(INTEL, INTEL_MID_DMAC1_ID), INFO(2, 6, 4095, 0x200020)}, | ||
1112 | { PCI_VDEVICE(INTEL, INTEL_MID_DMAC2_ID), INFO(2, 0, 2047, 0)}, | ||
1113 | { PCI_VDEVICE(INTEL, INTEL_MID_GP_DMAC2_ID), INFO(2, 0, 2047, 0)}, | ||
1114 | { PCI_VDEVICE(INTEL, INTEL_MFLD_DMAC1_ID), INFO(4, 0, 4095, 0x400040)}, | ||
1115 | { 0, } | ||
1116 | }; | ||
1117 | MODULE_DEVICE_TABLE(pci, intel_mid_dma_ids); | ||
1118 | |||
1119 | static struct pci_driver intel_mid_dma_pci = { | ||
1120 | .name = "Intel MID DMA", | ||
1121 | .id_table = intel_mid_dma_ids, | ||
1122 | .probe = intel_mid_dma_probe, | ||
1123 | .remove = __devexit_p(intel_mid_dma_remove), | ||
1124 | }; | ||
1125 | |||
1126 | static int __init intel_mid_dma_init(void) | ||
1127 | { | ||
1128 | pr_debug("INFO_MDMA: LNW DMA Driver Version %s\n", | ||
1129 | INTEL_MID_DMA_DRIVER_VERSION); | ||
1130 | return pci_register_driver(&intel_mid_dma_pci); | ||
1131 | } | ||
1132 | fs_initcall(intel_mid_dma_init); | ||
1133 | |||
1134 | static void __exit intel_mid_dma_exit(void) | ||
1135 | { | ||
1136 | pci_unregister_driver(&intel_mid_dma_pci); | ||
1137 | } | ||
1138 | module_exit(intel_mid_dma_exit); | ||
1139 | |||
1140 | MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); | ||
1141 | MODULE_DESCRIPTION("Intel (R) MID DMAC Driver"); | ||
1142 | MODULE_LICENSE("GPL v2"); | ||
1143 | MODULE_VERSION(INTEL_MID_DMA_DRIVER_VERSION); | ||
diff --git a/drivers/dma/intel_mid_dma_regs.h b/drivers/dma/intel_mid_dma_regs.h new file mode 100644 index 000000000000..d81aa658ab09 --- /dev/null +++ b/drivers/dma/intel_mid_dma_regs.h | |||
@@ -0,0 +1,260 @@ | |||
1 | /* | ||
2 | * intel_mid_dma_regs.h - Intel MID DMA Drivers | ||
3 | * | ||
4 | * Copyright (C) 2008-10 Intel Corp | ||
5 | * Author: Vinod Koul <vinod.koul@intel.com> | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
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 as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
20 | * | ||
21 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
22 | * | ||
23 | * | ||
24 | */ | ||
25 | #ifndef __INTEL_MID_DMAC_REGS_H__ | ||
26 | #define __INTEL_MID_DMAC_REGS_H__ | ||
27 | |||
28 | #include <linux/dmaengine.h> | ||
29 | #include <linux/dmapool.h> | ||
30 | #include <linux/pci_ids.h> | ||
31 | |||
32 | #define INTEL_MID_DMA_DRIVER_VERSION "1.0.5" | ||
33 | |||
34 | #define REG_BIT0 0x00000001 | ||
35 | #define REG_BIT8 0x00000100 | ||
36 | |||
37 | #define UNMASK_INTR_REG(chan_num) \ | ||
38 | ((REG_BIT0 << chan_num) | (REG_BIT8 << chan_num)) | ||
39 | #define MASK_INTR_REG(chan_num) (REG_BIT8 << chan_num) | ||
40 | |||
41 | #define ENABLE_CHANNEL(chan_num) \ | ||
42 | ((REG_BIT0 << chan_num) | (REG_BIT8 << chan_num)) | ||
43 | |||
44 | #define DESCS_PER_CHANNEL 16 | ||
45 | /*DMA Registers*/ | ||
46 | /*registers associated with channel programming*/ | ||
47 | #define DMA_REG_SIZE 0x400 | ||
48 | #define DMA_CH_SIZE 0x58 | ||
49 | |||
50 | /*CH X REG = (DMA_CH_SIZE)*CH_NO + REG*/ | ||
51 | #define SAR 0x00 /* Source Address Register*/ | ||
52 | #define DAR 0x08 /* Destination Address Register*/ | ||
53 | #define CTL_LOW 0x18 /* Control Register*/ | ||
54 | #define CTL_HIGH 0x1C /* Control Register*/ | ||
55 | #define CFG_LOW 0x40 /* Configuration Register Low*/ | ||
56 | #define CFG_HIGH 0x44 /* Configuration Register high*/ | ||
57 | |||
58 | #define STATUS_TFR 0x2E8 | ||
59 | #define STATUS_BLOCK 0x2F0 | ||
60 | #define STATUS_ERR 0x308 | ||
61 | |||
62 | #define RAW_TFR 0x2C0 | ||
63 | #define RAW_BLOCK 0x2C8 | ||
64 | #define RAW_ERR 0x2E0 | ||
65 | |||
66 | #define MASK_TFR 0x310 | ||
67 | #define MASK_BLOCK 0x318 | ||
68 | #define MASK_SRC_TRAN 0x320 | ||
69 | #define MASK_DST_TRAN 0x328 | ||
70 | #define MASK_ERR 0x330 | ||
71 | |||
72 | #define CLEAR_TFR 0x338 | ||
73 | #define CLEAR_BLOCK 0x340 | ||
74 | #define CLEAR_SRC_TRAN 0x348 | ||
75 | #define CLEAR_DST_TRAN 0x350 | ||
76 | #define CLEAR_ERR 0x358 | ||
77 | |||
78 | #define INTR_STATUS 0x360 | ||
79 | #define DMA_CFG 0x398 | ||
80 | #define DMA_CHAN_EN 0x3A0 | ||
81 | |||
82 | /*DMA channel control registers*/ | ||
83 | union intel_mid_dma_ctl_lo { | ||
84 | struct { | ||
85 | u32 int_en:1; /*enable or disable interrupts*/ | ||
86 | /*should be 0*/ | ||
87 | u32 dst_tr_width:3; /*destination transfer width*/ | ||
88 | /*usually 32 bits = 010*/ | ||
89 | u32 src_tr_width:3; /*source transfer width*/ | ||
90 | /*usually 32 bits = 010*/ | ||
91 | u32 dinc:2; /*destination address inc/dec*/ | ||
92 | /*For mem:INC=00, Periphral NoINC=11*/ | ||
93 | u32 sinc:2; /*source address inc or dec, as above*/ | ||
94 | u32 dst_msize:3; /*destination burst transaction length*/ | ||
95 | /*always = 16 ie 011*/ | ||
96 | u32 src_msize:3; /*source burst transaction length*/ | ||
97 | /*always = 16 ie 011*/ | ||
98 | u32 reser1:3; | ||
99 | u32 tt_fc:3; /*transfer type and flow controller*/ | ||
100 | /*M-M = 000 | ||
101 | P-M = 010 | ||
102 | M-P = 001*/ | ||
103 | u32 dms:2; /*destination master select = 0*/ | ||
104 | u32 sms:2; /*source master select = 0*/ | ||
105 | u32 llp_dst_en:1; /*enable/disable destination LLP = 0*/ | ||
106 | u32 llp_src_en:1; /*enable/disable source LLP = 0*/ | ||
107 | u32 reser2:3; | ||
108 | } ctlx; | ||
109 | u32 ctl_lo; | ||
110 | }; | ||
111 | |||
112 | union intel_mid_dma_ctl_hi { | ||
113 | struct { | ||
114 | u32 block_ts:12; /*block transfer size*/ | ||
115 | /*configured by DMAC*/ | ||
116 | u32 reser:20; | ||
117 | } ctlx; | ||
118 | u32 ctl_hi; | ||
119 | |||
120 | }; | ||
121 | |||
122 | /*DMA channel configuration registers*/ | ||
123 | union intel_mid_dma_cfg_lo { | ||
124 | struct { | ||
125 | u32 reser1:5; | ||
126 | u32 ch_prior:3; /*channel priority = 0*/ | ||
127 | u32 ch_susp:1; /*channel suspend = 0*/ | ||
128 | u32 fifo_empty:1; /*FIFO empty or not R bit = 0*/ | ||
129 | u32 hs_sel_dst:1; /*select HW/SW destn handshaking*/ | ||
130 | /*HW = 0, SW = 1*/ | ||
131 | u32 hs_sel_src:1; /*select HW/SW src handshaking*/ | ||
132 | u32 reser2:6; | ||
133 | u32 dst_hs_pol:1; /*dest HS interface polarity*/ | ||
134 | u32 src_hs_pol:1; /*src HS interface polarity*/ | ||
135 | u32 max_abrst:10; /*max AMBA burst len = 0 (no sw limit*/ | ||
136 | u32 reload_src:1; /*auto reload src addr =1 if src is P*/ | ||
137 | u32 reload_dst:1; /*AR destn addr =1 if dstn is P*/ | ||
138 | } cfgx; | ||
139 | u32 cfg_lo; | ||
140 | }; | ||
141 | |||
142 | union intel_mid_dma_cfg_hi { | ||
143 | struct { | ||
144 | u32 fcmode:1; /*flow control mode = 1*/ | ||
145 | u32 fifo_mode:1; /*FIFO mode select = 1*/ | ||
146 | u32 protctl:3; /*protection control = 0*/ | ||
147 | u32 rsvd:2; | ||
148 | u32 src_per:4; /*src hw HS interface*/ | ||
149 | u32 dst_per:4; /*dstn hw HS interface*/ | ||
150 | u32 reser2:17; | ||
151 | } cfgx; | ||
152 | u32 cfg_hi; | ||
153 | }; | ||
154 | |||
155 | /** | ||
156 | * struct intel_mid_dma_chan - internal mid representation of a DMA channel | ||
157 | * @chan: dma_chan strcture represetation for mid chan | ||
158 | * @ch_regs: MMIO register space pointer to channel register | ||
159 | * @dma_base: MMIO register space DMA engine base pointer | ||
160 | * @ch_id: DMA channel id | ||
161 | * @lock: channel spinlock | ||
162 | * @completed: DMA cookie | ||
163 | * @active_list: current active descriptors | ||
164 | * @queue: current queued up descriptors | ||
165 | * @free_list: current free descriptors | ||
166 | * @slave: dma slave struture | ||
167 | * @descs_allocated: total number of decsiptors allocated | ||
168 | * @dma: dma device struture pointer | ||
169 | * @in_use: bool representing if ch is in use or not | ||
170 | */ | ||
171 | struct intel_mid_dma_chan { | ||
172 | struct dma_chan chan; | ||
173 | void __iomem *ch_regs; | ||
174 | void __iomem *dma_base; | ||
175 | int ch_id; | ||
176 | spinlock_t lock; | ||
177 | dma_cookie_t completed; | ||
178 | struct list_head active_list; | ||
179 | struct list_head queue; | ||
180 | struct list_head free_list; | ||
181 | struct intel_mid_dma_slave *slave; | ||
182 | unsigned int descs_allocated; | ||
183 | struct middma_device *dma; | ||
184 | bool in_use; | ||
185 | }; | ||
186 | |||
187 | static inline struct intel_mid_dma_chan *to_intel_mid_dma_chan( | ||
188 | struct dma_chan *chan) | ||
189 | { | ||
190 | return container_of(chan, struct intel_mid_dma_chan, chan); | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * struct middma_device - internal representation of a DMA device | ||
195 | * @pdev: PCI device | ||
196 | * @dma_base: MMIO register space pointer of DMA | ||
197 | * @dma_pool: for allocating DMA descriptors | ||
198 | * @common: embedded struct dma_device | ||
199 | * @tasklet: dma tasklet for processing interrupts | ||
200 | * @ch: per channel data | ||
201 | * @pci_id: DMA device PCI ID | ||
202 | * @intr_mask: Interrupt mask to be used | ||
203 | * @mask_reg: MMIO register for periphral mask | ||
204 | * @chan_base: Base ch index (read from driver data) | ||
205 | * @max_chan: max number of chs supported (from drv_data) | ||
206 | * @block_size: Block size of DMA transfer supported (from drv_data) | ||
207 | * @pimr_mask: MMIO register addr for periphral interrupt (from drv_data) | ||
208 | */ | ||
209 | struct middma_device { | ||
210 | struct pci_dev *pdev; | ||
211 | void __iomem *dma_base; | ||
212 | struct pci_pool *dma_pool; | ||
213 | struct dma_device common; | ||
214 | struct tasklet_struct tasklet; | ||
215 | struct intel_mid_dma_chan ch[MAX_CHAN]; | ||
216 | unsigned int pci_id; | ||
217 | unsigned int intr_mask; | ||
218 | void __iomem *mask_reg; | ||
219 | int chan_base; | ||
220 | int max_chan; | ||
221 | int block_size; | ||
222 | unsigned int pimr_mask; | ||
223 | }; | ||
224 | |||
225 | static inline struct middma_device *to_middma_device(struct dma_device *common) | ||
226 | { | ||
227 | return container_of(common, struct middma_device, common); | ||
228 | } | ||
229 | |||
230 | struct intel_mid_dma_desc { | ||
231 | void __iomem *block; /*ch ptr*/ | ||
232 | struct list_head desc_node; | ||
233 | struct dma_async_tx_descriptor txd; | ||
234 | size_t len; | ||
235 | dma_addr_t sar; | ||
236 | dma_addr_t dar; | ||
237 | u32 cfg_hi; | ||
238 | u32 cfg_lo; | ||
239 | u32 ctl_lo; | ||
240 | u32 ctl_hi; | ||
241 | dma_addr_t next; | ||
242 | enum dma_data_direction dirn; | ||
243 | enum dma_status status; | ||
244 | enum intel_mid_dma_width width; /*width of DMA txn*/ | ||
245 | enum intel_mid_dma_mode cfg_mode; /*mode configuration*/ | ||
246 | |||
247 | }; | ||
248 | |||
249 | static inline int test_ch_en(void __iomem *dma, u32 ch_no) | ||
250 | { | ||
251 | u32 en_reg = ioread32(dma + DMA_CHAN_EN); | ||
252 | return (en_reg >> ch_no) & 0x1; | ||
253 | } | ||
254 | |||
255 | static inline struct intel_mid_dma_desc *to_intel_mid_dma_desc | ||
256 | (struct dma_async_tx_descriptor *txd) | ||
257 | { | ||
258 | return container_of(txd, struct intel_mid_dma_desc, txd); | ||
259 | } | ||
260 | #endif /*__INTEL_MID_DMAC_REGS_H__*/ | ||
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index 6d3a73b57e54..5216c8a92a21 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h | |||
@@ -97,6 +97,7 @@ struct ioat_chan_common { | |||
97 | #define IOAT_RESET_PENDING 2 | 97 | #define IOAT_RESET_PENDING 2 |
98 | #define IOAT_KOBJ_INIT_FAIL 3 | 98 | #define IOAT_KOBJ_INIT_FAIL 3 |
99 | #define IOAT_RESHAPE_PENDING 4 | 99 | #define IOAT_RESHAPE_PENDING 4 |
100 | #define IOAT_RUN 5 | ||
100 | struct timer_list timer; | 101 | struct timer_list timer; |
101 | #define COMPLETION_TIMEOUT msecs_to_jiffies(100) | 102 | #define COMPLETION_TIMEOUT msecs_to_jiffies(100) |
102 | #define IDLE_TIMEOUT msecs_to_jiffies(2000) | 103 | #define IDLE_TIMEOUT msecs_to_jiffies(2000) |
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 3c8b32a83794..216f9d383b5b 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c | |||
@@ -287,7 +287,10 @@ void ioat2_timer_event(unsigned long data) | |||
287 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); | 287 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); |
288 | dev_err(to_dev(chan), "%s: Channel halted (%x)\n", | 288 | dev_err(to_dev(chan), "%s: Channel halted (%x)\n", |
289 | __func__, chanerr); | 289 | __func__, chanerr); |
290 | BUG_ON(is_ioat_bug(chanerr)); | 290 | if (test_bit(IOAT_RUN, &chan->state)) |
291 | BUG_ON(is_ioat_bug(chanerr)); | ||
292 | else /* we never got off the ground */ | ||
293 | return; | ||
291 | } | 294 | } |
292 | 295 | ||
293 | /* if we haven't made progress and we have already | 296 | /* if we haven't made progress and we have already |
@@ -492,6 +495,8 @@ static struct ioat_ring_ent **ioat2_alloc_ring(struct dma_chan *c, int order, gf | |||
492 | return ring; | 495 | return ring; |
493 | } | 496 | } |
494 | 497 | ||
498 | void ioat2_free_chan_resources(struct dma_chan *c); | ||
499 | |||
495 | /* ioat2_alloc_chan_resources - allocate/initialize ioat2 descriptor ring | 500 | /* ioat2_alloc_chan_resources - allocate/initialize ioat2 descriptor ring |
496 | * @chan: channel to be initialized | 501 | * @chan: channel to be initialized |
497 | */ | 502 | */ |
@@ -500,6 +505,7 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) | |||
500 | struct ioat2_dma_chan *ioat = to_ioat2_chan(c); | 505 | struct ioat2_dma_chan *ioat = to_ioat2_chan(c); |
501 | struct ioat_chan_common *chan = &ioat->base; | 506 | struct ioat_chan_common *chan = &ioat->base; |
502 | struct ioat_ring_ent **ring; | 507 | struct ioat_ring_ent **ring; |
508 | u64 status; | ||
503 | int order; | 509 | int order; |
504 | 510 | ||
505 | /* have we already been set up? */ | 511 | /* have we already been set up? */ |
@@ -540,7 +546,20 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) | |||
540 | tasklet_enable(&chan->cleanup_task); | 546 | tasklet_enable(&chan->cleanup_task); |
541 | ioat2_start_null_desc(ioat); | 547 | ioat2_start_null_desc(ioat); |
542 | 548 | ||
543 | return 1 << ioat->alloc_order; | 549 | /* check that we got off the ground */ |
550 | udelay(5); | ||
551 | status = ioat_chansts(chan); | ||
552 | if (is_ioat_active(status) || is_ioat_idle(status)) { | ||
553 | set_bit(IOAT_RUN, &chan->state); | ||
554 | return 1 << ioat->alloc_order; | ||
555 | } else { | ||
556 | u32 chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); | ||
557 | |||
558 | dev_WARN(to_dev(chan), | ||
559 | "failed to start channel chanerr: %#x\n", chanerr); | ||
560 | ioat2_free_chan_resources(c); | ||
561 | return -EFAULT; | ||
562 | } | ||
544 | } | 563 | } |
545 | 564 | ||
546 | bool reshape_ring(struct ioat2_dma_chan *ioat, int order) | 565 | bool reshape_ring(struct ioat2_dma_chan *ioat, int order) |
@@ -778,6 +797,7 @@ void ioat2_free_chan_resources(struct dma_chan *c) | |||
778 | del_timer_sync(&chan->timer); | 797 | del_timer_sync(&chan->timer); |
779 | device->cleanup_fn((unsigned long) c); | 798 | device->cleanup_fn((unsigned long) c); |
780 | device->reset_hw(chan); | 799 | device->reset_hw(chan); |
800 | clear_bit(IOAT_RUN, &chan->state); | ||
781 | 801 | ||
782 | spin_lock_bh(&chan->cleanup_lock); | 802 | spin_lock_bh(&chan->cleanup_lock); |
783 | spin_lock_bh(&ioat->prep_lock); | 803 | spin_lock_bh(&ioat->prep_lock); |
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index 1cdd22e1051b..d0f499098479 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c | |||
@@ -361,7 +361,10 @@ static void ioat3_timer_event(unsigned long data) | |||
361 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); | 361 | chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); |
362 | dev_err(to_dev(chan), "%s: Channel halted (%x)\n", | 362 | dev_err(to_dev(chan), "%s: Channel halted (%x)\n", |
363 | __func__, chanerr); | 363 | __func__, chanerr); |
364 | BUG_ON(is_ioat_bug(chanerr)); | 364 | if (test_bit(IOAT_RUN, &chan->state)) |
365 | BUG_ON(is_ioat_bug(chanerr)); | ||
366 | else /* we never got off the ground */ | ||
367 | return; | ||
365 | } | 368 | } |
366 | 369 | ||
367 | /* if we haven't made progress and we have already | 370 | /* if we haven't made progress and we have already |
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c new file mode 100644 index 000000000000..3533948b88ba --- /dev/null +++ b/drivers/dma/pch_dma.c | |||
@@ -0,0 +1,957 @@ | |||
1 | /* | ||
2 | * Topcliff PCH DMA controller driver | ||
3 | * Copyright (c) 2010 Intel Corporation | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | #include <linux/dmaengine.h> | ||
20 | #include <linux/dma-mapping.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/pch_dma.h> | ||
26 | |||
27 | #define DRV_NAME "pch-dma" | ||
28 | |||
29 | #define DMA_CTL0_DISABLE 0x0 | ||
30 | #define DMA_CTL0_SG 0x1 | ||
31 | #define DMA_CTL0_ONESHOT 0x2 | ||
32 | #define DMA_CTL0_MODE_MASK_BITS 0x3 | ||
33 | #define DMA_CTL0_DIR_SHIFT_BITS 2 | ||
34 | #define DMA_CTL0_BITS_PER_CH 4 | ||
35 | |||
36 | #define DMA_CTL2_START_SHIFT_BITS 8 | ||
37 | #define DMA_CTL2_IRQ_ENABLE_MASK ((1UL << DMA_CTL2_START_SHIFT_BITS) - 1) | ||
38 | |||
39 | #define DMA_STATUS_IDLE 0x0 | ||
40 | #define DMA_STATUS_DESC_READ 0x1 | ||
41 | #define DMA_STATUS_WAIT 0x2 | ||
42 | #define DMA_STATUS_ACCESS 0x3 | ||
43 | #define DMA_STATUS_BITS_PER_CH 2 | ||
44 | #define DMA_STATUS_MASK_BITS 0x3 | ||
45 | #define DMA_STATUS_SHIFT_BITS 16 | ||
46 | #define DMA_STATUS_IRQ(x) (0x1 << (x)) | ||
47 | #define DMA_STATUS_ERR(x) (0x1 << ((x) + 8)) | ||
48 | |||
49 | #define DMA_DESC_WIDTH_SHIFT_BITS 12 | ||
50 | #define DMA_DESC_WIDTH_1_BYTE (0x3 << DMA_DESC_WIDTH_SHIFT_BITS) | ||
51 | #define DMA_DESC_WIDTH_2_BYTES (0x2 << DMA_DESC_WIDTH_SHIFT_BITS) | ||
52 | #define DMA_DESC_WIDTH_4_BYTES (0x0 << DMA_DESC_WIDTH_SHIFT_BITS) | ||
53 | #define DMA_DESC_MAX_COUNT_1_BYTE 0x3FF | ||
54 | #define DMA_DESC_MAX_COUNT_2_BYTES 0x3FF | ||
55 | #define DMA_DESC_MAX_COUNT_4_BYTES 0x7FF | ||
56 | #define DMA_DESC_END_WITHOUT_IRQ 0x0 | ||
57 | #define DMA_DESC_END_WITH_IRQ 0x1 | ||
58 | #define DMA_DESC_FOLLOW_WITHOUT_IRQ 0x2 | ||
59 | #define DMA_DESC_FOLLOW_WITH_IRQ 0x3 | ||
60 | |||
61 | #define MAX_CHAN_NR 8 | ||
62 | |||
63 | static unsigned int init_nr_desc_per_channel = 64; | ||
64 | module_param(init_nr_desc_per_channel, uint, 0644); | ||
65 | MODULE_PARM_DESC(init_nr_desc_per_channel, | ||
66 | "initial descriptors per channel (default: 64)"); | ||
67 | |||
68 | struct pch_dma_desc_regs { | ||
69 | u32 dev_addr; | ||
70 | u32 mem_addr; | ||
71 | u32 size; | ||
72 | u32 next; | ||
73 | }; | ||
74 | |||
75 | struct pch_dma_regs { | ||
76 | u32 dma_ctl0; | ||
77 | u32 dma_ctl1; | ||
78 | u32 dma_ctl2; | ||
79 | u32 reserved1; | ||
80 | u32 dma_sts0; | ||
81 | u32 dma_sts1; | ||
82 | u32 reserved2; | ||
83 | u32 reserved3; | ||
84 | struct pch_dma_desc_regs desc[0]; | ||
85 | }; | ||
86 | |||
87 | struct pch_dma_desc { | ||
88 | struct pch_dma_desc_regs regs; | ||
89 | struct dma_async_tx_descriptor txd; | ||
90 | struct list_head desc_node; | ||
91 | struct list_head tx_list; | ||
92 | }; | ||
93 | |||
94 | struct pch_dma_chan { | ||
95 | struct dma_chan chan; | ||
96 | void __iomem *membase; | ||
97 | enum dma_data_direction dir; | ||
98 | struct tasklet_struct tasklet; | ||
99 | unsigned long err_status; | ||
100 | |||
101 | spinlock_t lock; | ||
102 | |||
103 | dma_cookie_t completed_cookie; | ||
104 | struct list_head active_list; | ||
105 | struct list_head queue; | ||
106 | struct list_head free_list; | ||
107 | unsigned int descs_allocated; | ||
108 | }; | ||
109 | |||
110 | #define PDC_DEV_ADDR 0x00 | ||
111 | #define PDC_MEM_ADDR 0x04 | ||
112 | #define PDC_SIZE 0x08 | ||
113 | #define PDC_NEXT 0x0C | ||
114 | |||
115 | #define channel_readl(pdc, name) \ | ||
116 | readl((pdc)->membase + PDC_##name) | ||
117 | #define channel_writel(pdc, name, val) \ | ||
118 | writel((val), (pdc)->membase + PDC_##name) | ||
119 | |||
120 | struct pch_dma { | ||
121 | struct dma_device dma; | ||
122 | void __iomem *membase; | ||
123 | struct pci_pool *pool; | ||
124 | struct pch_dma_regs regs; | ||
125 | struct pch_dma_desc_regs ch_regs[MAX_CHAN_NR]; | ||
126 | struct pch_dma_chan channels[0]; | ||
127 | }; | ||
128 | |||
129 | #define PCH_DMA_CTL0 0x00 | ||
130 | #define PCH_DMA_CTL1 0x04 | ||
131 | #define PCH_DMA_CTL2 0x08 | ||
132 | #define PCH_DMA_STS0 0x10 | ||
133 | #define PCH_DMA_STS1 0x14 | ||
134 | |||
135 | #define dma_readl(pd, name) \ | ||
136 | readl((pd)->membase + PCH_DMA_##name) | ||
137 | #define dma_writel(pd, name, val) \ | ||
138 | writel((val), (pd)->membase + PCH_DMA_##name) | ||
139 | |||
140 | static inline struct pch_dma_desc *to_pd_desc(struct dma_async_tx_descriptor *txd) | ||
141 | { | ||
142 | return container_of(txd, struct pch_dma_desc, txd); | ||
143 | } | ||
144 | |||
145 | static inline struct pch_dma_chan *to_pd_chan(struct dma_chan *chan) | ||
146 | { | ||
147 | return container_of(chan, struct pch_dma_chan, chan); | ||
148 | } | ||
149 | |||
150 | static inline struct pch_dma *to_pd(struct dma_device *ddev) | ||
151 | { | ||
152 | return container_of(ddev, struct pch_dma, dma); | ||
153 | } | ||
154 | |||
155 | static inline struct device *chan2dev(struct dma_chan *chan) | ||
156 | { | ||
157 | return &chan->dev->device; | ||
158 | } | ||
159 | |||
160 | static inline struct device *chan2parent(struct dma_chan *chan) | ||
161 | { | ||
162 | return chan->dev->device.parent; | ||
163 | } | ||
164 | |||
165 | static inline struct pch_dma_desc *pdc_first_active(struct pch_dma_chan *pd_chan) | ||
166 | { | ||
167 | return list_first_entry(&pd_chan->active_list, | ||
168 | struct pch_dma_desc, desc_node); | ||
169 | } | ||
170 | |||
171 | static inline struct pch_dma_desc *pdc_first_queued(struct pch_dma_chan *pd_chan) | ||
172 | { | ||
173 | return list_first_entry(&pd_chan->queue, | ||
174 | struct pch_dma_desc, desc_node); | ||
175 | } | ||
176 | |||
177 | static void pdc_enable_irq(struct dma_chan *chan, int enable) | ||
178 | { | ||
179 | struct pch_dma *pd = to_pd(chan->device); | ||
180 | u32 val; | ||
181 | |||
182 | val = dma_readl(pd, CTL2); | ||
183 | |||
184 | if (enable) | ||
185 | val |= 0x1 << chan->chan_id; | ||
186 | else | ||
187 | val &= ~(0x1 << chan->chan_id); | ||
188 | |||
189 | dma_writel(pd, CTL2, val); | ||
190 | |||
191 | dev_dbg(chan2dev(chan), "pdc_enable_irq: chan %d -> %x\n", | ||
192 | chan->chan_id, val); | ||
193 | } | ||
194 | |||
195 | static void pdc_set_dir(struct dma_chan *chan) | ||
196 | { | ||
197 | struct pch_dma_chan *pd_chan = to_pd_chan(chan); | ||
198 | struct pch_dma *pd = to_pd(chan->device); | ||
199 | u32 val; | ||
200 | |||
201 | val = dma_readl(pd, CTL0); | ||
202 | |||
203 | if (pd_chan->dir == DMA_TO_DEVICE) | ||
204 | val |= 0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id + | ||
205 | DMA_CTL0_DIR_SHIFT_BITS); | ||
206 | else | ||
207 | val &= ~(0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id + | ||
208 | DMA_CTL0_DIR_SHIFT_BITS)); | ||
209 | |||
210 | dma_writel(pd, CTL0, val); | ||
211 | |||
212 | dev_dbg(chan2dev(chan), "pdc_set_dir: chan %d -> %x\n", | ||
213 | chan->chan_id, val); | ||
214 | } | ||
215 | |||
216 | static void pdc_set_mode(struct dma_chan *chan, u32 mode) | ||
217 | { | ||
218 | struct pch_dma *pd = to_pd(chan->device); | ||
219 | u32 val; | ||
220 | |||
221 | val = dma_readl(pd, CTL0); | ||
222 | |||
223 | val &= ~(DMA_CTL0_MODE_MASK_BITS << | ||
224 | (DMA_CTL0_BITS_PER_CH * chan->chan_id)); | ||
225 | val |= mode << (DMA_CTL0_BITS_PER_CH * chan->chan_id); | ||
226 | |||
227 | dma_writel(pd, CTL0, val); | ||
228 | |||
229 | dev_dbg(chan2dev(chan), "pdc_set_mode: chan %d -> %x\n", | ||
230 | chan->chan_id, val); | ||
231 | } | ||
232 | |||
233 | static u32 pdc_get_status(struct pch_dma_chan *pd_chan) | ||
234 | { | ||
235 | struct pch_dma *pd = to_pd(pd_chan->chan.device); | ||
236 | u32 val; | ||
237 | |||
238 | val = dma_readl(pd, STS0); | ||
239 | return DMA_STATUS_MASK_BITS & (val >> (DMA_STATUS_SHIFT_BITS + | ||
240 | DMA_STATUS_BITS_PER_CH * pd_chan->chan.chan_id)); | ||
241 | } | ||
242 | |||
243 | static bool pdc_is_idle(struct pch_dma_chan *pd_chan) | ||
244 | { | ||
245 | if (pdc_get_status(pd_chan) == DMA_STATUS_IDLE) | ||
246 | return true; | ||
247 | else | ||
248 | return false; | ||
249 | } | ||
250 | |||
251 | static void pdc_dostart(struct pch_dma_chan *pd_chan, struct pch_dma_desc* desc) | ||
252 | { | ||
253 | struct pch_dma *pd = to_pd(pd_chan->chan.device); | ||
254 | u32 val; | ||
255 | |||
256 | if (!pdc_is_idle(pd_chan)) { | ||
257 | dev_err(chan2dev(&pd_chan->chan), | ||
258 | "BUG: Attempt to start non-idle channel\n"); | ||
259 | return; | ||
260 | } | ||
261 | |||
262 | channel_writel(pd_chan, DEV_ADDR, desc->regs.dev_addr); | ||
263 | channel_writel(pd_chan, MEM_ADDR, desc->regs.mem_addr); | ||
264 | channel_writel(pd_chan, SIZE, desc->regs.size); | ||
265 | channel_writel(pd_chan, NEXT, desc->regs.next); | ||
266 | |||
267 | dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> dev_addr: %x\n", | ||
268 | pd_chan->chan.chan_id, desc->regs.dev_addr); | ||
269 | dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> mem_addr: %x\n", | ||
270 | pd_chan->chan.chan_id, desc->regs.mem_addr); | ||
271 | dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> size: %x\n", | ||
272 | pd_chan->chan.chan_id, desc->regs.size); | ||
273 | dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> next: %x\n", | ||
274 | pd_chan->chan.chan_id, desc->regs.next); | ||
275 | |||
276 | if (list_empty(&desc->tx_list)) | ||
277 | pdc_set_mode(&pd_chan->chan, DMA_CTL0_ONESHOT); | ||
278 | else | ||
279 | pdc_set_mode(&pd_chan->chan, DMA_CTL0_SG); | ||
280 | |||
281 | val = dma_readl(pd, CTL2); | ||
282 | val |= 1 << (DMA_CTL2_START_SHIFT_BITS + pd_chan->chan.chan_id); | ||
283 | dma_writel(pd, CTL2, val); | ||
284 | } | ||
285 | |||
286 | static void pdc_chain_complete(struct pch_dma_chan *pd_chan, | ||
287 | struct pch_dma_desc *desc) | ||
288 | { | ||
289 | struct dma_async_tx_descriptor *txd = &desc->txd; | ||
290 | dma_async_tx_callback callback = txd->callback; | ||
291 | void *param = txd->callback_param; | ||
292 | |||
293 | list_splice_init(&desc->tx_list, &pd_chan->free_list); | ||
294 | list_move(&desc->desc_node, &pd_chan->free_list); | ||
295 | |||
296 | if (callback) | ||
297 | callback(param); | ||
298 | } | ||
299 | |||
300 | static void pdc_complete_all(struct pch_dma_chan *pd_chan) | ||
301 | { | ||
302 | struct pch_dma_desc *desc, *_d; | ||
303 | LIST_HEAD(list); | ||
304 | |||
305 | BUG_ON(!pdc_is_idle(pd_chan)); | ||
306 | |||
307 | if (!list_empty(&pd_chan->queue)) | ||
308 | pdc_dostart(pd_chan, pdc_first_queued(pd_chan)); | ||
309 | |||
310 | list_splice_init(&pd_chan->active_list, &list); | ||
311 | list_splice_init(&pd_chan->queue, &pd_chan->active_list); | ||
312 | |||
313 | list_for_each_entry_safe(desc, _d, &list, desc_node) | ||
314 | pdc_chain_complete(pd_chan, desc); | ||
315 | } | ||
316 | |||
317 | static void pdc_handle_error(struct pch_dma_chan *pd_chan) | ||
318 | { | ||
319 | struct pch_dma_desc *bad_desc; | ||
320 | |||
321 | bad_desc = pdc_first_active(pd_chan); | ||
322 | list_del(&bad_desc->desc_node); | ||
323 | |||
324 | list_splice_init(&pd_chan->queue, pd_chan->active_list.prev); | ||
325 | |||
326 | if (!list_empty(&pd_chan->active_list)) | ||
327 | pdc_dostart(pd_chan, pdc_first_active(pd_chan)); | ||
328 | |||
329 | dev_crit(chan2dev(&pd_chan->chan), "Bad descriptor submitted\n"); | ||
330 | dev_crit(chan2dev(&pd_chan->chan), "descriptor cookie: %d\n", | ||
331 | bad_desc->txd.cookie); | ||
332 | |||
333 | pdc_chain_complete(pd_chan, bad_desc); | ||
334 | } | ||
335 | |||
336 | static void pdc_advance_work(struct pch_dma_chan *pd_chan) | ||
337 | { | ||
338 | if (list_empty(&pd_chan->active_list) || | ||
339 | list_is_singular(&pd_chan->active_list)) { | ||
340 | pdc_complete_all(pd_chan); | ||
341 | } else { | ||
342 | pdc_chain_complete(pd_chan, pdc_first_active(pd_chan)); | ||
343 | pdc_dostart(pd_chan, pdc_first_active(pd_chan)); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | static dma_cookie_t pdc_assign_cookie(struct pch_dma_chan *pd_chan, | ||
348 | struct pch_dma_desc *desc) | ||
349 | { | ||
350 | dma_cookie_t cookie = pd_chan->chan.cookie; | ||
351 | |||
352 | if (++cookie < 0) | ||
353 | cookie = 1; | ||
354 | |||
355 | pd_chan->chan.cookie = cookie; | ||
356 | desc->txd.cookie = cookie; | ||
357 | |||
358 | return cookie; | ||
359 | } | ||
360 | |||
361 | static dma_cookie_t pd_tx_submit(struct dma_async_tx_descriptor *txd) | ||
362 | { | ||
363 | struct pch_dma_desc *desc = to_pd_desc(txd); | ||
364 | struct pch_dma_chan *pd_chan = to_pd_chan(txd->chan); | ||
365 | dma_cookie_t cookie; | ||
366 | |||
367 | spin_lock_bh(&pd_chan->lock); | ||
368 | cookie = pdc_assign_cookie(pd_chan, desc); | ||
369 | |||
370 | if (list_empty(&pd_chan->active_list)) { | ||
371 | list_add_tail(&desc->desc_node, &pd_chan->active_list); | ||
372 | pdc_dostart(pd_chan, desc); | ||
373 | } else { | ||
374 | list_add_tail(&desc->desc_node, &pd_chan->queue); | ||
375 | } | ||
376 | |||
377 | spin_unlock_bh(&pd_chan->lock); | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static struct pch_dma_desc *pdc_alloc_desc(struct dma_chan *chan, gfp_t flags) | ||
382 | { | ||
383 | struct pch_dma_desc *desc = NULL; | ||
384 | struct pch_dma *pd = to_pd(chan->device); | ||
385 | dma_addr_t addr; | ||
386 | |||
387 | desc = pci_pool_alloc(pd->pool, GFP_KERNEL, &addr); | ||
388 | if (desc) { | ||
389 | memset(desc, 0, sizeof(struct pch_dma_desc)); | ||
390 | INIT_LIST_HEAD(&desc->tx_list); | ||
391 | dma_async_tx_descriptor_init(&desc->txd, chan); | ||
392 | desc->txd.tx_submit = pd_tx_submit; | ||
393 | desc->txd.flags = DMA_CTRL_ACK; | ||
394 | desc->txd.phys = addr; | ||
395 | } | ||
396 | |||
397 | return desc; | ||
398 | } | ||
399 | |||
400 | static struct pch_dma_desc *pdc_desc_get(struct pch_dma_chan *pd_chan) | ||
401 | { | ||
402 | struct pch_dma_desc *desc, *_d; | ||
403 | struct pch_dma_desc *ret = NULL; | ||
404 | int i; | ||
405 | |||
406 | spin_lock_bh(&pd_chan->lock); | ||
407 | list_for_each_entry_safe(desc, _d, &pd_chan->free_list, desc_node) { | ||
408 | i++; | ||
409 | if (async_tx_test_ack(&desc->txd)) { | ||
410 | list_del(&desc->desc_node); | ||
411 | ret = desc; | ||
412 | break; | ||
413 | } | ||
414 | dev_dbg(chan2dev(&pd_chan->chan), "desc %p not ACKed\n", desc); | ||
415 | } | ||
416 | spin_unlock_bh(&pd_chan->lock); | ||
417 | dev_dbg(chan2dev(&pd_chan->chan), "scanned %d descriptors\n", i); | ||
418 | |||
419 | if (!ret) { | ||
420 | ret = pdc_alloc_desc(&pd_chan->chan, GFP_NOIO); | ||
421 | if (ret) { | ||
422 | spin_lock_bh(&pd_chan->lock); | ||
423 | pd_chan->descs_allocated++; | ||
424 | spin_unlock_bh(&pd_chan->lock); | ||
425 | } else { | ||
426 | dev_err(chan2dev(&pd_chan->chan), | ||
427 | "failed to alloc desc\n"); | ||
428 | } | ||
429 | } | ||
430 | |||
431 | return ret; | ||
432 | } | ||
433 | |||
434 | static void pdc_desc_put(struct pch_dma_chan *pd_chan, | ||
435 | struct pch_dma_desc *desc) | ||
436 | { | ||
437 | if (desc) { | ||
438 | spin_lock_bh(&pd_chan->lock); | ||
439 | list_splice_init(&desc->tx_list, &pd_chan->free_list); | ||
440 | list_add(&desc->desc_node, &pd_chan->free_list); | ||
441 | spin_unlock_bh(&pd_chan->lock); | ||
442 | } | ||
443 | } | ||
444 | |||
445 | static int pd_alloc_chan_resources(struct dma_chan *chan) | ||
446 | { | ||
447 | struct pch_dma_chan *pd_chan = to_pd_chan(chan); | ||
448 | struct pch_dma_desc *desc; | ||
449 | LIST_HEAD(tmp_list); | ||
450 | int i; | ||
451 | |||
452 | if (!pdc_is_idle(pd_chan)) { | ||
453 | dev_dbg(chan2dev(chan), "DMA channel not idle ?\n"); | ||
454 | return -EIO; | ||
455 | } | ||
456 | |||
457 | if (!list_empty(&pd_chan->free_list)) | ||
458 | return pd_chan->descs_allocated; | ||
459 | |||
460 | for (i = 0; i < init_nr_desc_per_channel; i++) { | ||
461 | desc = pdc_alloc_desc(chan, GFP_KERNEL); | ||
462 | |||
463 | if (!desc) { | ||
464 | dev_warn(chan2dev(chan), | ||
465 | "Only allocated %d initial descriptors\n", i); | ||
466 | break; | ||
467 | } | ||
468 | |||
469 | list_add_tail(&desc->desc_node, &tmp_list); | ||
470 | } | ||
471 | |||
472 | spin_lock_bh(&pd_chan->lock); | ||
473 | list_splice(&tmp_list, &pd_chan->free_list); | ||
474 | pd_chan->descs_allocated = i; | ||
475 | pd_chan->completed_cookie = chan->cookie = 1; | ||
476 | spin_unlock_bh(&pd_chan->lock); | ||
477 | |||
478 | pdc_enable_irq(chan, 1); | ||
479 | pdc_set_dir(chan); | ||
480 | |||
481 | return pd_chan->descs_allocated; | ||
482 | } | ||
483 | |||
484 | static void pd_free_chan_resources(struct dma_chan *chan) | ||
485 | { | ||
486 | struct pch_dma_chan *pd_chan = to_pd_chan(chan); | ||
487 | struct pch_dma *pd = to_pd(chan->device); | ||
488 | struct pch_dma_desc *desc, *_d; | ||
489 | LIST_HEAD(tmp_list); | ||
490 | |||
491 | BUG_ON(!pdc_is_idle(pd_chan)); | ||
492 | BUG_ON(!list_empty(&pd_chan->active_list)); | ||
493 | BUG_ON(!list_empty(&pd_chan->queue)); | ||
494 | |||
495 | spin_lock_bh(&pd_chan->lock); | ||
496 | list_splice_init(&pd_chan->free_list, &tmp_list); | ||
497 | pd_chan->descs_allocated = 0; | ||
498 | spin_unlock_bh(&pd_chan->lock); | ||
499 | |||
500 | list_for_each_entry_safe(desc, _d, &tmp_list, desc_node) | ||
501 | pci_pool_free(pd->pool, desc, desc->txd.phys); | ||
502 | |||
503 | pdc_enable_irq(chan, 0); | ||
504 | } | ||
505 | |||
506 | static enum dma_status pd_tx_status(struct dma_chan *chan, dma_cookie_t cookie, | ||
507 | struct dma_tx_state *txstate) | ||
508 | { | ||
509 | struct pch_dma_chan *pd_chan = to_pd_chan(chan); | ||
510 | dma_cookie_t last_used; | ||
511 | dma_cookie_t last_completed; | ||
512 | int ret; | ||
513 | |||
514 | spin_lock_bh(&pd_chan->lock); | ||
515 | last_completed = pd_chan->completed_cookie; | ||
516 | last_used = chan->cookie; | ||
517 | spin_unlock_bh(&pd_chan->lock); | ||
518 | |||
519 | ret = dma_async_is_complete(cookie, last_completed, last_used); | ||
520 | |||
521 | dma_set_tx_state(txstate, last_completed, last_used, 0); | ||
522 | |||
523 | return ret; | ||
524 | } | ||
525 | |||
526 | static void pd_issue_pending(struct dma_chan *chan) | ||
527 | { | ||
528 | struct pch_dma_chan *pd_chan = to_pd_chan(chan); | ||
529 | |||
530 | if (pdc_is_idle(pd_chan)) { | ||
531 | spin_lock_bh(&pd_chan->lock); | ||
532 | pdc_advance_work(pd_chan); | ||
533 | spin_unlock_bh(&pd_chan->lock); | ||
534 | } | ||
535 | } | ||
536 | |||
537 | static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan, | ||
538 | struct scatterlist *sgl, unsigned int sg_len, | ||
539 | enum dma_data_direction direction, unsigned long flags) | ||
540 | { | ||
541 | struct pch_dma_chan *pd_chan = to_pd_chan(chan); | ||
542 | struct pch_dma_slave *pd_slave = chan->private; | ||
543 | struct pch_dma_desc *first = NULL; | ||
544 | struct pch_dma_desc *prev = NULL; | ||
545 | struct pch_dma_desc *desc = NULL; | ||
546 | struct scatterlist *sg; | ||
547 | dma_addr_t reg; | ||
548 | int i; | ||
549 | |||
550 | if (unlikely(!sg_len)) { | ||
551 | dev_info(chan2dev(chan), "prep_slave_sg: length is zero!\n"); | ||
552 | return NULL; | ||
553 | } | ||
554 | |||
555 | if (direction == DMA_FROM_DEVICE) | ||
556 | reg = pd_slave->rx_reg; | ||
557 | else if (direction == DMA_TO_DEVICE) | ||
558 | reg = pd_slave->tx_reg; | ||
559 | else | ||
560 | return NULL; | ||
561 | |||
562 | for_each_sg(sgl, sg, sg_len, i) { | ||
563 | desc = pdc_desc_get(pd_chan); | ||
564 | |||
565 | if (!desc) | ||
566 | goto err_desc_get; | ||
567 | |||
568 | desc->regs.dev_addr = reg; | ||
569 | desc->regs.mem_addr = sg_phys(sg); | ||
570 | desc->regs.size = sg_dma_len(sg); | ||
571 | desc->regs.next = DMA_DESC_FOLLOW_WITHOUT_IRQ; | ||
572 | |||
573 | switch (pd_slave->width) { | ||
574 | case PCH_DMA_WIDTH_1_BYTE: | ||
575 | if (desc->regs.size > DMA_DESC_MAX_COUNT_1_BYTE) | ||
576 | goto err_desc_get; | ||
577 | desc->regs.size |= DMA_DESC_WIDTH_1_BYTE; | ||
578 | break; | ||
579 | case PCH_DMA_WIDTH_2_BYTES: | ||
580 | if (desc->regs.size > DMA_DESC_MAX_COUNT_2_BYTES) | ||
581 | goto err_desc_get; | ||
582 | desc->regs.size |= DMA_DESC_WIDTH_2_BYTES; | ||
583 | break; | ||
584 | case PCH_DMA_WIDTH_4_BYTES: | ||
585 | if (desc->regs.size > DMA_DESC_MAX_COUNT_4_BYTES) | ||
586 | goto err_desc_get; | ||
587 | desc->regs.size |= DMA_DESC_WIDTH_4_BYTES; | ||
588 | break; | ||
589 | default: | ||
590 | goto err_desc_get; | ||
591 | } | ||
592 | |||
593 | |||
594 | if (!first) { | ||
595 | first = desc; | ||
596 | } else { | ||
597 | prev->regs.next |= desc->txd.phys; | ||
598 | list_add_tail(&desc->desc_node, &first->tx_list); | ||
599 | } | ||
600 | |||
601 | prev = desc; | ||
602 | } | ||
603 | |||
604 | if (flags & DMA_PREP_INTERRUPT) | ||
605 | desc->regs.next = DMA_DESC_END_WITH_IRQ; | ||
606 | else | ||
607 | desc->regs.next = DMA_DESC_END_WITHOUT_IRQ; | ||
608 | |||
609 | first->txd.cookie = -EBUSY; | ||
610 | desc->txd.flags = flags; | ||
611 | |||
612 | return &first->txd; | ||
613 | |||
614 | err_desc_get: | ||
615 | dev_err(chan2dev(chan), "failed to get desc or wrong parameters\n"); | ||
616 | pdc_desc_put(pd_chan, first); | ||
617 | return NULL; | ||
618 | } | ||
619 | |||
620 | static int pd_device_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | ||
621 | unsigned long arg) | ||
622 | { | ||
623 | struct pch_dma_chan *pd_chan = to_pd_chan(chan); | ||
624 | struct pch_dma_desc *desc, *_d; | ||
625 | LIST_HEAD(list); | ||
626 | |||
627 | if (cmd != DMA_TERMINATE_ALL) | ||
628 | return -ENXIO; | ||
629 | |||
630 | spin_lock_bh(&pd_chan->lock); | ||
631 | |||
632 | pdc_set_mode(&pd_chan->chan, DMA_CTL0_DISABLE); | ||
633 | |||
634 | list_splice_init(&pd_chan->active_list, &list); | ||
635 | list_splice_init(&pd_chan->queue, &list); | ||
636 | |||
637 | list_for_each_entry_safe(desc, _d, &list, desc_node) | ||
638 | pdc_chain_complete(pd_chan, desc); | ||
639 | |||
640 | spin_unlock_bh(&pd_chan->lock); | ||
641 | |||
642 | |||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | static void pdc_tasklet(unsigned long data) | ||
647 | { | ||
648 | struct pch_dma_chan *pd_chan = (struct pch_dma_chan *)data; | ||
649 | |||
650 | if (!pdc_is_idle(pd_chan)) { | ||
651 | dev_err(chan2dev(&pd_chan->chan), | ||
652 | "BUG: handle non-idle channel in tasklet\n"); | ||
653 | return; | ||
654 | } | ||
655 | |||
656 | spin_lock_bh(&pd_chan->lock); | ||
657 | if (test_and_clear_bit(0, &pd_chan->err_status)) | ||
658 | pdc_handle_error(pd_chan); | ||
659 | else | ||
660 | pdc_advance_work(pd_chan); | ||
661 | spin_unlock_bh(&pd_chan->lock); | ||
662 | } | ||
663 | |||
664 | static irqreturn_t pd_irq(int irq, void *devid) | ||
665 | { | ||
666 | struct pch_dma *pd = (struct pch_dma *)devid; | ||
667 | struct pch_dma_chan *pd_chan; | ||
668 | u32 sts0; | ||
669 | int i; | ||
670 | int ret = IRQ_NONE; | ||
671 | |||
672 | sts0 = dma_readl(pd, STS0); | ||
673 | |||
674 | dev_dbg(pd->dma.dev, "pd_irq sts0: %x\n", sts0); | ||
675 | |||
676 | for (i = 0; i < pd->dma.chancnt; i++) { | ||
677 | pd_chan = &pd->channels[i]; | ||
678 | |||
679 | if (sts0 & DMA_STATUS_IRQ(i)) { | ||
680 | if (sts0 & DMA_STATUS_ERR(i)) | ||
681 | set_bit(0, &pd_chan->err_status); | ||
682 | |||
683 | tasklet_schedule(&pd_chan->tasklet); | ||
684 | ret = IRQ_HANDLED; | ||
685 | } | ||
686 | |||
687 | } | ||
688 | |||
689 | /* clear interrupt bits in status register */ | ||
690 | dma_writel(pd, STS0, sts0); | ||
691 | |||
692 | return ret; | ||
693 | } | ||
694 | |||
695 | static void pch_dma_save_regs(struct pch_dma *pd) | ||
696 | { | ||
697 | struct pch_dma_chan *pd_chan; | ||
698 | struct dma_chan *chan, *_c; | ||
699 | int i = 0; | ||
700 | |||
701 | pd->regs.dma_ctl0 = dma_readl(pd, CTL0); | ||
702 | pd->regs.dma_ctl1 = dma_readl(pd, CTL1); | ||
703 | pd->regs.dma_ctl2 = dma_readl(pd, CTL2); | ||
704 | |||
705 | list_for_each_entry_safe(chan, _c, &pd->dma.channels, device_node) { | ||
706 | pd_chan = to_pd_chan(chan); | ||
707 | |||
708 | pd->ch_regs[i].dev_addr = channel_readl(pd_chan, DEV_ADDR); | ||
709 | pd->ch_regs[i].mem_addr = channel_readl(pd_chan, MEM_ADDR); | ||
710 | pd->ch_regs[i].size = channel_readl(pd_chan, SIZE); | ||
711 | pd->ch_regs[i].next = channel_readl(pd_chan, NEXT); | ||
712 | |||
713 | i++; | ||
714 | } | ||
715 | } | ||
716 | |||
717 | static void pch_dma_restore_regs(struct pch_dma *pd) | ||
718 | { | ||
719 | struct pch_dma_chan *pd_chan; | ||
720 | struct dma_chan *chan, *_c; | ||
721 | int i = 0; | ||
722 | |||
723 | dma_writel(pd, CTL0, pd->regs.dma_ctl0); | ||
724 | dma_writel(pd, CTL1, pd->regs.dma_ctl1); | ||
725 | dma_writel(pd, CTL2, pd->regs.dma_ctl2); | ||
726 | |||
727 | list_for_each_entry_safe(chan, _c, &pd->dma.channels, device_node) { | ||
728 | pd_chan = to_pd_chan(chan); | ||
729 | |||
730 | channel_writel(pd_chan, DEV_ADDR, pd->ch_regs[i].dev_addr); | ||
731 | channel_writel(pd_chan, MEM_ADDR, pd->ch_regs[i].mem_addr); | ||
732 | channel_writel(pd_chan, SIZE, pd->ch_regs[i].size); | ||
733 | channel_writel(pd_chan, NEXT, pd->ch_regs[i].next); | ||
734 | |||
735 | i++; | ||
736 | } | ||
737 | } | ||
738 | |||
739 | static int pch_dma_suspend(struct pci_dev *pdev, pm_message_t state) | ||
740 | { | ||
741 | struct pch_dma *pd = pci_get_drvdata(pdev); | ||
742 | |||
743 | if (pd) | ||
744 | pch_dma_save_regs(pd); | ||
745 | |||
746 | pci_save_state(pdev); | ||
747 | pci_disable_device(pdev); | ||
748 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
749 | |||
750 | return 0; | ||
751 | } | ||
752 | |||
753 | static int pch_dma_resume(struct pci_dev *pdev) | ||
754 | { | ||
755 | struct pch_dma *pd = pci_get_drvdata(pdev); | ||
756 | int err; | ||
757 | |||
758 | pci_set_power_state(pdev, PCI_D0); | ||
759 | pci_restore_state(pdev); | ||
760 | |||
761 | err = pci_enable_device(pdev); | ||
762 | if (err) { | ||
763 | dev_dbg(&pdev->dev, "failed to enable device\n"); | ||
764 | return err; | ||
765 | } | ||
766 | |||
767 | if (pd) | ||
768 | pch_dma_restore_regs(pd); | ||
769 | |||
770 | return 0; | ||
771 | } | ||
772 | |||
773 | static int __devinit pch_dma_probe(struct pci_dev *pdev, | ||
774 | const struct pci_device_id *id) | ||
775 | { | ||
776 | struct pch_dma *pd; | ||
777 | struct pch_dma_regs *regs; | ||
778 | unsigned int nr_channels; | ||
779 | int err; | ||
780 | int i; | ||
781 | |||
782 | nr_channels = id->driver_data; | ||
783 | pd = kzalloc(sizeof(struct pch_dma)+ | ||
784 | sizeof(struct pch_dma_chan) * nr_channels, GFP_KERNEL); | ||
785 | if (!pd) | ||
786 | return -ENOMEM; | ||
787 | |||
788 | pci_set_drvdata(pdev, pd); | ||
789 | |||
790 | err = pci_enable_device(pdev); | ||
791 | if (err) { | ||
792 | dev_err(&pdev->dev, "Cannot enable PCI device\n"); | ||
793 | goto err_free_mem; | ||
794 | } | ||
795 | |||
796 | if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { | ||
797 | dev_err(&pdev->dev, "Cannot find proper base address\n"); | ||
798 | goto err_disable_pdev; | ||
799 | } | ||
800 | |||
801 | err = pci_request_regions(pdev, DRV_NAME); | ||
802 | if (err) { | ||
803 | dev_err(&pdev->dev, "Cannot obtain PCI resources\n"); | ||
804 | goto err_disable_pdev; | ||
805 | } | ||
806 | |||
807 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
808 | if (err) { | ||
809 | dev_err(&pdev->dev, "Cannot set proper DMA config\n"); | ||
810 | goto err_free_res; | ||
811 | } | ||
812 | |||
813 | regs = pd->membase = pci_iomap(pdev, 1, 0); | ||
814 | if (!pd->membase) { | ||
815 | dev_err(&pdev->dev, "Cannot map MMIO registers\n"); | ||
816 | err = -ENOMEM; | ||
817 | goto err_free_res; | ||
818 | } | ||
819 | |||
820 | pci_set_master(pdev); | ||
821 | |||
822 | err = request_irq(pdev->irq, pd_irq, IRQF_SHARED, DRV_NAME, pd); | ||
823 | if (err) { | ||
824 | dev_err(&pdev->dev, "Failed to request IRQ\n"); | ||
825 | goto err_iounmap; | ||
826 | } | ||
827 | |||
828 | pd->pool = pci_pool_create("pch_dma_desc_pool", pdev, | ||
829 | sizeof(struct pch_dma_desc), 4, 0); | ||
830 | if (!pd->pool) { | ||
831 | dev_err(&pdev->dev, "Failed to alloc DMA descriptors\n"); | ||
832 | err = -ENOMEM; | ||
833 | goto err_free_irq; | ||
834 | } | ||
835 | |||
836 | pd->dma.dev = &pdev->dev; | ||
837 | pd->dma.chancnt = nr_channels; | ||
838 | |||
839 | INIT_LIST_HEAD(&pd->dma.channels); | ||
840 | |||
841 | for (i = 0; i < nr_channels; i++) { | ||
842 | struct pch_dma_chan *pd_chan = &pd->channels[i]; | ||
843 | |||
844 | pd_chan->chan.device = &pd->dma; | ||
845 | pd_chan->chan.cookie = 1; | ||
846 | pd_chan->chan.chan_id = i; | ||
847 | |||
848 | pd_chan->membase = ®s->desc[i]; | ||
849 | |||
850 | pd_chan->dir = (i % 2) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
851 | |||
852 | spin_lock_init(&pd_chan->lock); | ||
853 | |||
854 | INIT_LIST_HEAD(&pd_chan->active_list); | ||
855 | INIT_LIST_HEAD(&pd_chan->queue); | ||
856 | INIT_LIST_HEAD(&pd_chan->free_list); | ||
857 | |||
858 | tasklet_init(&pd_chan->tasklet, pdc_tasklet, | ||
859 | (unsigned long)pd_chan); | ||
860 | list_add_tail(&pd_chan->chan.device_node, &pd->dma.channels); | ||
861 | } | ||
862 | |||
863 | dma_cap_zero(pd->dma.cap_mask); | ||
864 | dma_cap_set(DMA_PRIVATE, pd->dma.cap_mask); | ||
865 | dma_cap_set(DMA_SLAVE, pd->dma.cap_mask); | ||
866 | |||
867 | pd->dma.device_alloc_chan_resources = pd_alloc_chan_resources; | ||
868 | pd->dma.device_free_chan_resources = pd_free_chan_resources; | ||
869 | pd->dma.device_tx_status = pd_tx_status; | ||
870 | pd->dma.device_issue_pending = pd_issue_pending; | ||
871 | pd->dma.device_prep_slave_sg = pd_prep_slave_sg; | ||
872 | pd->dma.device_control = pd_device_control; | ||
873 | |||
874 | err = dma_async_device_register(&pd->dma); | ||
875 | if (err) { | ||
876 | dev_err(&pdev->dev, "Failed to register DMA device\n"); | ||
877 | goto err_free_pool; | ||
878 | } | ||
879 | |||
880 | return 0; | ||
881 | |||
882 | err_free_pool: | ||
883 | pci_pool_destroy(pd->pool); | ||
884 | err_free_irq: | ||
885 | free_irq(pdev->irq, pd); | ||
886 | err_iounmap: | ||
887 | pci_iounmap(pdev, pd->membase); | ||
888 | err_free_res: | ||
889 | pci_release_regions(pdev); | ||
890 | err_disable_pdev: | ||
891 | pci_disable_device(pdev); | ||
892 | err_free_mem: | ||
893 | return err; | ||
894 | } | ||
895 | |||
896 | static void __devexit pch_dma_remove(struct pci_dev *pdev) | ||
897 | { | ||
898 | struct pch_dma *pd = pci_get_drvdata(pdev); | ||
899 | struct pch_dma_chan *pd_chan; | ||
900 | struct dma_chan *chan, *_c; | ||
901 | |||
902 | if (pd) { | ||
903 | dma_async_device_unregister(&pd->dma); | ||
904 | |||
905 | list_for_each_entry_safe(chan, _c, &pd->dma.channels, | ||
906 | device_node) { | ||
907 | pd_chan = to_pd_chan(chan); | ||
908 | |||
909 | tasklet_disable(&pd_chan->tasklet); | ||
910 | tasklet_kill(&pd_chan->tasklet); | ||
911 | } | ||
912 | |||
913 | pci_pool_destroy(pd->pool); | ||
914 | free_irq(pdev->irq, pd); | ||
915 | pci_iounmap(pdev, pd->membase); | ||
916 | pci_release_regions(pdev); | ||
917 | pci_disable_device(pdev); | ||
918 | kfree(pd); | ||
919 | } | ||
920 | } | ||
921 | |||
922 | /* PCI Device ID of DMA device */ | ||
923 | #define PCI_DEVICE_ID_PCH_DMA_8CH 0x8810 | ||
924 | #define PCI_DEVICE_ID_PCH_DMA_4CH 0x8815 | ||
925 | |||
926 | static const struct pci_device_id pch_dma_id_table[] = { | ||
927 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_DMA_8CH), 8 }, | ||
928 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_DMA_4CH), 4 }, | ||
929 | }; | ||
930 | |||
931 | static struct pci_driver pch_dma_driver = { | ||
932 | .name = DRV_NAME, | ||
933 | .id_table = pch_dma_id_table, | ||
934 | .probe = pch_dma_probe, | ||
935 | .remove = __devexit_p(pch_dma_remove), | ||
936 | #ifdef CONFIG_PM | ||
937 | .suspend = pch_dma_suspend, | ||
938 | .resume = pch_dma_resume, | ||
939 | #endif | ||
940 | }; | ||
941 | |||
942 | static int __init pch_dma_init(void) | ||
943 | { | ||
944 | return pci_register_driver(&pch_dma_driver); | ||
945 | } | ||
946 | |||
947 | static void __exit pch_dma_exit(void) | ||
948 | { | ||
949 | pci_unregister_driver(&pch_dma_driver); | ||
950 | } | ||
951 | |||
952 | module_init(pch_dma_init); | ||
953 | module_exit(pch_dma_exit); | ||
954 | |||
955 | MODULE_DESCRIPTION("Topcliff PCH DMA controller driver"); | ||
956 | MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>"); | ||
957 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index c426829f6ab8..17e2600a00cf 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c | |||
@@ -30,14 +30,16 @@ | |||
30 | /* Maximum iterations taken before giving up suspending a channel */ | 30 | /* Maximum iterations taken before giving up suspending a channel */ |
31 | #define D40_SUSPEND_MAX_IT 500 | 31 | #define D40_SUSPEND_MAX_IT 500 |
32 | 32 | ||
33 | /* Hardware requirement on LCLA alignment */ | ||
34 | #define LCLA_ALIGNMENT 0x40000 | ||
35 | /* Attempts before giving up to trying to get pages that are aligned */ | ||
36 | #define MAX_LCLA_ALLOC_ATTEMPTS 256 | ||
37 | |||
38 | /* Bit markings for allocation map */ | ||
33 | #define D40_ALLOC_FREE (1 << 31) | 39 | #define D40_ALLOC_FREE (1 << 31) |
34 | #define D40_ALLOC_PHY (1 << 30) | 40 | #define D40_ALLOC_PHY (1 << 30) |
35 | #define D40_ALLOC_LOG_FREE 0 | 41 | #define D40_ALLOC_LOG_FREE 0 |
36 | 42 | ||
37 | /* The number of free d40_desc to keep in memory before starting | ||
38 | * to kfree() them */ | ||
39 | #define D40_DESC_CACHE_SIZE 50 | ||
40 | |||
41 | /* Hardware designer of the block */ | 43 | /* Hardware designer of the block */ |
42 | #define D40_PERIPHID2_DESIGNER 0x8 | 44 | #define D40_PERIPHID2_DESIGNER 0x8 |
43 | 45 | ||
@@ -68,9 +70,9 @@ enum d40_command { | |||
68 | */ | 70 | */ |
69 | struct d40_lli_pool { | 71 | struct d40_lli_pool { |
70 | void *base; | 72 | void *base; |
71 | int size; | 73 | int size; |
72 | /* Space for dst and src, plus an extra for padding */ | 74 | /* Space for dst and src, plus an extra for padding */ |
73 | u8 pre_alloc_lli[3 * sizeof(struct d40_phy_lli)]; | 75 | u8 pre_alloc_lli[3 * sizeof(struct d40_phy_lli)]; |
74 | }; | 76 | }; |
75 | 77 | ||
76 | /** | 78 | /** |
@@ -81,9 +83,10 @@ struct d40_lli_pool { | |||
81 | * lli_len equals one. | 83 | * lli_len equals one. |
82 | * @lli_log: Same as above but for logical channels. | 84 | * @lli_log: Same as above but for logical channels. |
83 | * @lli_pool: The pool with two entries pre-allocated. | 85 | * @lli_pool: The pool with two entries pre-allocated. |
84 | * @lli_len: Number of LLI's in lli_pool | 86 | * @lli_len: Number of llis of current descriptor. |
85 | * @lli_tcount: Number of LLIs processed in the transfer. When equals lli_len | 87 | * @lli_count: Number of transfered llis. |
86 | * then this transfer job is done. | 88 | * @lli_tx_len: Max number of LLIs per transfer, there can be |
89 | * many transfer for one descriptor. | ||
87 | * @txd: DMA engine struct. Used for among other things for communication | 90 | * @txd: DMA engine struct. Used for among other things for communication |
88 | * during a transfer. | 91 | * during a transfer. |
89 | * @node: List entry. | 92 | * @node: List entry. |
@@ -100,8 +103,9 @@ struct d40_desc { | |||
100 | struct d40_log_lli_bidir lli_log; | 103 | struct d40_log_lli_bidir lli_log; |
101 | 104 | ||
102 | struct d40_lli_pool lli_pool; | 105 | struct d40_lli_pool lli_pool; |
103 | u32 lli_len; | 106 | int lli_len; |
104 | u32 lli_tcount; | 107 | int lli_count; |
108 | u32 lli_tx_len; | ||
105 | 109 | ||
106 | struct dma_async_tx_descriptor txd; | 110 | struct dma_async_tx_descriptor txd; |
107 | struct list_head node; | 111 | struct list_head node; |
@@ -113,18 +117,20 @@ struct d40_desc { | |||
113 | /** | 117 | /** |
114 | * struct d40_lcla_pool - LCLA pool settings and data. | 118 | * struct d40_lcla_pool - LCLA pool settings and data. |
115 | * | 119 | * |
116 | * @base: The virtual address of LCLA. | 120 | * @base: The virtual address of LCLA. 18 bit aligned. |
117 | * @phy: Physical base address of LCLA. | 121 | * @base_unaligned: The orignal kmalloc pointer, if kmalloc is used. |
118 | * @base_size: size of lcla. | 122 | * This pointer is only there for clean-up on error. |
123 | * @pages: The number of pages needed for all physical channels. | ||
124 | * Only used later for clean-up on error | ||
119 | * @lock: Lock to protect the content in this struct. | 125 | * @lock: Lock to protect the content in this struct. |
120 | * @alloc_map: Mapping between physical channel and LCLA entries. | 126 | * @alloc_map: Bitmap mapping between physical channel and LCLA entries. |
121 | * @num_blocks: The number of entries of alloc_map. Equals to the | 127 | * @num_blocks: The number of entries of alloc_map. Equals to the |
122 | * number of physical channels. | 128 | * number of physical channels. |
123 | */ | 129 | */ |
124 | struct d40_lcla_pool { | 130 | struct d40_lcla_pool { |
125 | void *base; | 131 | void *base; |
126 | dma_addr_t phy; | 132 | void *base_unaligned; |
127 | resource_size_t base_size; | 133 | int pages; |
128 | spinlock_t lock; | 134 | spinlock_t lock; |
129 | u32 *alloc_map; | 135 | u32 *alloc_map; |
130 | int num_blocks; | 136 | int num_blocks; |
@@ -163,15 +169,14 @@ struct d40_base; | |||
163 | * @pending_tx: The number of pending transfers. Used between interrupt handler | 169 | * @pending_tx: The number of pending transfers. Used between interrupt handler |
164 | * and tasklet. | 170 | * and tasklet. |
165 | * @busy: Set to true when transfer is ongoing on this channel. | 171 | * @busy: Set to true when transfer is ongoing on this channel. |
166 | * @phy_chan: Pointer to physical channel which this instance runs on. | 172 | * @phy_chan: Pointer to physical channel which this instance runs on. If this |
173 | * point is NULL, then the channel is not allocated. | ||
167 | * @chan: DMA engine handle. | 174 | * @chan: DMA engine handle. |
168 | * @tasklet: Tasklet that gets scheduled from interrupt context to complete a | 175 | * @tasklet: Tasklet that gets scheduled from interrupt context to complete a |
169 | * transfer and call client callback. | 176 | * transfer and call client callback. |
170 | * @client: Cliented owned descriptor list. | 177 | * @client: Cliented owned descriptor list. |
171 | * @active: Active descriptor. | 178 | * @active: Active descriptor. |
172 | * @queue: Queued jobs. | 179 | * @queue: Queued jobs. |
173 | * @free: List of free descripts, ready to be reused. | ||
174 | * @free_len: Number of descriptors in the free list. | ||
175 | * @dma_cfg: The client configuration of this dma channel. | 180 | * @dma_cfg: The client configuration of this dma channel. |
176 | * @base: Pointer to the device instance struct. | 181 | * @base: Pointer to the device instance struct. |
177 | * @src_def_cfg: Default cfg register setting for src. | 182 | * @src_def_cfg: Default cfg register setting for src. |
@@ -195,8 +200,6 @@ struct d40_chan { | |||
195 | struct list_head client; | 200 | struct list_head client; |
196 | struct list_head active; | 201 | struct list_head active; |
197 | struct list_head queue; | 202 | struct list_head queue; |
198 | struct list_head free; | ||
199 | int free_len; | ||
200 | struct stedma40_chan_cfg dma_cfg; | 203 | struct stedma40_chan_cfg dma_cfg; |
201 | struct d40_base *base; | 204 | struct d40_base *base; |
202 | /* Default register configurations */ | 205 | /* Default register configurations */ |
@@ -205,6 +208,9 @@ struct d40_chan { | |||
205 | struct d40_def_lcsp log_def; | 208 | struct d40_def_lcsp log_def; |
206 | struct d40_lcla_elem lcla; | 209 | struct d40_lcla_elem lcla; |
207 | struct d40_log_lli_full *lcpa; | 210 | struct d40_log_lli_full *lcpa; |
211 | /* Runtime reconfiguration */ | ||
212 | dma_addr_t runtime_addr; | ||
213 | enum dma_data_direction runtime_direction; | ||
208 | }; | 214 | }; |
209 | 215 | ||
210 | /** | 216 | /** |
@@ -215,6 +221,7 @@ struct d40_chan { | |||
215 | * the same physical register. | 221 | * the same physical register. |
216 | * @dev: The device structure. | 222 | * @dev: The device structure. |
217 | * @virtbase: The virtual base address of the DMA's register. | 223 | * @virtbase: The virtual base address of the DMA's register. |
224 | * @rev: silicon revision detected. | ||
218 | * @clk: Pointer to the DMA clock structure. | 225 | * @clk: Pointer to the DMA clock structure. |
219 | * @phy_start: Physical memory start of the DMA registers. | 226 | * @phy_start: Physical memory start of the DMA registers. |
220 | * @phy_size: Size of the DMA register map. | 227 | * @phy_size: Size of the DMA register map. |
@@ -240,12 +247,14 @@ struct d40_chan { | |||
240 | * @lcpa_base: The virtual mapped address of LCPA. | 247 | * @lcpa_base: The virtual mapped address of LCPA. |
241 | * @phy_lcpa: The physical address of the LCPA. | 248 | * @phy_lcpa: The physical address of the LCPA. |
242 | * @lcpa_size: The size of the LCPA area. | 249 | * @lcpa_size: The size of the LCPA area. |
250 | * @desc_slab: cache for descriptors. | ||
243 | */ | 251 | */ |
244 | struct d40_base { | 252 | struct d40_base { |
245 | spinlock_t interrupt_lock; | 253 | spinlock_t interrupt_lock; |
246 | spinlock_t execmd_lock; | 254 | spinlock_t execmd_lock; |
247 | struct device *dev; | 255 | struct device *dev; |
248 | void __iomem *virtbase; | 256 | void __iomem *virtbase; |
257 | u8 rev:4; | ||
249 | struct clk *clk; | 258 | struct clk *clk; |
250 | phys_addr_t phy_start; | 259 | phys_addr_t phy_start; |
251 | resource_size_t phy_size; | 260 | resource_size_t phy_size; |
@@ -266,6 +275,7 @@ struct d40_base { | |||
266 | void *lcpa_base; | 275 | void *lcpa_base; |
267 | dma_addr_t phy_lcpa; | 276 | dma_addr_t phy_lcpa; |
268 | resource_size_t lcpa_size; | 277 | resource_size_t lcpa_size; |
278 | struct kmem_cache *desc_slab; | ||
269 | }; | 279 | }; |
270 | 280 | ||
271 | /** | 281 | /** |
@@ -365,11 +375,6 @@ static dma_cookie_t d40_assign_cookie(struct d40_chan *d40c, | |||
365 | return cookie; | 375 | return cookie; |
366 | } | 376 | } |
367 | 377 | ||
368 | static void d40_desc_reset(struct d40_desc *d40d) | ||
369 | { | ||
370 | d40d->lli_tcount = 0; | ||
371 | } | ||
372 | |||
373 | static void d40_desc_remove(struct d40_desc *d40d) | 378 | static void d40_desc_remove(struct d40_desc *d40d) |
374 | { | 379 | { |
375 | list_del(&d40d->node); | 380 | list_del(&d40d->node); |
@@ -377,7 +382,6 @@ static void d40_desc_remove(struct d40_desc *d40d) | |||
377 | 382 | ||
378 | static struct d40_desc *d40_desc_get(struct d40_chan *d40c) | 383 | static struct d40_desc *d40_desc_get(struct d40_chan *d40c) |
379 | { | 384 | { |
380 | struct d40_desc *desc; | ||
381 | struct d40_desc *d; | 385 | struct d40_desc *d; |
382 | struct d40_desc *_d; | 386 | struct d40_desc *_d; |
383 | 387 | ||
@@ -386,36 +390,21 @@ static struct d40_desc *d40_desc_get(struct d40_chan *d40c) | |||
386 | if (async_tx_test_ack(&d->txd)) { | 390 | if (async_tx_test_ack(&d->txd)) { |
387 | d40_pool_lli_free(d); | 391 | d40_pool_lli_free(d); |
388 | d40_desc_remove(d); | 392 | d40_desc_remove(d); |
389 | desc = d; | 393 | break; |
390 | goto out; | ||
391 | } | 394 | } |
392 | } | ||
393 | |||
394 | if (list_empty(&d40c->free)) { | ||
395 | /* Alloc new desc because we're out of used ones */ | ||
396 | desc = kzalloc(sizeof(struct d40_desc), GFP_NOWAIT); | ||
397 | if (desc == NULL) | ||
398 | goto out; | ||
399 | INIT_LIST_HEAD(&desc->node); | ||
400 | } else { | 395 | } else { |
401 | /* Reuse an old desc. */ | 396 | d = kmem_cache_alloc(d40c->base->desc_slab, GFP_NOWAIT); |
402 | desc = list_first_entry(&d40c->free, | 397 | if (d != NULL) { |
403 | struct d40_desc, | 398 | memset(d, 0, sizeof(struct d40_desc)); |
404 | node); | 399 | INIT_LIST_HEAD(&d->node); |
405 | list_del(&desc->node); | 400 | } |
406 | d40c->free_len--; | ||
407 | } | 401 | } |
408 | out: | 402 | return d; |
409 | return desc; | ||
410 | } | 403 | } |
411 | 404 | ||
412 | static void d40_desc_free(struct d40_chan *d40c, struct d40_desc *d40d) | 405 | static void d40_desc_free(struct d40_chan *d40c, struct d40_desc *d40d) |
413 | { | 406 | { |
414 | if (d40c->free_len < D40_DESC_CACHE_SIZE) { | 407 | kmem_cache_free(d40c->base->desc_slab, d40d); |
415 | list_add_tail(&d40d->node, &d40c->free); | ||
416 | d40c->free_len++; | ||
417 | } else | ||
418 | kfree(d40d); | ||
419 | } | 408 | } |
420 | 409 | ||
421 | static void d40_desc_submit(struct d40_chan *d40c, struct d40_desc *desc) | 410 | static void d40_desc_submit(struct d40_chan *d40c, struct d40_desc *desc) |
@@ -456,37 +445,41 @@ static struct d40_desc *d40_first_queued(struct d40_chan *d40c) | |||
456 | 445 | ||
457 | /* Support functions for logical channels */ | 446 | /* Support functions for logical channels */ |
458 | 447 | ||
459 | static int d40_lcla_id_get(struct d40_chan *d40c, | 448 | static int d40_lcla_id_get(struct d40_chan *d40c) |
460 | struct d40_lcla_pool *pool) | ||
461 | { | 449 | { |
462 | int src_id = 0; | 450 | int src_id = 0; |
463 | int dst_id = 0; | 451 | int dst_id = 0; |
464 | struct d40_log_lli *lcla_lidx_base = | 452 | struct d40_log_lli *lcla_lidx_base = |
465 | pool->base + d40c->phy_chan->num * 1024; | 453 | d40c->base->lcla_pool.base + d40c->phy_chan->num * 1024; |
466 | int i; | 454 | int i; |
467 | int lli_per_log = d40c->base->plat_data->llis_per_log; | 455 | int lli_per_log = d40c->base->plat_data->llis_per_log; |
456 | unsigned long flags; | ||
468 | 457 | ||
469 | if (d40c->lcla.src_id >= 0 && d40c->lcla.dst_id >= 0) | 458 | if (d40c->lcla.src_id >= 0 && d40c->lcla.dst_id >= 0) |
470 | return 0; | 459 | return 0; |
471 | 460 | ||
472 | if (pool->num_blocks > 32) | 461 | if (d40c->base->lcla_pool.num_blocks > 32) |
473 | return -EINVAL; | 462 | return -EINVAL; |
474 | 463 | ||
475 | spin_lock(&pool->lock); | 464 | spin_lock_irqsave(&d40c->base->lcla_pool.lock, flags); |
476 | 465 | ||
477 | for (i = 0; i < pool->num_blocks; i++) { | 466 | for (i = 0; i < d40c->base->lcla_pool.num_blocks; i++) { |
478 | if (!(pool->alloc_map[d40c->phy_chan->num] & (0x1 << i))) { | 467 | if (!(d40c->base->lcla_pool.alloc_map[d40c->phy_chan->num] & |
479 | pool->alloc_map[d40c->phy_chan->num] |= (0x1 << i); | 468 | (0x1 << i))) { |
469 | d40c->base->lcla_pool.alloc_map[d40c->phy_chan->num] |= | ||
470 | (0x1 << i); | ||
480 | break; | 471 | break; |
481 | } | 472 | } |
482 | } | 473 | } |
483 | src_id = i; | 474 | src_id = i; |
484 | if (src_id >= pool->num_blocks) | 475 | if (src_id >= d40c->base->lcla_pool.num_blocks) |
485 | goto err; | 476 | goto err; |
486 | 477 | ||
487 | for (; i < pool->num_blocks; i++) { | 478 | for (; i < d40c->base->lcla_pool.num_blocks; i++) { |
488 | if (!(pool->alloc_map[d40c->phy_chan->num] & (0x1 << i))) { | 479 | if (!(d40c->base->lcla_pool.alloc_map[d40c->phy_chan->num] & |
489 | pool->alloc_map[d40c->phy_chan->num] |= (0x1 << i); | 480 | (0x1 << i))) { |
481 | d40c->base->lcla_pool.alloc_map[d40c->phy_chan->num] |= | ||
482 | (0x1 << i); | ||
490 | break; | 483 | break; |
491 | } | 484 | } |
492 | } | 485 | } |
@@ -500,28 +493,13 @@ static int d40_lcla_id_get(struct d40_chan *d40c, | |||
500 | d40c->lcla.dst = lcla_lidx_base + dst_id * lli_per_log + 1; | 493 | d40c->lcla.dst = lcla_lidx_base + dst_id * lli_per_log + 1; |
501 | d40c->lcla.src = lcla_lidx_base + src_id * lli_per_log + 1; | 494 | d40c->lcla.src = lcla_lidx_base + src_id * lli_per_log + 1; |
502 | 495 | ||
503 | 496 | spin_unlock_irqrestore(&d40c->base->lcla_pool.lock, flags); | |
504 | spin_unlock(&pool->lock); | ||
505 | return 0; | 497 | return 0; |
506 | err: | 498 | err: |
507 | spin_unlock(&pool->lock); | 499 | spin_unlock_irqrestore(&d40c->base->lcla_pool.lock, flags); |
508 | return -EINVAL; | 500 | return -EINVAL; |
509 | } | 501 | } |
510 | 502 | ||
511 | static void d40_lcla_id_put(struct d40_chan *d40c, | ||
512 | struct d40_lcla_pool *pool, | ||
513 | int id) | ||
514 | { | ||
515 | if (id < 0) | ||
516 | return; | ||
517 | |||
518 | d40c->lcla.src_id = -1; | ||
519 | d40c->lcla.dst_id = -1; | ||
520 | |||
521 | spin_lock(&pool->lock); | ||
522 | pool->alloc_map[d40c->phy_chan->num] &= (~(0x1 << id)); | ||
523 | spin_unlock(&pool->lock); | ||
524 | } | ||
525 | 503 | ||
526 | static int d40_channel_execute_command(struct d40_chan *d40c, | 504 | static int d40_channel_execute_command(struct d40_chan *d40c, |
527 | enum d40_command command) | 505 | enum d40_command command) |
@@ -530,6 +508,7 @@ static int d40_channel_execute_command(struct d40_chan *d40c, | |||
530 | void __iomem *active_reg; | 508 | void __iomem *active_reg; |
531 | int ret = 0; | 509 | int ret = 0; |
532 | unsigned long flags; | 510 | unsigned long flags; |
511 | u32 wmask; | ||
533 | 512 | ||
534 | spin_lock_irqsave(&d40c->base->execmd_lock, flags); | 513 | spin_lock_irqsave(&d40c->base->execmd_lock, flags); |
535 | 514 | ||
@@ -547,7 +526,9 @@ static int d40_channel_execute_command(struct d40_chan *d40c, | |||
547 | goto done; | 526 | goto done; |
548 | } | 527 | } |
549 | 528 | ||
550 | writel(command << D40_CHAN_POS(d40c->phy_chan->num), active_reg); | 529 | wmask = 0xffffffff & ~(D40_CHAN_POS_MASK(d40c->phy_chan->num)); |
530 | writel(wmask | (command << D40_CHAN_POS(d40c->phy_chan->num)), | ||
531 | active_reg); | ||
551 | 532 | ||
552 | if (command == D40_DMA_SUSPEND_REQ) { | 533 | if (command == D40_DMA_SUSPEND_REQ) { |
553 | 534 | ||
@@ -586,8 +567,7 @@ done: | |||
586 | static void d40_term_all(struct d40_chan *d40c) | 567 | static void d40_term_all(struct d40_chan *d40c) |
587 | { | 568 | { |
588 | struct d40_desc *d40d; | 569 | struct d40_desc *d40d; |
589 | struct d40_desc *d; | 570 | unsigned long flags; |
590 | struct d40_desc *_d; | ||
591 | 571 | ||
592 | /* Release active descriptors */ | 572 | /* Release active descriptors */ |
593 | while ((d40d = d40_first_active_get(d40c))) { | 573 | while ((d40d = d40_first_active_get(d40c))) { |
@@ -605,19 +585,17 @@ static void d40_term_all(struct d40_chan *d40c) | |||
605 | d40_desc_free(d40c, d40d); | 585 | d40_desc_free(d40c, d40d); |
606 | } | 586 | } |
607 | 587 | ||
608 | /* Release client owned descriptors */ | 588 | spin_lock_irqsave(&d40c->base->lcla_pool.lock, flags); |
609 | if (!list_empty(&d40c->client)) | 589 | |
610 | list_for_each_entry_safe(d, _d, &d40c->client, node) { | 590 | d40c->base->lcla_pool.alloc_map[d40c->phy_chan->num] &= |
611 | d40_pool_lli_free(d); | 591 | (~(0x1 << d40c->lcla.dst_id)); |
612 | d40_desc_remove(d); | 592 | d40c->base->lcla_pool.alloc_map[d40c->phy_chan->num] &= |
613 | /* Return desc to free-list */ | 593 | (~(0x1 << d40c->lcla.src_id)); |
614 | d40_desc_free(d40c, d40d); | 594 | |
615 | } | 595 | d40c->lcla.src_id = -1; |
596 | d40c->lcla.dst_id = -1; | ||
616 | 597 | ||
617 | d40_lcla_id_put(d40c, &d40c->base->lcla_pool, | 598 | spin_unlock_irqrestore(&d40c->base->lcla_pool.lock, flags); |
618 | d40c->lcla.src_id); | ||
619 | d40_lcla_id_put(d40c, &d40c->base->lcla_pool, | ||
620 | d40c->lcla.dst_id); | ||
621 | 599 | ||
622 | d40c->pending_tx = 0; | 600 | d40c->pending_tx = 0; |
623 | d40c->busy = false; | 601 | d40c->busy = false; |
@@ -628,6 +606,7 @@ static void d40_config_set_event(struct d40_chan *d40c, bool do_enable) | |||
628 | u32 val; | 606 | u32 val; |
629 | unsigned long flags; | 607 | unsigned long flags; |
630 | 608 | ||
609 | /* Notice, that disable requires the physical channel to be stopped */ | ||
631 | if (do_enable) | 610 | if (do_enable) |
632 | val = D40_ACTIVATE_EVENTLINE; | 611 | val = D40_ACTIVATE_EVENTLINE; |
633 | else | 612 | else |
@@ -732,31 +711,34 @@ static int d40_config_write(struct d40_chan *d40c) | |||
732 | 711 | ||
733 | static void d40_desc_load(struct d40_chan *d40c, struct d40_desc *d40d) | 712 | static void d40_desc_load(struct d40_chan *d40c, struct d40_desc *d40d) |
734 | { | 713 | { |
735 | |||
736 | if (d40d->lli_phy.dst && d40d->lli_phy.src) { | 714 | if (d40d->lli_phy.dst && d40d->lli_phy.src) { |
737 | d40_phy_lli_write(d40c->base->virtbase, | 715 | d40_phy_lli_write(d40c->base->virtbase, |
738 | d40c->phy_chan->num, | 716 | d40c->phy_chan->num, |
739 | d40d->lli_phy.dst, | 717 | d40d->lli_phy.dst, |
740 | d40d->lli_phy.src); | 718 | d40d->lli_phy.src); |
741 | d40d->lli_tcount = d40d->lli_len; | ||
742 | } else if (d40d->lli_log.dst && d40d->lli_log.src) { | 719 | } else if (d40d->lli_log.dst && d40d->lli_log.src) { |
743 | u32 lli_len; | ||
744 | struct d40_log_lli *src = d40d->lli_log.src; | 720 | struct d40_log_lli *src = d40d->lli_log.src; |
745 | struct d40_log_lli *dst = d40d->lli_log.dst; | 721 | struct d40_log_lli *dst = d40d->lli_log.dst; |
746 | 722 | int s; | |
747 | src += d40d->lli_tcount; | 723 | |
748 | dst += d40d->lli_tcount; | 724 | src += d40d->lli_count; |
749 | 725 | dst += d40d->lli_count; | |
750 | if (d40d->lli_len <= d40c->base->plat_data->llis_per_log) | 726 | s = d40_log_lli_write(d40c->lcpa, |
751 | lli_len = d40d->lli_len; | 727 | d40c->lcla.src, d40c->lcla.dst, |
752 | else | 728 | dst, src, |
753 | lli_len = d40c->base->plat_data->llis_per_log; | 729 | d40c->base->plat_data->llis_per_log); |
754 | d40d->lli_tcount += lli_len; | 730 | |
755 | d40_log_lli_write(d40c->lcpa, d40c->lcla.src, | 731 | /* If s equals to zero, the job is not linked */ |
756 | d40c->lcla.dst, | 732 | if (s > 0) { |
757 | dst, src, | 733 | (void) dma_map_single(d40c->base->dev, d40c->lcla.src, |
758 | d40c->base->plat_data->llis_per_log); | 734 | s * sizeof(struct d40_log_lli), |
735 | DMA_TO_DEVICE); | ||
736 | (void) dma_map_single(d40c->base->dev, d40c->lcla.dst, | ||
737 | s * sizeof(struct d40_log_lli), | ||
738 | DMA_TO_DEVICE); | ||
739 | } | ||
759 | } | 740 | } |
741 | d40d->lli_count += d40d->lli_tx_len; | ||
760 | } | 742 | } |
761 | 743 | ||
762 | static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx) | 744 | static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx) |
@@ -780,18 +762,21 @@ static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx) | |||
780 | 762 | ||
781 | static int d40_start(struct d40_chan *d40c) | 763 | static int d40_start(struct d40_chan *d40c) |
782 | { | 764 | { |
783 | int err; | 765 | if (d40c->base->rev == 0) { |
766 | int err; | ||
784 | 767 | ||
785 | if (d40c->log_num != D40_PHY_CHAN) { | 768 | if (d40c->log_num != D40_PHY_CHAN) { |
786 | err = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); | 769 | err = d40_channel_execute_command(d40c, |
787 | if (err) | 770 | D40_DMA_SUSPEND_REQ); |
788 | return err; | 771 | if (err) |
789 | d40_config_set_event(d40c, true); | 772 | return err; |
773 | } | ||
790 | } | 774 | } |
791 | 775 | ||
792 | err = d40_channel_execute_command(d40c, D40_DMA_RUN); | 776 | if (d40c->log_num != D40_PHY_CHAN) |
777 | d40_config_set_event(d40c, true); | ||
793 | 778 | ||
794 | return err; | 779 | return d40_channel_execute_command(d40c, D40_DMA_RUN); |
795 | } | 780 | } |
796 | 781 | ||
797 | static struct d40_desc *d40_queue_start(struct d40_chan *d40c) | 782 | static struct d40_desc *d40_queue_start(struct d40_chan *d40c) |
@@ -838,7 +823,7 @@ static void dma_tc_handle(struct d40_chan *d40c) | |||
838 | if (d40d == NULL) | 823 | if (d40d == NULL) |
839 | return; | 824 | return; |
840 | 825 | ||
841 | if (d40d->lli_tcount < d40d->lli_len) { | 826 | if (d40d->lli_count < d40d->lli_len) { |
842 | 827 | ||
843 | d40_desc_load(d40c, d40d); | 828 | d40_desc_load(d40c, d40d); |
844 | /* Start dma job */ | 829 | /* Start dma job */ |
@@ -891,7 +876,6 @@ static void dma_tasklet(unsigned long data) | |||
891 | /* Return desc to free-list */ | 876 | /* Return desc to free-list */ |
892 | d40_desc_free(d40c, d40d_fin); | 877 | d40_desc_free(d40c, d40d_fin); |
893 | } else { | 878 | } else { |
894 | d40_desc_reset(d40d_fin); | ||
895 | if (!d40d_fin->is_in_client_list) { | 879 | if (!d40d_fin->is_in_client_list) { |
896 | d40_desc_remove(d40d_fin); | 880 | d40_desc_remove(d40d_fin); |
897 | list_add_tail(&d40d_fin->node, &d40c->client); | 881 | list_add_tail(&d40d_fin->node, &d40c->client); |
@@ -975,7 +959,8 @@ static irqreturn_t d40_handle_interrupt(int irq, void *data) | |||
975 | if (!il[row].is_error) | 959 | if (!il[row].is_error) |
976 | dma_tc_handle(d40c); | 960 | dma_tc_handle(d40c); |
977 | else | 961 | else |
978 | dev_err(base->dev, "[%s] IRQ chan: %ld offset %d idx %d\n", | 962 | dev_err(base->dev, |
963 | "[%s] IRQ chan: %ld offset %d idx %d\n", | ||
979 | __func__, chan, il[row].offset, idx); | 964 | __func__, chan, il[row].offset, idx); |
980 | 965 | ||
981 | spin_unlock(&d40c->lock); | 966 | spin_unlock(&d40c->lock); |
@@ -1134,7 +1119,8 @@ static int d40_allocate_channel(struct d40_chan *d40c) | |||
1134 | int j; | 1119 | int j; |
1135 | int log_num; | 1120 | int log_num; |
1136 | bool is_src; | 1121 | bool is_src; |
1137 | bool is_log = (d40c->dma_cfg.channel_type & STEDMA40_CHANNEL_IN_OPER_MODE) | 1122 | bool is_log = (d40c->dma_cfg.channel_type & |
1123 | STEDMA40_CHANNEL_IN_OPER_MODE) | ||
1138 | == STEDMA40_CHANNEL_IN_LOG_MODE; | 1124 | == STEDMA40_CHANNEL_IN_LOG_MODE; |
1139 | 1125 | ||
1140 | 1126 | ||
@@ -1169,8 +1155,10 @@ static int d40_allocate_channel(struct d40_chan *d40c) | |||
1169 | for (j = 0; j < d40c->base->num_phy_chans; j += 8) { | 1155 | for (j = 0; j < d40c->base->num_phy_chans; j += 8) { |
1170 | int phy_num = j + event_group * 2; | 1156 | int phy_num = j + event_group * 2; |
1171 | for (i = phy_num; i < phy_num + 2; i++) { | 1157 | for (i = phy_num; i < phy_num + 2; i++) { |
1172 | if (d40_alloc_mask_set(&phys[i], is_src, | 1158 | if (d40_alloc_mask_set(&phys[i], |
1173 | 0, is_log)) | 1159 | is_src, |
1160 | 0, | ||
1161 | is_log)) | ||
1174 | goto found_phy; | 1162 | goto found_phy; |
1175 | } | 1163 | } |
1176 | } | 1164 | } |
@@ -1221,30 +1209,6 @@ out: | |||
1221 | 1209 | ||
1222 | } | 1210 | } |
1223 | 1211 | ||
1224 | static int d40_config_chan(struct d40_chan *d40c, | ||
1225 | struct stedma40_chan_cfg *info) | ||
1226 | { | ||
1227 | |||
1228 | /* Fill in basic CFG register values */ | ||
1229 | d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg, | ||
1230 | &d40c->dst_def_cfg, d40c->log_num != D40_PHY_CHAN); | ||
1231 | |||
1232 | if (d40c->log_num != D40_PHY_CHAN) { | ||
1233 | d40_log_cfg(&d40c->dma_cfg, | ||
1234 | &d40c->log_def.lcsp1, &d40c->log_def.lcsp3); | ||
1235 | |||
1236 | if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) | ||
1237 | d40c->lcpa = d40c->base->lcpa_base + | ||
1238 | d40c->dma_cfg.src_dev_type * 32; | ||
1239 | else | ||
1240 | d40c->lcpa = d40c->base->lcpa_base + | ||
1241 | d40c->dma_cfg.dst_dev_type * 32 + 16; | ||
1242 | } | ||
1243 | |||
1244 | /* Write channel configuration to the DMA */ | ||
1245 | return d40_config_write(d40c); | ||
1246 | } | ||
1247 | |||
1248 | static int d40_config_memcpy(struct d40_chan *d40c) | 1212 | static int d40_config_memcpy(struct d40_chan *d40c) |
1249 | { | 1213 | { |
1250 | dma_cap_mask_t cap = d40c->chan.device->cap_mask; | 1214 | dma_cap_mask_t cap = d40c->chan.device->cap_mask; |
@@ -1272,13 +1236,25 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
1272 | { | 1236 | { |
1273 | 1237 | ||
1274 | int res = 0; | 1238 | int res = 0; |
1275 | u32 event, dir; | 1239 | u32 event; |
1276 | struct d40_phy_res *phy = d40c->phy_chan; | 1240 | struct d40_phy_res *phy = d40c->phy_chan; |
1277 | bool is_src; | 1241 | bool is_src; |
1242 | struct d40_desc *d; | ||
1243 | struct d40_desc *_d; | ||
1244 | |||
1278 | 1245 | ||
1279 | /* Terminate all queued and active transfers */ | 1246 | /* Terminate all queued and active transfers */ |
1280 | d40_term_all(d40c); | 1247 | d40_term_all(d40c); |
1281 | 1248 | ||
1249 | /* Release client owned descriptors */ | ||
1250 | if (!list_empty(&d40c->client)) | ||
1251 | list_for_each_entry_safe(d, _d, &d40c->client, node) { | ||
1252 | d40_pool_lli_free(d); | ||
1253 | d40_desc_remove(d); | ||
1254 | /* Return desc to free-list */ | ||
1255 | d40_desc_free(d40c, d); | ||
1256 | } | ||
1257 | |||
1282 | if (phy == NULL) { | 1258 | if (phy == NULL) { |
1283 | dev_err(&d40c->chan.dev->device, "[%s] phy == null\n", | 1259 | dev_err(&d40c->chan.dev->device, "[%s] phy == null\n", |
1284 | __func__); | 1260 | __func__); |
@@ -1292,22 +1268,12 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
1292 | return -EINVAL; | 1268 | return -EINVAL; |
1293 | } | 1269 | } |
1294 | 1270 | ||
1295 | |||
1296 | res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); | ||
1297 | if (res) { | ||
1298 | dev_err(&d40c->chan.dev->device, "[%s] suspend\n", | ||
1299 | __func__); | ||
1300 | return res; | ||
1301 | } | ||
1302 | |||
1303 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || | 1271 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || |
1304 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { | 1272 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { |
1305 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); | 1273 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); |
1306 | dir = D40_CHAN_REG_SDLNK; | ||
1307 | is_src = false; | 1274 | is_src = false; |
1308 | } else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { | 1275 | } else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { |
1309 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); | 1276 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); |
1310 | dir = D40_CHAN_REG_SSLNK; | ||
1311 | is_src = true; | 1277 | is_src = true; |
1312 | } else { | 1278 | } else { |
1313 | dev_err(&d40c->chan.dev->device, | 1279 | dev_err(&d40c->chan.dev->device, |
@@ -1315,16 +1281,17 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
1315 | return -EINVAL; | 1281 | return -EINVAL; |
1316 | } | 1282 | } |
1317 | 1283 | ||
1284 | res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); | ||
1285 | if (res) { | ||
1286 | dev_err(&d40c->chan.dev->device, "[%s] suspend failed\n", | ||
1287 | __func__); | ||
1288 | return res; | ||
1289 | } | ||
1290 | |||
1318 | if (d40c->log_num != D40_PHY_CHAN) { | 1291 | if (d40c->log_num != D40_PHY_CHAN) { |
1319 | /* | 1292 | /* Release logical channel, deactivate the event line */ |
1320 | * Release logical channel, deactivate the event line during | ||
1321 | * the time physical res is suspended. | ||
1322 | */ | ||
1323 | writel((D40_DEACTIVATE_EVENTLINE << D40_EVENTLINE_POS(event)) & | ||
1324 | D40_EVENTLINE_MASK(event), | ||
1325 | d40c->base->virtbase + D40_DREG_PCBASE + | ||
1326 | phy->num * D40_DREG_PCDELTA + dir); | ||
1327 | 1293 | ||
1294 | d40_config_set_event(d40c, false); | ||
1328 | d40c->base->lookup_log_chans[d40c->log_num] = NULL; | 1295 | d40c->base->lookup_log_chans[d40c->log_num] = NULL; |
1329 | 1296 | ||
1330 | /* | 1297 | /* |
@@ -1345,8 +1312,9 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
1345 | } | 1312 | } |
1346 | return 0; | 1313 | return 0; |
1347 | } | 1314 | } |
1348 | } else | 1315 | } else { |
1349 | d40_alloc_mask_free(phy, is_src, 0); | 1316 | (void) d40_alloc_mask_free(phy, is_src, 0); |
1317 | } | ||
1350 | 1318 | ||
1351 | /* Release physical channel */ | 1319 | /* Release physical channel */ |
1352 | res = d40_channel_execute_command(d40c, D40_DMA_STOP); | 1320 | res = d40_channel_execute_command(d40c, D40_DMA_STOP); |
@@ -1361,8 +1329,6 @@ static int d40_free_dma(struct d40_chan *d40c) | |||
1361 | d40c->base->lookup_phy_chans[phy->num] = NULL; | 1329 | d40c->base->lookup_phy_chans[phy->num] = NULL; |
1362 | 1330 | ||
1363 | return 0; | 1331 | return 0; |
1364 | |||
1365 | |||
1366 | } | 1332 | } |
1367 | 1333 | ||
1368 | static int d40_pause(struct dma_chan *chan) | 1334 | static int d40_pause(struct dma_chan *chan) |
@@ -1370,7 +1336,6 @@ static int d40_pause(struct dma_chan *chan) | |||
1370 | struct d40_chan *d40c = | 1336 | struct d40_chan *d40c = |
1371 | container_of(chan, struct d40_chan, chan); | 1337 | container_of(chan, struct d40_chan, chan); |
1372 | int res; | 1338 | int res; |
1373 | |||
1374 | unsigned long flags; | 1339 | unsigned long flags; |
1375 | 1340 | ||
1376 | spin_lock_irqsave(&d40c->lock, flags); | 1341 | spin_lock_irqsave(&d40c->lock, flags); |
@@ -1397,7 +1362,6 @@ static bool d40_is_paused(struct d40_chan *d40c) | |||
1397 | void __iomem *active_reg; | 1362 | void __iomem *active_reg; |
1398 | u32 status; | 1363 | u32 status; |
1399 | u32 event; | 1364 | u32 event; |
1400 | int res; | ||
1401 | 1365 | ||
1402 | spin_lock_irqsave(&d40c->lock, flags); | 1366 | spin_lock_irqsave(&d40c->lock, flags); |
1403 | 1367 | ||
@@ -1416,10 +1380,6 @@ static bool d40_is_paused(struct d40_chan *d40c) | |||
1416 | goto _exit; | 1380 | goto _exit; |
1417 | } | 1381 | } |
1418 | 1382 | ||
1419 | res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); | ||
1420 | if (res != 0) | ||
1421 | goto _exit; | ||
1422 | |||
1423 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || | 1383 | if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || |
1424 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) | 1384 | d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) |
1425 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); | 1385 | event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); |
@@ -1436,12 +1396,6 @@ static bool d40_is_paused(struct d40_chan *d40c) | |||
1436 | 1396 | ||
1437 | if (status != D40_DMA_RUN) | 1397 | if (status != D40_DMA_RUN) |
1438 | is_paused = true; | 1398 | is_paused = true; |
1439 | |||
1440 | /* Resume the other logical channels if any */ | ||
1441 | if (d40_chan_has_events(d40c)) | ||
1442 | res = d40_channel_execute_command(d40c, | ||
1443 | D40_DMA_RUN); | ||
1444 | |||
1445 | _exit: | 1399 | _exit: |
1446 | spin_unlock_irqrestore(&d40c->lock, flags); | 1400 | spin_unlock_irqrestore(&d40c->lock, flags); |
1447 | return is_paused; | 1401 | return is_paused; |
@@ -1468,13 +1422,14 @@ static u32 d40_residue(struct d40_chan *d40c) | |||
1468 | u32 num_elt; | 1422 | u32 num_elt; |
1469 | 1423 | ||
1470 | if (d40c->log_num != D40_PHY_CHAN) | 1424 | if (d40c->log_num != D40_PHY_CHAN) |
1471 | num_elt = (readl(&d40c->lcpa->lcsp2) & D40_MEM_LCSP2_ECNT_MASK) | 1425 | num_elt = (readl(&d40c->lcpa->lcsp2) & D40_MEM_LCSP2_ECNT_MASK) |
1472 | >> D40_MEM_LCSP2_ECNT_POS; | 1426 | >> D40_MEM_LCSP2_ECNT_POS; |
1473 | else | 1427 | else |
1474 | num_elt = (readl(d40c->base->virtbase + D40_DREG_PCBASE + | 1428 | num_elt = (readl(d40c->base->virtbase + D40_DREG_PCBASE + |
1475 | d40c->phy_chan->num * D40_DREG_PCDELTA + | 1429 | d40c->phy_chan->num * D40_DREG_PCDELTA + |
1476 | D40_CHAN_REG_SDELT) & | 1430 | D40_CHAN_REG_SDELT) & |
1477 | D40_SREG_ELEM_PHY_ECNT_MASK) >> D40_SREG_ELEM_PHY_ECNT_POS; | 1431 | D40_SREG_ELEM_PHY_ECNT_MASK) >> |
1432 | D40_SREG_ELEM_PHY_ECNT_POS; | ||
1478 | return num_elt * (1 << d40c->dma_cfg.dst_info.data_width); | 1433 | return num_elt * (1 << d40c->dma_cfg.dst_info.data_width); |
1479 | } | 1434 | } |
1480 | 1435 | ||
@@ -1487,20 +1442,21 @@ static int d40_resume(struct dma_chan *chan) | |||
1487 | 1442 | ||
1488 | spin_lock_irqsave(&d40c->lock, flags); | 1443 | spin_lock_irqsave(&d40c->lock, flags); |
1489 | 1444 | ||
1490 | if (d40c->log_num != D40_PHY_CHAN) { | 1445 | if (d40c->base->rev == 0) |
1491 | res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); | 1446 | if (d40c->log_num != D40_PHY_CHAN) { |
1492 | if (res) | 1447 | res = d40_channel_execute_command(d40c, |
1493 | goto out; | 1448 | D40_DMA_SUSPEND_REQ); |
1449 | goto no_suspend; | ||
1450 | } | ||
1494 | 1451 | ||
1495 | /* If bytes left to transfer or linked tx resume job */ | 1452 | /* If bytes left to transfer or linked tx resume job */ |
1496 | if (d40_residue(d40c) || d40_tx_is_linked(d40c)) { | 1453 | if (d40_residue(d40c) || d40_tx_is_linked(d40c)) { |
1454 | if (d40c->log_num != D40_PHY_CHAN) | ||
1497 | d40_config_set_event(d40c, true); | 1455 | d40_config_set_event(d40c, true); |
1498 | res = d40_channel_execute_command(d40c, D40_DMA_RUN); | ||
1499 | } | ||
1500 | } else if (d40_residue(d40c) || d40_tx_is_linked(d40c)) | ||
1501 | res = d40_channel_execute_command(d40c, D40_DMA_RUN); | 1456 | res = d40_channel_execute_command(d40c, D40_DMA_RUN); |
1457 | } | ||
1502 | 1458 | ||
1503 | out: | 1459 | no_suspend: |
1504 | spin_unlock_irqrestore(&d40c->lock, flags); | 1460 | spin_unlock_irqrestore(&d40c->lock, flags); |
1505 | return res; | 1461 | return res; |
1506 | } | 1462 | } |
@@ -1534,8 +1490,10 @@ int stedma40_set_psize(struct dma_chan *chan, | |||
1534 | if (d40c->log_num != D40_PHY_CHAN) { | 1490 | if (d40c->log_num != D40_PHY_CHAN) { |
1535 | d40c->log_def.lcsp1 &= ~D40_MEM_LCSP1_SCFG_PSIZE_MASK; | 1491 | d40c->log_def.lcsp1 &= ~D40_MEM_LCSP1_SCFG_PSIZE_MASK; |
1536 | d40c->log_def.lcsp3 &= ~D40_MEM_LCSP1_SCFG_PSIZE_MASK; | 1492 | d40c->log_def.lcsp3 &= ~D40_MEM_LCSP1_SCFG_PSIZE_MASK; |
1537 | d40c->log_def.lcsp1 |= src_psize << D40_MEM_LCSP1_SCFG_PSIZE_POS; | 1493 | d40c->log_def.lcsp1 |= src_psize << |
1538 | d40c->log_def.lcsp3 |= dst_psize << D40_MEM_LCSP1_SCFG_PSIZE_POS; | 1494 | D40_MEM_LCSP1_SCFG_PSIZE_POS; |
1495 | d40c->log_def.lcsp3 |= dst_psize << | ||
1496 | D40_MEM_LCSP1_SCFG_PSIZE_POS; | ||
1539 | goto out; | 1497 | goto out; |
1540 | } | 1498 | } |
1541 | 1499 | ||
@@ -1566,37 +1524,42 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, | |||
1566 | struct scatterlist *sgl_dst, | 1524 | struct scatterlist *sgl_dst, |
1567 | struct scatterlist *sgl_src, | 1525 | struct scatterlist *sgl_src, |
1568 | unsigned int sgl_len, | 1526 | unsigned int sgl_len, |
1569 | unsigned long flags) | 1527 | unsigned long dma_flags) |
1570 | { | 1528 | { |
1571 | int res; | 1529 | int res; |
1572 | struct d40_desc *d40d; | 1530 | struct d40_desc *d40d; |
1573 | struct d40_chan *d40c = container_of(chan, struct d40_chan, | 1531 | struct d40_chan *d40c = container_of(chan, struct d40_chan, |
1574 | chan); | 1532 | chan); |
1575 | unsigned long flg; | 1533 | unsigned long flags; |
1576 | int lli_max = d40c->base->plat_data->llis_per_log; | ||
1577 | 1534 | ||
1535 | if (d40c->phy_chan == NULL) { | ||
1536 | dev_err(&d40c->chan.dev->device, | ||
1537 | "[%s] Unallocated channel.\n", __func__); | ||
1538 | return ERR_PTR(-EINVAL); | ||
1539 | } | ||
1578 | 1540 | ||
1579 | spin_lock_irqsave(&d40c->lock, flg); | 1541 | spin_lock_irqsave(&d40c->lock, flags); |
1580 | d40d = d40_desc_get(d40c); | 1542 | d40d = d40_desc_get(d40c); |
1581 | 1543 | ||
1582 | if (d40d == NULL) | 1544 | if (d40d == NULL) |
1583 | goto err; | 1545 | goto err; |
1584 | 1546 | ||
1585 | memset(d40d, 0, sizeof(struct d40_desc)); | ||
1586 | d40d->lli_len = sgl_len; | 1547 | d40d->lli_len = sgl_len; |
1587 | 1548 | d40d->lli_tx_len = d40d->lli_len; | |
1588 | d40d->txd.flags = flags; | 1549 | d40d->txd.flags = dma_flags; |
1589 | 1550 | ||
1590 | if (d40c->log_num != D40_PHY_CHAN) { | 1551 | if (d40c->log_num != D40_PHY_CHAN) { |
1552 | if (d40d->lli_len > d40c->base->plat_data->llis_per_log) | ||
1553 | d40d->lli_tx_len = d40c->base->plat_data->llis_per_log; | ||
1554 | |||
1591 | if (sgl_len > 1) | 1555 | if (sgl_len > 1) |
1592 | /* | 1556 | /* |
1593 | * Check if there is space available in lcla. If not, | 1557 | * Check if there is space available in lcla. If not, |
1594 | * split list into 1-length and run only in lcpa | 1558 | * split list into 1-length and run only in lcpa |
1595 | * space. | 1559 | * space. |
1596 | */ | 1560 | */ |
1597 | if (d40_lcla_id_get(d40c, | 1561 | if (d40_lcla_id_get(d40c) != 0) |
1598 | &d40c->base->lcla_pool) != 0) | 1562 | d40d->lli_tx_len = 1; |
1599 | lli_max = 1; | ||
1600 | 1563 | ||
1601 | if (d40_pool_lli_alloc(d40d, sgl_len, true) < 0) { | 1564 | if (d40_pool_lli_alloc(d40d, sgl_len, true) < 0) { |
1602 | dev_err(&d40c->chan.dev->device, | 1565 | dev_err(&d40c->chan.dev->device, |
@@ -1610,7 +1573,8 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, | |||
1610 | d40d->lli_log.src, | 1573 | d40d->lli_log.src, |
1611 | d40c->log_def.lcsp1, | 1574 | d40c->log_def.lcsp1, |
1612 | d40c->dma_cfg.src_info.data_width, | 1575 | d40c->dma_cfg.src_info.data_width, |
1613 | flags & DMA_PREP_INTERRUPT, lli_max, | 1576 | dma_flags & DMA_PREP_INTERRUPT, |
1577 | d40d->lli_tx_len, | ||
1614 | d40c->base->plat_data->llis_per_log); | 1578 | d40c->base->plat_data->llis_per_log); |
1615 | 1579 | ||
1616 | (void) d40_log_sg_to_lli(d40c->lcla.dst_id, | 1580 | (void) d40_log_sg_to_lli(d40c->lcla.dst_id, |
@@ -1619,7 +1583,8 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, | |||
1619 | d40d->lli_log.dst, | 1583 | d40d->lli_log.dst, |
1620 | d40c->log_def.lcsp3, | 1584 | d40c->log_def.lcsp3, |
1621 | d40c->dma_cfg.dst_info.data_width, | 1585 | d40c->dma_cfg.dst_info.data_width, |
1622 | flags & DMA_PREP_INTERRUPT, lli_max, | 1586 | dma_flags & DMA_PREP_INTERRUPT, |
1587 | d40d->lli_tx_len, | ||
1623 | d40c->base->plat_data->llis_per_log); | 1588 | d40c->base->plat_data->llis_per_log); |
1624 | 1589 | ||
1625 | 1590 | ||
@@ -1664,11 +1629,11 @@ struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan, | |||
1664 | 1629 | ||
1665 | d40d->txd.tx_submit = d40_tx_submit; | 1630 | d40d->txd.tx_submit = d40_tx_submit; |
1666 | 1631 | ||
1667 | spin_unlock_irqrestore(&d40c->lock, flg); | 1632 | spin_unlock_irqrestore(&d40c->lock, flags); |
1668 | 1633 | ||
1669 | return &d40d->txd; | 1634 | return &d40d->txd; |
1670 | err: | 1635 | err: |
1671 | spin_unlock_irqrestore(&d40c->lock, flg); | 1636 | spin_unlock_irqrestore(&d40c->lock, flags); |
1672 | return NULL; | 1637 | return NULL; |
1673 | } | 1638 | } |
1674 | EXPORT_SYMBOL(stedma40_memcpy_sg); | 1639 | EXPORT_SYMBOL(stedma40_memcpy_sg); |
@@ -1698,46 +1663,66 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) | |||
1698 | unsigned long flags; | 1663 | unsigned long flags; |
1699 | struct d40_chan *d40c = | 1664 | struct d40_chan *d40c = |
1700 | container_of(chan, struct d40_chan, chan); | 1665 | container_of(chan, struct d40_chan, chan); |
1701 | 1666 | bool is_free_phy; | |
1702 | spin_lock_irqsave(&d40c->lock, flags); | 1667 | spin_lock_irqsave(&d40c->lock, flags); |
1703 | 1668 | ||
1704 | d40c->completed = chan->cookie = 1; | 1669 | d40c->completed = chan->cookie = 1; |
1705 | 1670 | ||
1706 | /* | 1671 | /* |
1707 | * If no dma configuration is set (channel_type == 0) | 1672 | * If no dma configuration is set (channel_type == 0) |
1708 | * use default configuration | 1673 | * use default configuration (memcpy) |
1709 | */ | 1674 | */ |
1710 | if (d40c->dma_cfg.channel_type == 0) { | 1675 | if (d40c->dma_cfg.channel_type == 0) { |
1711 | err = d40_config_memcpy(d40c); | 1676 | err = d40_config_memcpy(d40c); |
1712 | if (err) | 1677 | if (err) { |
1713 | goto err_alloc; | 1678 | dev_err(&d40c->chan.dev->device, |
1679 | "[%s] Failed to configure memcpy channel\n", | ||
1680 | __func__); | ||
1681 | goto fail; | ||
1682 | } | ||
1714 | } | 1683 | } |
1684 | is_free_phy = (d40c->phy_chan == NULL); | ||
1715 | 1685 | ||
1716 | err = d40_allocate_channel(d40c); | 1686 | err = d40_allocate_channel(d40c); |
1717 | if (err) { | 1687 | if (err) { |
1718 | dev_err(&d40c->chan.dev->device, | 1688 | dev_err(&d40c->chan.dev->device, |
1719 | "[%s] Failed to allocate channel\n", __func__); | 1689 | "[%s] Failed to allocate channel\n", __func__); |
1720 | goto err_alloc; | 1690 | goto fail; |
1721 | } | 1691 | } |
1722 | 1692 | ||
1723 | err = d40_config_chan(d40c, &d40c->dma_cfg); | 1693 | /* Fill in basic CFG register values */ |
1724 | if (err) { | 1694 | d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg, |
1725 | dev_err(&d40c->chan.dev->device, | 1695 | &d40c->dst_def_cfg, d40c->log_num != D40_PHY_CHAN); |
1726 | "[%s] Failed to configure channel\n", | ||
1727 | __func__); | ||
1728 | goto err_config; | ||
1729 | } | ||
1730 | 1696 | ||
1731 | spin_unlock_irqrestore(&d40c->lock, flags); | 1697 | if (d40c->log_num != D40_PHY_CHAN) { |
1732 | return 0; | 1698 | d40_log_cfg(&d40c->dma_cfg, |
1699 | &d40c->log_def.lcsp1, &d40c->log_def.lcsp3); | ||
1733 | 1700 | ||
1734 | err_config: | 1701 | if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) |
1735 | (void) d40_free_dma(d40c); | 1702 | d40c->lcpa = d40c->base->lcpa_base + |
1736 | err_alloc: | 1703 | d40c->dma_cfg.src_dev_type * D40_LCPA_CHAN_SIZE; |
1704 | else | ||
1705 | d40c->lcpa = d40c->base->lcpa_base + | ||
1706 | d40c->dma_cfg.dst_dev_type * | ||
1707 | D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA; | ||
1708 | } | ||
1709 | |||
1710 | /* | ||
1711 | * Only write channel configuration to the DMA if the physical | ||
1712 | * resource is free. In case of multiple logical channels | ||
1713 | * on the same physical resource, only the first write is necessary. | ||
1714 | */ | ||
1715 | if (is_free_phy) { | ||
1716 | err = d40_config_write(d40c); | ||
1717 | if (err) { | ||
1718 | dev_err(&d40c->chan.dev->device, | ||
1719 | "[%s] Failed to configure channel\n", | ||
1720 | __func__); | ||
1721 | } | ||
1722 | } | ||
1723 | fail: | ||
1737 | spin_unlock_irqrestore(&d40c->lock, flags); | 1724 | spin_unlock_irqrestore(&d40c->lock, flags); |
1738 | dev_err(&d40c->chan.dev->device, | 1725 | return err; |
1739 | "[%s] Channel allocation failed\n", __func__); | ||
1740 | return -EINVAL; | ||
1741 | } | 1726 | } |
1742 | 1727 | ||
1743 | static void d40_free_chan_resources(struct dma_chan *chan) | 1728 | static void d40_free_chan_resources(struct dma_chan *chan) |
@@ -1747,6 +1732,13 @@ static void d40_free_chan_resources(struct dma_chan *chan) | |||
1747 | int err; | 1732 | int err; |
1748 | unsigned long flags; | 1733 | unsigned long flags; |
1749 | 1734 | ||
1735 | if (d40c->phy_chan == NULL) { | ||
1736 | dev_err(&d40c->chan.dev->device, | ||
1737 | "[%s] Cannot free unallocated channel\n", __func__); | ||
1738 | return; | ||
1739 | } | ||
1740 | |||
1741 | |||
1750 | spin_lock_irqsave(&d40c->lock, flags); | 1742 | spin_lock_irqsave(&d40c->lock, flags); |
1751 | 1743 | ||
1752 | err = d40_free_dma(d40c); | 1744 | err = d40_free_dma(d40c); |
@@ -1761,15 +1753,21 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, | |||
1761 | dma_addr_t dst, | 1753 | dma_addr_t dst, |
1762 | dma_addr_t src, | 1754 | dma_addr_t src, |
1763 | size_t size, | 1755 | size_t size, |
1764 | unsigned long flags) | 1756 | unsigned long dma_flags) |
1765 | { | 1757 | { |
1766 | struct d40_desc *d40d; | 1758 | struct d40_desc *d40d; |
1767 | struct d40_chan *d40c = container_of(chan, struct d40_chan, | 1759 | struct d40_chan *d40c = container_of(chan, struct d40_chan, |
1768 | chan); | 1760 | chan); |
1769 | unsigned long flg; | 1761 | unsigned long flags; |
1770 | int err = 0; | 1762 | int err = 0; |
1771 | 1763 | ||
1772 | spin_lock_irqsave(&d40c->lock, flg); | 1764 | if (d40c->phy_chan == NULL) { |
1765 | dev_err(&d40c->chan.dev->device, | ||
1766 | "[%s] Channel is not allocated.\n", __func__); | ||
1767 | return ERR_PTR(-EINVAL); | ||
1768 | } | ||
1769 | |||
1770 | spin_lock_irqsave(&d40c->lock, flags); | ||
1773 | d40d = d40_desc_get(d40c); | 1771 | d40d = d40_desc_get(d40c); |
1774 | 1772 | ||
1775 | if (d40d == NULL) { | 1773 | if (d40d == NULL) { |
@@ -1778,9 +1776,7 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, | |||
1778 | goto err; | 1776 | goto err; |
1779 | } | 1777 | } |
1780 | 1778 | ||
1781 | memset(d40d, 0, sizeof(struct d40_desc)); | 1779 | d40d->txd.flags = dma_flags; |
1782 | |||
1783 | d40d->txd.flags = flags; | ||
1784 | 1780 | ||
1785 | dma_async_tx_descriptor_init(&d40d->txd, chan); | 1781 | dma_async_tx_descriptor_init(&d40d->txd, chan); |
1786 | 1782 | ||
@@ -1794,6 +1790,7 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, | |||
1794 | goto err; | 1790 | goto err; |
1795 | } | 1791 | } |
1796 | d40d->lli_len = 1; | 1792 | d40d->lli_len = 1; |
1793 | d40d->lli_tx_len = 1; | ||
1797 | 1794 | ||
1798 | d40_log_fill_lli(d40d->lli_log.src, | 1795 | d40_log_fill_lli(d40d->lli_log.src, |
1799 | src, | 1796 | src, |
@@ -1801,7 +1798,7 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, | |||
1801 | 0, | 1798 | 0, |
1802 | d40c->log_def.lcsp1, | 1799 | d40c->log_def.lcsp1, |
1803 | d40c->dma_cfg.src_info.data_width, | 1800 | d40c->dma_cfg.src_info.data_width, |
1804 | true, true); | 1801 | false, true); |
1805 | 1802 | ||
1806 | d40_log_fill_lli(d40d->lli_log.dst, | 1803 | d40_log_fill_lli(d40d->lli_log.dst, |
1807 | dst, | 1804 | dst, |
@@ -1848,7 +1845,7 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan, | |||
1848 | d40d->lli_pool.size, DMA_TO_DEVICE); | 1845 | d40d->lli_pool.size, DMA_TO_DEVICE); |
1849 | } | 1846 | } |
1850 | 1847 | ||
1851 | spin_unlock_irqrestore(&d40c->lock, flg); | 1848 | spin_unlock_irqrestore(&d40c->lock, flags); |
1852 | return &d40d->txd; | 1849 | return &d40d->txd; |
1853 | 1850 | ||
1854 | err_fill_lli: | 1851 | err_fill_lli: |
@@ -1856,7 +1853,7 @@ err_fill_lli: | |||
1856 | "[%s] Failed filling in PHY LLI\n", __func__); | 1853 | "[%s] Failed filling in PHY LLI\n", __func__); |
1857 | d40_pool_lli_free(d40d); | 1854 | d40_pool_lli_free(d40d); |
1858 | err: | 1855 | err: |
1859 | spin_unlock_irqrestore(&d40c->lock, flg); | 1856 | spin_unlock_irqrestore(&d40c->lock, flags); |
1860 | return NULL; | 1857 | return NULL; |
1861 | } | 1858 | } |
1862 | 1859 | ||
@@ -1865,11 +1862,10 @@ static int d40_prep_slave_sg_log(struct d40_desc *d40d, | |||
1865 | struct scatterlist *sgl, | 1862 | struct scatterlist *sgl, |
1866 | unsigned int sg_len, | 1863 | unsigned int sg_len, |
1867 | enum dma_data_direction direction, | 1864 | enum dma_data_direction direction, |
1868 | unsigned long flags) | 1865 | unsigned long dma_flags) |
1869 | { | 1866 | { |
1870 | dma_addr_t dev_addr = 0; | 1867 | dma_addr_t dev_addr = 0; |
1871 | int total_size; | 1868 | int total_size; |
1872 | int lli_max = d40c->base->plat_data->llis_per_log; | ||
1873 | 1869 | ||
1874 | if (d40_pool_lli_alloc(d40d, sg_len, true) < 0) { | 1870 | if (d40_pool_lli_alloc(d40d, sg_len, true) < 0) { |
1875 | dev_err(&d40c->chan.dev->device, | 1871 | dev_err(&d40c->chan.dev->device, |
@@ -1878,7 +1874,10 @@ static int d40_prep_slave_sg_log(struct d40_desc *d40d, | |||
1878 | } | 1874 | } |
1879 | 1875 | ||
1880 | d40d->lli_len = sg_len; | 1876 | d40d->lli_len = sg_len; |
1881 | d40d->lli_tcount = 0; | 1877 | if (d40d->lli_len <= d40c->base->plat_data->llis_per_log) |
1878 | d40d->lli_tx_len = d40d->lli_len; | ||
1879 | else | ||
1880 | d40d->lli_tx_len = d40c->base->plat_data->llis_per_log; | ||
1882 | 1881 | ||
1883 | if (sg_len > 1) | 1882 | if (sg_len > 1) |
1884 | /* | 1883 | /* |
@@ -1886,35 +1885,34 @@ static int d40_prep_slave_sg_log(struct d40_desc *d40d, | |||
1886 | * If not, split list into 1-length and run only | 1885 | * If not, split list into 1-length and run only |
1887 | * in lcpa space. | 1886 | * in lcpa space. |
1888 | */ | 1887 | */ |
1889 | if (d40_lcla_id_get(d40c, &d40c->base->lcla_pool) != 0) | 1888 | if (d40_lcla_id_get(d40c) != 0) |
1890 | lli_max = 1; | 1889 | d40d->lli_tx_len = 1; |
1891 | 1890 | ||
1892 | if (direction == DMA_FROM_DEVICE) { | 1891 | if (direction == DMA_FROM_DEVICE) |
1893 | dev_addr = d40c->base->plat_data->dev_rx[d40c->dma_cfg.src_dev_type]; | 1892 | if (d40c->runtime_addr) |
1894 | total_size = d40_log_sg_to_dev(&d40c->lcla, | 1893 | dev_addr = d40c->runtime_addr; |
1895 | sgl, sg_len, | 1894 | else |
1896 | &d40d->lli_log, | 1895 | dev_addr = d40c->base->plat_data->dev_rx[d40c->dma_cfg.src_dev_type]; |
1897 | &d40c->log_def, | 1896 | else if (direction == DMA_TO_DEVICE) |
1898 | d40c->dma_cfg.src_info.data_width, | 1897 | if (d40c->runtime_addr) |
1899 | d40c->dma_cfg.dst_info.data_width, | 1898 | dev_addr = d40c->runtime_addr; |
1900 | direction, | 1899 | else |
1901 | flags & DMA_PREP_INTERRUPT, | 1900 | dev_addr = d40c->base->plat_data->dev_tx[d40c->dma_cfg.dst_dev_type]; |
1902 | dev_addr, lli_max, | 1901 | |
1903 | d40c->base->plat_data->llis_per_log); | 1902 | else |
1904 | } else if (direction == DMA_TO_DEVICE) { | ||
1905 | dev_addr = d40c->base->plat_data->dev_tx[d40c->dma_cfg.dst_dev_type]; | ||
1906 | total_size = d40_log_sg_to_dev(&d40c->lcla, | ||
1907 | sgl, sg_len, | ||
1908 | &d40d->lli_log, | ||
1909 | &d40c->log_def, | ||
1910 | d40c->dma_cfg.src_info.data_width, | ||
1911 | d40c->dma_cfg.dst_info.data_width, | ||
1912 | direction, | ||
1913 | flags & DMA_PREP_INTERRUPT, | ||
1914 | dev_addr, lli_max, | ||
1915 | d40c->base->plat_data->llis_per_log); | ||
1916 | } else | ||
1917 | return -EINVAL; | 1903 | return -EINVAL; |
1904 | |||
1905 | total_size = d40_log_sg_to_dev(&d40c->lcla, | ||
1906 | sgl, sg_len, | ||
1907 | &d40d->lli_log, | ||
1908 | &d40c->log_def, | ||
1909 | d40c->dma_cfg.src_info.data_width, | ||
1910 | d40c->dma_cfg.dst_info.data_width, | ||
1911 | direction, | ||
1912 | dma_flags & DMA_PREP_INTERRUPT, | ||
1913 | dev_addr, d40d->lli_tx_len, | ||
1914 | d40c->base->plat_data->llis_per_log); | ||
1915 | |||
1918 | if (total_size < 0) | 1916 | if (total_size < 0) |
1919 | return -EINVAL; | 1917 | return -EINVAL; |
1920 | 1918 | ||
@@ -1926,7 +1924,7 @@ static int d40_prep_slave_sg_phy(struct d40_desc *d40d, | |||
1926 | struct scatterlist *sgl, | 1924 | struct scatterlist *sgl, |
1927 | unsigned int sgl_len, | 1925 | unsigned int sgl_len, |
1928 | enum dma_data_direction direction, | 1926 | enum dma_data_direction direction, |
1929 | unsigned long flags) | 1927 | unsigned long dma_flags) |
1930 | { | 1928 | { |
1931 | dma_addr_t src_dev_addr; | 1929 | dma_addr_t src_dev_addr; |
1932 | dma_addr_t dst_dev_addr; | 1930 | dma_addr_t dst_dev_addr; |
@@ -1939,13 +1937,19 @@ static int d40_prep_slave_sg_phy(struct d40_desc *d40d, | |||
1939 | } | 1937 | } |
1940 | 1938 | ||
1941 | d40d->lli_len = sgl_len; | 1939 | d40d->lli_len = sgl_len; |
1942 | d40d->lli_tcount = 0; | 1940 | d40d->lli_tx_len = sgl_len; |
1943 | 1941 | ||
1944 | if (direction == DMA_FROM_DEVICE) { | 1942 | if (direction == DMA_FROM_DEVICE) { |
1945 | dst_dev_addr = 0; | 1943 | dst_dev_addr = 0; |
1946 | src_dev_addr = d40c->base->plat_data->dev_rx[d40c->dma_cfg.src_dev_type]; | 1944 | if (d40c->runtime_addr) |
1945 | src_dev_addr = d40c->runtime_addr; | ||
1946 | else | ||
1947 | src_dev_addr = d40c->base->plat_data->dev_rx[d40c->dma_cfg.src_dev_type]; | ||
1947 | } else if (direction == DMA_TO_DEVICE) { | 1948 | } else if (direction == DMA_TO_DEVICE) { |
1948 | dst_dev_addr = d40c->base->plat_data->dev_tx[d40c->dma_cfg.dst_dev_type]; | 1949 | if (d40c->runtime_addr) |
1950 | dst_dev_addr = d40c->runtime_addr; | ||
1951 | else | ||
1952 | dst_dev_addr = d40c->base->plat_data->dev_tx[d40c->dma_cfg.dst_dev_type]; | ||
1949 | src_dev_addr = 0; | 1953 | src_dev_addr = 0; |
1950 | } else | 1954 | } else |
1951 | return -EINVAL; | 1955 | return -EINVAL; |
@@ -1983,34 +1987,38 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, | |||
1983 | struct scatterlist *sgl, | 1987 | struct scatterlist *sgl, |
1984 | unsigned int sg_len, | 1988 | unsigned int sg_len, |
1985 | enum dma_data_direction direction, | 1989 | enum dma_data_direction direction, |
1986 | unsigned long flags) | 1990 | unsigned long dma_flags) |
1987 | { | 1991 | { |
1988 | struct d40_desc *d40d; | 1992 | struct d40_desc *d40d; |
1989 | struct d40_chan *d40c = container_of(chan, struct d40_chan, | 1993 | struct d40_chan *d40c = container_of(chan, struct d40_chan, |
1990 | chan); | 1994 | chan); |
1991 | unsigned long flg; | 1995 | unsigned long flags; |
1992 | int err; | 1996 | int err; |
1993 | 1997 | ||
1998 | if (d40c->phy_chan == NULL) { | ||
1999 | dev_err(&d40c->chan.dev->device, | ||
2000 | "[%s] Cannot prepare unallocated channel\n", __func__); | ||
2001 | return ERR_PTR(-EINVAL); | ||
2002 | } | ||
2003 | |||
1994 | if (d40c->dma_cfg.pre_transfer) | 2004 | if (d40c->dma_cfg.pre_transfer) |
1995 | d40c->dma_cfg.pre_transfer(chan, | 2005 | d40c->dma_cfg.pre_transfer(chan, |
1996 | d40c->dma_cfg.pre_transfer_data, | 2006 | d40c->dma_cfg.pre_transfer_data, |
1997 | sg_dma_len(sgl)); | 2007 | sg_dma_len(sgl)); |
1998 | 2008 | ||
1999 | spin_lock_irqsave(&d40c->lock, flg); | 2009 | spin_lock_irqsave(&d40c->lock, flags); |
2000 | d40d = d40_desc_get(d40c); | 2010 | d40d = d40_desc_get(d40c); |
2001 | spin_unlock_irqrestore(&d40c->lock, flg); | 2011 | spin_unlock_irqrestore(&d40c->lock, flags); |
2002 | 2012 | ||
2003 | if (d40d == NULL) | 2013 | if (d40d == NULL) |
2004 | return NULL; | 2014 | return NULL; |
2005 | 2015 | ||
2006 | memset(d40d, 0, sizeof(struct d40_desc)); | ||
2007 | |||
2008 | if (d40c->log_num != D40_PHY_CHAN) | 2016 | if (d40c->log_num != D40_PHY_CHAN) |
2009 | err = d40_prep_slave_sg_log(d40d, d40c, sgl, sg_len, | 2017 | err = d40_prep_slave_sg_log(d40d, d40c, sgl, sg_len, |
2010 | direction, flags); | 2018 | direction, dma_flags); |
2011 | else | 2019 | else |
2012 | err = d40_prep_slave_sg_phy(d40d, d40c, sgl, sg_len, | 2020 | err = d40_prep_slave_sg_phy(d40d, d40c, sgl, sg_len, |
2013 | direction, flags); | 2021 | direction, dma_flags); |
2014 | if (err) { | 2022 | if (err) { |
2015 | dev_err(&d40c->chan.dev->device, | 2023 | dev_err(&d40c->chan.dev->device, |
2016 | "[%s] Failed to prepare %s slave sg job: %d\n", | 2024 | "[%s] Failed to prepare %s slave sg job: %d\n", |
@@ -2019,7 +2027,7 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, | |||
2019 | return NULL; | 2027 | return NULL; |
2020 | } | 2028 | } |
2021 | 2029 | ||
2022 | d40d->txd.flags = flags; | 2030 | d40d->txd.flags = dma_flags; |
2023 | 2031 | ||
2024 | dma_async_tx_descriptor_init(&d40d->txd, chan); | 2032 | dma_async_tx_descriptor_init(&d40d->txd, chan); |
2025 | 2033 | ||
@@ -2037,6 +2045,13 @@ static enum dma_status d40_tx_status(struct dma_chan *chan, | |||
2037 | dma_cookie_t last_complete; | 2045 | dma_cookie_t last_complete; |
2038 | int ret; | 2046 | int ret; |
2039 | 2047 | ||
2048 | if (d40c->phy_chan == NULL) { | ||
2049 | dev_err(&d40c->chan.dev->device, | ||
2050 | "[%s] Cannot read status of unallocated channel\n", | ||
2051 | __func__); | ||
2052 | return -EINVAL; | ||
2053 | } | ||
2054 | |||
2040 | last_complete = d40c->completed; | 2055 | last_complete = d40c->completed; |
2041 | last_used = chan->cookie; | 2056 | last_used = chan->cookie; |
2042 | 2057 | ||
@@ -2056,6 +2071,12 @@ static void d40_issue_pending(struct dma_chan *chan) | |||
2056 | struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); | 2071 | struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); |
2057 | unsigned long flags; | 2072 | unsigned long flags; |
2058 | 2073 | ||
2074 | if (d40c->phy_chan == NULL) { | ||
2075 | dev_err(&d40c->chan.dev->device, | ||
2076 | "[%s] Channel is not allocated!\n", __func__); | ||
2077 | return; | ||
2078 | } | ||
2079 | |||
2059 | spin_lock_irqsave(&d40c->lock, flags); | 2080 | spin_lock_irqsave(&d40c->lock, flags); |
2060 | 2081 | ||
2061 | /* Busy means that pending jobs are already being processed */ | 2082 | /* Busy means that pending jobs are already being processed */ |
@@ -2065,12 +2086,129 @@ static void d40_issue_pending(struct dma_chan *chan) | |||
2065 | spin_unlock_irqrestore(&d40c->lock, flags); | 2086 | spin_unlock_irqrestore(&d40c->lock, flags); |
2066 | } | 2087 | } |
2067 | 2088 | ||
2089 | /* Runtime reconfiguration extension */ | ||
2090 | static void d40_set_runtime_config(struct dma_chan *chan, | ||
2091 | struct dma_slave_config *config) | ||
2092 | { | ||
2093 | struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); | ||
2094 | struct stedma40_chan_cfg *cfg = &d40c->dma_cfg; | ||
2095 | enum dma_slave_buswidth config_addr_width; | ||
2096 | dma_addr_t config_addr; | ||
2097 | u32 config_maxburst; | ||
2098 | enum stedma40_periph_data_width addr_width; | ||
2099 | int psize; | ||
2100 | |||
2101 | if (config->direction == DMA_FROM_DEVICE) { | ||
2102 | dma_addr_t dev_addr_rx = | ||
2103 | d40c->base->plat_data->dev_rx[cfg->src_dev_type]; | ||
2104 | |||
2105 | config_addr = config->src_addr; | ||
2106 | if (dev_addr_rx) | ||
2107 | dev_dbg(d40c->base->dev, | ||
2108 | "channel has a pre-wired RX address %08x " | ||
2109 | "overriding with %08x\n", | ||
2110 | dev_addr_rx, config_addr); | ||
2111 | if (cfg->dir != STEDMA40_PERIPH_TO_MEM) | ||
2112 | dev_dbg(d40c->base->dev, | ||
2113 | "channel was not configured for peripheral " | ||
2114 | "to memory transfer (%d) overriding\n", | ||
2115 | cfg->dir); | ||
2116 | cfg->dir = STEDMA40_PERIPH_TO_MEM; | ||
2117 | |||
2118 | config_addr_width = config->src_addr_width; | ||
2119 | config_maxburst = config->src_maxburst; | ||
2120 | |||
2121 | } else if (config->direction == DMA_TO_DEVICE) { | ||
2122 | dma_addr_t dev_addr_tx = | ||
2123 | d40c->base->plat_data->dev_tx[cfg->dst_dev_type]; | ||
2124 | |||
2125 | config_addr = config->dst_addr; | ||
2126 | if (dev_addr_tx) | ||
2127 | dev_dbg(d40c->base->dev, | ||
2128 | "channel has a pre-wired TX address %08x " | ||
2129 | "overriding with %08x\n", | ||
2130 | dev_addr_tx, config_addr); | ||
2131 | if (cfg->dir != STEDMA40_MEM_TO_PERIPH) | ||
2132 | dev_dbg(d40c->base->dev, | ||
2133 | "channel was not configured for memory " | ||
2134 | "to peripheral transfer (%d) overriding\n", | ||
2135 | cfg->dir); | ||
2136 | cfg->dir = STEDMA40_MEM_TO_PERIPH; | ||
2137 | |||
2138 | config_addr_width = config->dst_addr_width; | ||
2139 | config_maxburst = config->dst_maxburst; | ||
2140 | |||
2141 | } else { | ||
2142 | dev_err(d40c->base->dev, | ||
2143 | "unrecognized channel direction %d\n", | ||
2144 | config->direction); | ||
2145 | return; | ||
2146 | } | ||
2147 | |||
2148 | switch (config_addr_width) { | ||
2149 | case DMA_SLAVE_BUSWIDTH_1_BYTE: | ||
2150 | addr_width = STEDMA40_BYTE_WIDTH; | ||
2151 | break; | ||
2152 | case DMA_SLAVE_BUSWIDTH_2_BYTES: | ||
2153 | addr_width = STEDMA40_HALFWORD_WIDTH; | ||
2154 | break; | ||
2155 | case DMA_SLAVE_BUSWIDTH_4_BYTES: | ||
2156 | addr_width = STEDMA40_WORD_WIDTH; | ||
2157 | break; | ||
2158 | case DMA_SLAVE_BUSWIDTH_8_BYTES: | ||
2159 | addr_width = STEDMA40_DOUBLEWORD_WIDTH; | ||
2160 | break; | ||
2161 | default: | ||
2162 | dev_err(d40c->base->dev, | ||
2163 | "illegal peripheral address width " | ||
2164 | "requested (%d)\n", | ||
2165 | config->src_addr_width); | ||
2166 | return; | ||
2167 | } | ||
2168 | |||
2169 | if (config_maxburst >= 16) | ||
2170 | psize = STEDMA40_PSIZE_LOG_16; | ||
2171 | else if (config_maxburst >= 8) | ||
2172 | psize = STEDMA40_PSIZE_LOG_8; | ||
2173 | else if (config_maxburst >= 4) | ||
2174 | psize = STEDMA40_PSIZE_LOG_4; | ||
2175 | else | ||
2176 | psize = STEDMA40_PSIZE_LOG_1; | ||
2177 | |||
2178 | /* Set up all the endpoint configs */ | ||
2179 | cfg->src_info.data_width = addr_width; | ||
2180 | cfg->src_info.psize = psize; | ||
2181 | cfg->src_info.endianess = STEDMA40_LITTLE_ENDIAN; | ||
2182 | cfg->src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL; | ||
2183 | cfg->dst_info.data_width = addr_width; | ||
2184 | cfg->dst_info.psize = psize; | ||
2185 | cfg->dst_info.endianess = STEDMA40_LITTLE_ENDIAN; | ||
2186 | cfg->dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL; | ||
2187 | |||
2188 | /* These settings will take precedence later */ | ||
2189 | d40c->runtime_addr = config_addr; | ||
2190 | d40c->runtime_direction = config->direction; | ||
2191 | dev_dbg(d40c->base->dev, | ||
2192 | "configured channel %s for %s, data width %d, " | ||
2193 | "maxburst %d bytes, LE, no flow control\n", | ||
2194 | dma_chan_name(chan), | ||
2195 | (config->direction == DMA_FROM_DEVICE) ? "RX" : "TX", | ||
2196 | config_addr_width, | ||
2197 | config_maxburst); | ||
2198 | } | ||
2199 | |||
2068 | static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | 2200 | static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, |
2069 | unsigned long arg) | 2201 | unsigned long arg) |
2070 | { | 2202 | { |
2071 | unsigned long flags; | 2203 | unsigned long flags; |
2072 | struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); | 2204 | struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); |
2073 | 2205 | ||
2206 | if (d40c->phy_chan == NULL) { | ||
2207 | dev_err(&d40c->chan.dev->device, | ||
2208 | "[%s] Channel is not allocated!\n", __func__); | ||
2209 | return -EINVAL; | ||
2210 | } | ||
2211 | |||
2074 | switch (cmd) { | 2212 | switch (cmd) { |
2075 | case DMA_TERMINATE_ALL: | 2213 | case DMA_TERMINATE_ALL: |
2076 | spin_lock_irqsave(&d40c->lock, flags); | 2214 | spin_lock_irqsave(&d40c->lock, flags); |
@@ -2081,6 +2219,12 @@ static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | |||
2081 | return d40_pause(chan); | 2219 | return d40_pause(chan); |
2082 | case DMA_RESUME: | 2220 | case DMA_RESUME: |
2083 | return d40_resume(chan); | 2221 | return d40_resume(chan); |
2222 | case DMA_SLAVE_CONFIG: | ||
2223 | d40_set_runtime_config(chan, | ||
2224 | (struct dma_slave_config *) arg); | ||
2225 | return 0; | ||
2226 | default: | ||
2227 | break; | ||
2084 | } | 2228 | } |
2085 | 2229 | ||
2086 | /* Other commands are unimplemented */ | 2230 | /* Other commands are unimplemented */ |
@@ -2111,13 +2255,10 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma, | |||
2111 | 2255 | ||
2112 | d40c->log_num = D40_PHY_CHAN; | 2256 | d40c->log_num = D40_PHY_CHAN; |
2113 | 2257 | ||
2114 | INIT_LIST_HEAD(&d40c->free); | ||
2115 | INIT_LIST_HEAD(&d40c->active); | 2258 | INIT_LIST_HEAD(&d40c->active); |
2116 | INIT_LIST_HEAD(&d40c->queue); | 2259 | INIT_LIST_HEAD(&d40c->queue); |
2117 | INIT_LIST_HEAD(&d40c->client); | 2260 | INIT_LIST_HEAD(&d40c->client); |
2118 | 2261 | ||
2119 | d40c->free_len = 0; | ||
2120 | |||
2121 | tasklet_init(&d40c->tasklet, dma_tasklet, | 2262 | tasklet_init(&d40c->tasklet, dma_tasklet, |
2122 | (unsigned long) d40c); | 2263 | (unsigned long) d40c); |
2123 | 2264 | ||
@@ -2243,6 +2384,14 @@ static int __init d40_phy_res_init(struct d40_base *base) | |||
2243 | } | 2384 | } |
2244 | spin_lock_init(&base->phy_res[i].lock); | 2385 | spin_lock_init(&base->phy_res[i].lock); |
2245 | } | 2386 | } |
2387 | |||
2388 | /* Mark disabled channels as occupied */ | ||
2389 | for (i = 0; base->plat_data->disabled_channels[i] != -1; i++) { | ||
2390 | base->phy_res[i].allocated_src = D40_ALLOC_PHY; | ||
2391 | base->phy_res[i].allocated_dst = D40_ALLOC_PHY; | ||
2392 | num_phy_chans_avail--; | ||
2393 | } | ||
2394 | |||
2246 | dev_info(base->dev, "%d of %d physical DMA channels available\n", | 2395 | dev_info(base->dev, "%d of %d physical DMA channels available\n", |
2247 | num_phy_chans_avail, base->num_phy_chans); | 2396 | num_phy_chans_avail, base->num_phy_chans); |
2248 | 2397 | ||
@@ -2291,6 +2440,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
2291 | int num_log_chans = 0; | 2440 | int num_log_chans = 0; |
2292 | int num_phy_chans; | 2441 | int num_phy_chans; |
2293 | int i; | 2442 | int i; |
2443 | u32 val; | ||
2294 | 2444 | ||
2295 | clk = clk_get(&pdev->dev, NULL); | 2445 | clk = clk_get(&pdev->dev, NULL); |
2296 | 2446 | ||
@@ -2329,12 +2479,13 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
2329 | } | 2479 | } |
2330 | } | 2480 | } |
2331 | 2481 | ||
2332 | i = readl(virtbase + D40_DREG_PERIPHID2); | 2482 | /* Get silicon revision */ |
2483 | val = readl(virtbase + D40_DREG_PERIPHID2); | ||
2333 | 2484 | ||
2334 | if ((i & 0xf) != D40_PERIPHID2_DESIGNER) { | 2485 | if ((val & 0xf) != D40_PERIPHID2_DESIGNER) { |
2335 | dev_err(&pdev->dev, | 2486 | dev_err(&pdev->dev, |
2336 | "[%s] Unknown designer! Got %x wanted %x\n", | 2487 | "[%s] Unknown designer! Got %x wanted %x\n", |
2337 | __func__, i & 0xf, D40_PERIPHID2_DESIGNER); | 2488 | __func__, val & 0xf, D40_PERIPHID2_DESIGNER); |
2338 | goto failure; | 2489 | goto failure; |
2339 | } | 2490 | } |
2340 | 2491 | ||
@@ -2342,7 +2493,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
2342 | num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4; | 2493 | num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4; |
2343 | 2494 | ||
2344 | dev_info(&pdev->dev, "hardware revision: %d @ 0x%x\n", | 2495 | dev_info(&pdev->dev, "hardware revision: %d @ 0x%x\n", |
2345 | (i >> 4) & 0xf, res->start); | 2496 | (val >> 4) & 0xf, res->start); |
2346 | 2497 | ||
2347 | plat_data = pdev->dev.platform_data; | 2498 | plat_data = pdev->dev.platform_data; |
2348 | 2499 | ||
@@ -2364,6 +2515,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
2364 | goto failure; | 2515 | goto failure; |
2365 | } | 2516 | } |
2366 | 2517 | ||
2518 | base->rev = (val >> 4) & 0xf; | ||
2367 | base->clk = clk; | 2519 | base->clk = clk; |
2368 | base->num_phy_chans = num_phy_chans; | 2520 | base->num_phy_chans = num_phy_chans; |
2369 | base->num_log_chans = num_log_chans; | 2521 | base->num_log_chans = num_log_chans; |
@@ -2402,6 +2554,12 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
2402 | if (!base->lcla_pool.alloc_map) | 2554 | if (!base->lcla_pool.alloc_map) |
2403 | goto failure; | 2555 | goto failure; |
2404 | 2556 | ||
2557 | base->desc_slab = kmem_cache_create(D40_NAME, sizeof(struct d40_desc), | ||
2558 | 0, SLAB_HWCACHE_ALIGN, | ||
2559 | NULL); | ||
2560 | if (base->desc_slab == NULL) | ||
2561 | goto failure; | ||
2562 | |||
2405 | return base; | 2563 | return base; |
2406 | 2564 | ||
2407 | failure: | 2565 | failure: |
@@ -2495,6 +2653,78 @@ static void __init d40_hw_init(struct d40_base *base) | |||
2495 | 2653 | ||
2496 | } | 2654 | } |
2497 | 2655 | ||
2656 | static int __init d40_lcla_allocate(struct d40_base *base) | ||
2657 | { | ||
2658 | unsigned long *page_list; | ||
2659 | int i, j; | ||
2660 | int ret = 0; | ||
2661 | |||
2662 | /* | ||
2663 | * This is somewhat ugly. We need 8192 bytes that are 18 bit aligned, | ||
2664 | * To full fill this hardware requirement without wasting 256 kb | ||
2665 | * we allocate pages until we get an aligned one. | ||
2666 | */ | ||
2667 | page_list = kmalloc(sizeof(unsigned long) * MAX_LCLA_ALLOC_ATTEMPTS, | ||
2668 | GFP_KERNEL); | ||
2669 | |||
2670 | if (!page_list) { | ||
2671 | ret = -ENOMEM; | ||
2672 | goto failure; | ||
2673 | } | ||
2674 | |||
2675 | /* Calculating how many pages that are required */ | ||
2676 | base->lcla_pool.pages = SZ_1K * base->num_phy_chans / PAGE_SIZE; | ||
2677 | |||
2678 | for (i = 0; i < MAX_LCLA_ALLOC_ATTEMPTS; i++) { | ||
2679 | page_list[i] = __get_free_pages(GFP_KERNEL, | ||
2680 | base->lcla_pool.pages); | ||
2681 | if (!page_list[i]) { | ||
2682 | |||
2683 | dev_err(base->dev, | ||
2684 | "[%s] Failed to allocate %d pages.\n", | ||
2685 | __func__, base->lcla_pool.pages); | ||
2686 | |||
2687 | for (j = 0; j < i; j++) | ||
2688 | free_pages(page_list[j], base->lcla_pool.pages); | ||
2689 | goto failure; | ||
2690 | } | ||
2691 | |||
2692 | if ((virt_to_phys((void *)page_list[i]) & | ||
2693 | (LCLA_ALIGNMENT - 1)) == 0) | ||
2694 | break; | ||
2695 | } | ||
2696 | |||
2697 | for (j = 0; j < i; j++) | ||
2698 | free_pages(page_list[j], base->lcla_pool.pages); | ||
2699 | |||
2700 | if (i < MAX_LCLA_ALLOC_ATTEMPTS) { | ||
2701 | base->lcla_pool.base = (void *)page_list[i]; | ||
2702 | } else { | ||
2703 | /* After many attempts, no succees with finding the correct | ||
2704 | * alignment try with allocating a big buffer */ | ||
2705 | dev_warn(base->dev, | ||
2706 | "[%s] Failed to get %d pages @ 18 bit align.\n", | ||
2707 | __func__, base->lcla_pool.pages); | ||
2708 | base->lcla_pool.base_unaligned = kmalloc(SZ_1K * | ||
2709 | base->num_phy_chans + | ||
2710 | LCLA_ALIGNMENT, | ||
2711 | GFP_KERNEL); | ||
2712 | if (!base->lcla_pool.base_unaligned) { | ||
2713 | ret = -ENOMEM; | ||
2714 | goto failure; | ||
2715 | } | ||
2716 | |||
2717 | base->lcla_pool.base = PTR_ALIGN(base->lcla_pool.base_unaligned, | ||
2718 | LCLA_ALIGNMENT); | ||
2719 | } | ||
2720 | |||
2721 | writel(virt_to_phys(base->lcla_pool.base), | ||
2722 | base->virtbase + D40_DREG_LCLA); | ||
2723 | failure: | ||
2724 | kfree(page_list); | ||
2725 | return ret; | ||
2726 | } | ||
2727 | |||
2498 | static int __init d40_probe(struct platform_device *pdev) | 2728 | static int __init d40_probe(struct platform_device *pdev) |
2499 | { | 2729 | { |
2500 | int err; | 2730 | int err; |
@@ -2554,41 +2784,11 @@ static int __init d40_probe(struct platform_device *pdev) | |||
2554 | __func__); | 2784 | __func__); |
2555 | goto failure; | 2785 | goto failure; |
2556 | } | 2786 | } |
2557 | /* Get IO for logical channel link address */ | ||
2558 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lcla"); | ||
2559 | if (!res) { | ||
2560 | ret = -ENOENT; | ||
2561 | dev_err(&pdev->dev, | ||
2562 | "[%s] No \"lcla\" resource defined\n", | ||
2563 | __func__); | ||
2564 | goto failure; | ||
2565 | } | ||
2566 | 2787 | ||
2567 | base->lcla_pool.base_size = resource_size(res); | 2788 | ret = d40_lcla_allocate(base); |
2568 | base->lcla_pool.phy = res->start; | 2789 | if (ret) { |
2569 | 2790 | dev_err(&pdev->dev, "[%s] Failed to allocate LCLA area\n", | |
2570 | if (request_mem_region(res->start, resource_size(res), | 2791 | __func__); |
2571 | D40_NAME " I/O lcla") == NULL) { | ||
2572 | ret = -EBUSY; | ||
2573 | dev_err(&pdev->dev, | ||
2574 | "[%s] Failed to request LCLA region 0x%x-0x%x\n", | ||
2575 | __func__, res->start, res->end); | ||
2576 | goto failure; | ||
2577 | } | ||
2578 | val = readl(base->virtbase + D40_DREG_LCLA); | ||
2579 | if (res->start != val && val != 0) { | ||
2580 | dev_warn(&pdev->dev, | ||
2581 | "[%s] Mismatch LCLA dma 0x%x, def 0x%x\n", | ||
2582 | __func__, val, res->start); | ||
2583 | } else | ||
2584 | writel(res->start, base->virtbase + D40_DREG_LCLA); | ||
2585 | |||
2586 | base->lcla_pool.base = ioremap(res->start, resource_size(res)); | ||
2587 | if (!base->lcla_pool.base) { | ||
2588 | ret = -ENOMEM; | ||
2589 | dev_err(&pdev->dev, | ||
2590 | "[%s] Failed to ioremap LCLA 0x%x-0x%x\n", | ||
2591 | __func__, res->start, res->end); | ||
2592 | goto failure; | 2792 | goto failure; |
2593 | } | 2793 | } |
2594 | 2794 | ||
@@ -2616,11 +2816,15 @@ static int __init d40_probe(struct platform_device *pdev) | |||
2616 | 2816 | ||
2617 | failure: | 2817 | failure: |
2618 | if (base) { | 2818 | if (base) { |
2819 | if (base->desc_slab) | ||
2820 | kmem_cache_destroy(base->desc_slab); | ||
2619 | if (base->virtbase) | 2821 | if (base->virtbase) |
2620 | iounmap(base->virtbase); | 2822 | iounmap(base->virtbase); |
2621 | if (base->lcla_pool.phy) | 2823 | if (!base->lcla_pool.base_unaligned && base->lcla_pool.base) |
2622 | release_mem_region(base->lcla_pool.phy, | 2824 | free_pages((unsigned long)base->lcla_pool.base, |
2623 | base->lcla_pool.base_size); | 2825 | base->lcla_pool.pages); |
2826 | if (base->lcla_pool.base_unaligned) | ||
2827 | kfree(base->lcla_pool.base_unaligned); | ||
2624 | if (base->phy_lcpa) | 2828 | if (base->phy_lcpa) |
2625 | release_mem_region(base->phy_lcpa, | 2829 | release_mem_region(base->phy_lcpa, |
2626 | base->lcpa_size); | 2830 | base->lcpa_size); |
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index 561fdd8a80c1..d937f76d6e2e 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c | |||
@@ -315,11 +315,8 @@ int d40_log_sg_to_dev(struct d40_lcla_elem *lcla, | |||
315 | int total_size = 0; | 315 | int total_size = 0; |
316 | struct scatterlist *current_sg = sg; | 316 | struct scatterlist *current_sg = sg; |
317 | int i; | 317 | int i; |
318 | u32 next_lli_off_dst; | 318 | u32 next_lli_off_dst = 0; |
319 | u32 next_lli_off_src; | 319 | u32 next_lli_off_src = 0; |
320 | |||
321 | next_lli_off_src = 0; | ||
322 | next_lli_off_dst = 0; | ||
323 | 320 | ||
324 | for_each_sg(sg, current_sg, sg_len, i) { | 321 | for_each_sg(sg, current_sg, sg_len, i) { |
325 | total_size += sg_dma_len(current_sg); | 322 | total_size += sg_dma_len(current_sg); |
@@ -351,7 +348,7 @@ int d40_log_sg_to_dev(struct d40_lcla_elem *lcla, | |||
351 | sg_dma_len(current_sg), | 348 | sg_dma_len(current_sg), |
352 | next_lli_off_src, | 349 | next_lli_off_src, |
353 | lcsp->lcsp1, src_data_width, | 350 | lcsp->lcsp1, src_data_width, |
354 | term_int && !next_lli_off_src, | 351 | false, |
355 | true); | 352 | true); |
356 | d40_log_fill_lli(&lli->dst[i], | 353 | d40_log_fill_lli(&lli->dst[i], |
357 | dev_addr, | 354 | dev_addr, |
@@ -375,7 +372,7 @@ int d40_log_sg_to_dev(struct d40_lcla_elem *lcla, | |||
375 | sg_dma_len(current_sg), | 372 | sg_dma_len(current_sg), |
376 | next_lli_off_src, | 373 | next_lli_off_src, |
377 | lcsp->lcsp1, src_data_width, | 374 | lcsp->lcsp1, src_data_width, |
378 | term_int && !next_lli_off_src, | 375 | false, |
379 | false); | 376 | false); |
380 | } | 377 | } |
381 | } | 378 | } |
@@ -423,32 +420,35 @@ int d40_log_sg_to_lli(int lcla_id, | |||
423 | return total_size; | 420 | return total_size; |
424 | } | 421 | } |
425 | 422 | ||
426 | void d40_log_lli_write(struct d40_log_lli_full *lcpa, | 423 | int d40_log_lli_write(struct d40_log_lli_full *lcpa, |
427 | struct d40_log_lli *lcla_src, | 424 | struct d40_log_lli *lcla_src, |
428 | struct d40_log_lli *lcla_dst, | 425 | struct d40_log_lli *lcla_dst, |
429 | struct d40_log_lli *lli_dst, | 426 | struct d40_log_lli *lli_dst, |
430 | struct d40_log_lli *lli_src, | 427 | struct d40_log_lli *lli_src, |
431 | int llis_per_log) | 428 | int llis_per_log) |
432 | { | 429 | { |
433 | u32 slos = 0; | 430 | u32 slos; |
434 | u32 dlos = 0; | 431 | u32 dlos; |
435 | int i; | 432 | int i; |
436 | 433 | ||
437 | lcpa->lcsp0 = lli_src->lcsp02; | 434 | writel(lli_src->lcsp02, &lcpa->lcsp0); |
438 | lcpa->lcsp1 = lli_src->lcsp13; | 435 | writel(lli_src->lcsp13, &lcpa->lcsp1); |
439 | lcpa->lcsp2 = lli_dst->lcsp02; | 436 | writel(lli_dst->lcsp02, &lcpa->lcsp2); |
440 | lcpa->lcsp3 = lli_dst->lcsp13; | 437 | writel(lli_dst->lcsp13, &lcpa->lcsp3); |
441 | 438 | ||
442 | slos = lli_src->lcsp13 & D40_MEM_LCSP1_SLOS_MASK; | 439 | slos = lli_src->lcsp13 & D40_MEM_LCSP1_SLOS_MASK; |
443 | dlos = lli_dst->lcsp13 & D40_MEM_LCSP3_DLOS_MASK; | 440 | dlos = lli_dst->lcsp13 & D40_MEM_LCSP3_DLOS_MASK; |
444 | 441 | ||
445 | for (i = 0; (i < llis_per_log) && slos && dlos; i++) { | 442 | for (i = 0; (i < llis_per_log) && slos && dlos; i++) { |
446 | writel(lli_src[i+1].lcsp02, &lcla_src[i].lcsp02); | 443 | writel(lli_src[i + 1].lcsp02, &lcla_src[i].lcsp02); |
447 | writel(lli_src[i+1].lcsp13, &lcla_src[i].lcsp13); | 444 | writel(lli_src[i + 1].lcsp13, &lcla_src[i].lcsp13); |
448 | writel(lli_dst[i+1].lcsp02, &lcla_dst[i].lcsp02); | 445 | writel(lli_dst[i + 1].lcsp02, &lcla_dst[i].lcsp02); |
449 | writel(lli_dst[i+1].lcsp13, &lcla_dst[i].lcsp13); | 446 | writel(lli_dst[i + 1].lcsp13, &lcla_dst[i].lcsp13); |
450 | 447 | ||
451 | slos = lli_src[i+1].lcsp13 & D40_MEM_LCSP1_SLOS_MASK; | 448 | slos = lli_src[i + 1].lcsp13 & D40_MEM_LCSP1_SLOS_MASK; |
452 | dlos = lli_dst[i+1].lcsp13 & D40_MEM_LCSP3_DLOS_MASK; | 449 | dlos = lli_dst[i + 1].lcsp13 & D40_MEM_LCSP3_DLOS_MASK; |
453 | } | 450 | } |
451 | |||
452 | return i; | ||
453 | |||
454 | } | 454 | } |
diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index 2029280cb332..9c0fa2f5fe57 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h | |||
@@ -13,6 +13,9 @@ | |||
13 | #define D40_DREG_PCDELTA (8 * 4) | 13 | #define D40_DREG_PCDELTA (8 * 4) |
14 | #define D40_LLI_ALIGN 16 /* LLI alignment must be 16 bytes. */ | 14 | #define D40_LLI_ALIGN 16 /* LLI alignment must be 16 bytes. */ |
15 | 15 | ||
16 | #define D40_LCPA_CHAN_SIZE 32 | ||
17 | #define D40_LCPA_CHAN_DST_DELTA 16 | ||
18 | |||
16 | #define D40_TYPE_TO_GROUP(type) (type / 16) | 19 | #define D40_TYPE_TO_GROUP(type) (type / 16) |
17 | #define D40_TYPE_TO_EVENT(type) (type % 16) | 20 | #define D40_TYPE_TO_EVENT(type) (type % 16) |
18 | 21 | ||
@@ -336,12 +339,12 @@ int d40_log_sg_to_dev(struct d40_lcla_elem *lcla, | |||
336 | bool term_int, dma_addr_t dev_addr, int max_len, | 339 | bool term_int, dma_addr_t dev_addr, int max_len, |
337 | int llis_per_log); | 340 | int llis_per_log); |
338 | 341 | ||
339 | void d40_log_lli_write(struct d40_log_lli_full *lcpa, | 342 | int d40_log_lli_write(struct d40_log_lli_full *lcpa, |
340 | struct d40_log_lli *lcla_src, | 343 | struct d40_log_lli *lcla_src, |
341 | struct d40_log_lli *lcla_dst, | 344 | struct d40_log_lli *lcla_dst, |
342 | struct d40_log_lli *lli_dst, | 345 | struct d40_log_lli *lli_dst, |
343 | struct d40_log_lli *lli_src, | 346 | struct d40_log_lli *lli_src, |
344 | int llis_per_log); | 347 | int llis_per_log); |
345 | 348 | ||
346 | int d40_log_sg_to_lli(int lcla_id, | 349 | int d40_log_sg_to_lli(int lcla_id, |
347 | struct scatterlist *sg, | 350 | struct scatterlist *sg, |
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c index a1bf77c1993f..2ec1ed56f204 100644 --- a/drivers/dma/timb_dma.c +++ b/drivers/dma/timb_dma.c | |||
@@ -200,8 +200,8 @@ static int td_fill_desc(struct timb_dma_chan *td_chan, u8 *dma_desc, | |||
200 | return -EINVAL; | 200 | return -EINVAL; |
201 | } | 201 | } |
202 | 202 | ||
203 | dev_dbg(chan2dev(&td_chan->chan), "desc: %p, addr: %p\n", | 203 | dev_dbg(chan2dev(&td_chan->chan), "desc: %p, addr: 0x%llx\n", |
204 | dma_desc, (void *)sg_dma_address(sg)); | 204 | dma_desc, (unsigned long long)sg_dma_address(sg)); |
205 | 205 | ||
206 | dma_desc[7] = (sg_dma_address(sg) >> 24) & 0xff; | 206 | dma_desc[7] = (sg_dma_address(sg) >> 24) & 0xff; |
207 | dma_desc[6] = (sg_dma_address(sg) >> 16) & 0xff; | 207 | dma_desc[6] = (sg_dma_address(sg) >> 16) & 0xff; |
@@ -382,7 +382,7 @@ static struct timb_dma_desc *td_alloc_init_desc(struct timb_dma_chan *td_chan) | |||
382 | td_desc = kzalloc(sizeof(struct timb_dma_desc), GFP_KERNEL); | 382 | td_desc = kzalloc(sizeof(struct timb_dma_desc), GFP_KERNEL); |
383 | if (!td_desc) { | 383 | if (!td_desc) { |
384 | dev_err(chan2dev(chan), "Failed to alloc descriptor\n"); | 384 | dev_err(chan2dev(chan), "Failed to alloc descriptor\n"); |
385 | goto err; | 385 | goto out; |
386 | } | 386 | } |
387 | 387 | ||
388 | td_desc->desc_list_len = td_chan->desc_elems * TIMB_DMA_DESC_SIZE; | 388 | td_desc->desc_list_len = td_chan->desc_elems * TIMB_DMA_DESC_SIZE; |
@@ -410,7 +410,7 @@ static struct timb_dma_desc *td_alloc_init_desc(struct timb_dma_chan *td_chan) | |||
410 | err: | 410 | err: |
411 | kfree(td_desc->desc_list); | 411 | kfree(td_desc->desc_list); |
412 | kfree(td_desc); | 412 | kfree(td_desc); |
413 | 413 | out: | |
414 | return NULL; | 414 | return NULL; |
415 | 415 | ||
416 | } | 416 | } |
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index 110e24e50883..f287fe79edc4 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c | |||
@@ -744,7 +744,7 @@ static inline int edd_num_devices(void) | |||
744 | static int __init | 744 | static int __init |
745 | edd_init(void) | 745 | edd_init(void) |
746 | { | 746 | { |
747 | unsigned int i; | 747 | int i; |
748 | int rc=0; | 748 | int rc=0; |
749 | struct edd_device *edev; | 749 | struct edd_device *edev; |
750 | 750 | ||
@@ -760,21 +760,27 @@ edd_init(void) | |||
760 | if (!edd_kset) | 760 | if (!edd_kset) |
761 | return -ENOMEM; | 761 | return -ENOMEM; |
762 | 762 | ||
763 | for (i = 0; i < edd_num_devices() && !rc; i++) { | 763 | for (i = 0; i < edd_num_devices(); i++) { |
764 | edev = kzalloc(sizeof (*edev), GFP_KERNEL); | 764 | edev = kzalloc(sizeof (*edev), GFP_KERNEL); |
765 | if (!edev) | 765 | if (!edev) { |
766 | return -ENOMEM; | 766 | rc = -ENOMEM; |
767 | goto out; | ||
768 | } | ||
767 | 769 | ||
768 | rc = edd_device_register(edev, i); | 770 | rc = edd_device_register(edev, i); |
769 | if (rc) { | 771 | if (rc) { |
770 | kfree(edev); | 772 | kfree(edev); |
771 | break; | 773 | goto out; |
772 | } | 774 | } |
773 | edd_devices[i] = edev; | 775 | edd_devices[i] = edev; |
774 | } | 776 | } |
775 | 777 | ||
776 | if (rc) | 778 | return 0; |
777 | kset_unregister(edd_kset); | 779 | |
780 | out: | ||
781 | while (--i >= 0) | ||
782 | edd_device_unregister(edd_devices[i]); | ||
783 | kset_unregister(edd_kset); | ||
778 | return rc; | 784 | return rc; |
779 | } | 785 | } |
780 | 786 | ||
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 45981304feb8..b9e4dbfa0533 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -839,7 +839,6 @@ static void output_poll_execute(struct work_struct *work) | |||
839 | struct drm_connector *connector; | 839 | struct drm_connector *connector; |
840 | enum drm_connector_status old_status, status; | 840 | enum drm_connector_status old_status, status; |
841 | bool repoll = false, changed = false; | 841 | bool repoll = false, changed = false; |
842 | int ret; | ||
843 | 842 | ||
844 | mutex_lock(&dev->mode_config.mutex); | 843 | mutex_lock(&dev->mode_config.mutex); |
845 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 844 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
@@ -874,11 +873,8 @@ static void output_poll_execute(struct work_struct *work) | |||
874 | dev->mode_config.funcs->output_poll_changed(dev); | 873 | dev->mode_config.funcs->output_poll_changed(dev); |
875 | } | 874 | } |
876 | 875 | ||
877 | if (repoll) { | 876 | if (repoll) |
878 | ret = queue_delayed_work(system_nrt_wq, delayed_work, DRM_OUTPUT_POLL_PERIOD); | 877 | queue_delayed_work(system_nrt_wq, delayed_work, DRM_OUTPUT_POLL_PERIOD); |
879 | if (ret) | ||
880 | DRM_ERROR("delayed enqueue failed %d\n", ret); | ||
881 | } | ||
882 | } | 878 | } |
883 | 879 | ||
884 | void drm_kms_helper_poll_disable(struct drm_device *dev) | 880 | void drm_kms_helper_poll_disable(struct drm_device *dev) |
@@ -893,18 +889,14 @@ void drm_kms_helper_poll_enable(struct drm_device *dev) | |||
893 | { | 889 | { |
894 | bool poll = false; | 890 | bool poll = false; |
895 | struct drm_connector *connector; | 891 | struct drm_connector *connector; |
896 | int ret; | ||
897 | 892 | ||
898 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 893 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
899 | if (connector->polled) | 894 | if (connector->polled) |
900 | poll = true; | 895 | poll = true; |
901 | } | 896 | } |
902 | 897 | ||
903 | if (poll) { | 898 | if (poll) |
904 | ret = queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); | 899 | queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); |
905 | if (ret) | ||
906 | DRM_ERROR("delayed enqueue failed %d\n", ret); | ||
907 | } | ||
908 | } | 900 | } |
909 | EXPORT_SYMBOL(drm_kms_helper_poll_enable); | 901 | EXPORT_SYMBOL(drm_kms_helper_poll_enable); |
910 | 902 | ||
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 54acd8b534df..a79525f434a8 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
@@ -130,7 +130,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
130 | 130 | ||
131 | strcpy(info->fix.id, "inteldrmfb"); | 131 | strcpy(info->fix.id, "inteldrmfb"); |
132 | 132 | ||
133 | info->flags = FBINFO_DEFAULT; | 133 | info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; |
134 | info->fbops = &intelfb_ops; | 134 | info->fbops = &intelfb_ops; |
135 | 135 | ||
136 | /* setup aperture base/size for vesafb takeover */ | 136 | /* setup aperture base/size for vesafb takeover */ |
@@ -148,8 +148,6 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
148 | info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; | 148 | info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; |
149 | info->fix.smem_len = size; | 149 | info->fix.smem_len = size; |
150 | 150 | ||
151 | info->flags = FBINFO_DEFAULT; | ||
152 | |||
153 | info->screen_base = ioremap_wc(dev->agp->base + obj_priv->gtt_offset, | 151 | info->screen_base = ioremap_wc(dev->agp->base + obj_priv->gtt_offset, |
154 | size); | 152 | size); |
155 | if (!info->screen_base) { | 153 | if (!info->screen_base) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 2fb2444d2322..099f637264aa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -250,6 +250,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
250 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | | 250 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | |
251 | FBINFO_HWACCEL_FILLRECT | | 251 | FBINFO_HWACCEL_FILLRECT | |
252 | FBINFO_HWACCEL_IMAGEBLIT; | 252 | FBINFO_HWACCEL_IMAGEBLIT; |
253 | info->flags |= FBINFO_CAN_FORCE_OUTPUT; | ||
253 | info->fbops = &nouveau_fbcon_ops; | 254 | info->fbops = &nouveau_fbcon_ops; |
254 | info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - | 255 | info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - |
255 | dev_priv->vm_vram_base; | 256 | dev_priv->vm_vram_base; |
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index dc1634bb0c11..dbf86962bdd1 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
@@ -224,7 +224,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, | |||
224 | 224 | ||
225 | drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); | 225 | drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); |
226 | 226 | ||
227 | info->flags = FBINFO_DEFAULT; | 227 | info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; |
228 | info->fbops = &radeonfb_ops; | 228 | info->fbops = &radeonfb_ops; |
229 | 229 | ||
230 | tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start; | 230 | tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start; |
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 807dcd1555a6..724f46ed612f 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c | |||
@@ -230,7 +230,7 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
230 | input_report_key(input, BTN_RIGHT, 0); | 230 | input_report_key(input, BTN_RIGHT, 0); |
231 | input_report_key(input, BTN_MIDDLE, 0); | 231 | input_report_key(input, BTN_MIDDLE, 0); |
232 | input_report_abs(input, ABS_DISTANCE, | 232 | input_report_abs(input, ABS_DISTANCE, |
233 | input->absmax[ABS_DISTANCE]); | 233 | input_abs_get_max(input, ABS_DISTANCE)); |
234 | } else { | 234 | } else { |
235 | input_report_key(input, BTN_TOUCH, 0); | 235 | input_report_key(input, BTN_TOUCH, 0); |
236 | input_report_key(input, BTN_STYLUS, 0); | 236 | input_report_key(input, BTN_STYLUS, 0); |
@@ -383,38 +383,37 @@ move_on: | |||
383 | 383 | ||
384 | /* Basics */ | 384 | /* Basics */ |
385 | input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); | 385 | input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); |
386 | input->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | | 386 | |
387 | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE); | 387 | __set_bit(REL_WHEEL, input->relbit); |
388 | input->relbit[0] |= BIT(REL_WHEEL); | 388 | |
389 | set_bit(BTN_TOOL_PEN, input->keybit); | 389 | __set_bit(BTN_TOOL_PEN, input->keybit); |
390 | set_bit(BTN_TOUCH, input->keybit); | 390 | __set_bit(BTN_TOUCH, input->keybit); |
391 | set_bit(BTN_STYLUS, input->keybit); | 391 | __set_bit(BTN_STYLUS, input->keybit); |
392 | set_bit(BTN_STYLUS2, input->keybit); | 392 | __set_bit(BTN_STYLUS2, input->keybit); |
393 | set_bit(BTN_LEFT, input->keybit); | 393 | __set_bit(BTN_LEFT, input->keybit); |
394 | set_bit(BTN_RIGHT, input->keybit); | 394 | __set_bit(BTN_RIGHT, input->keybit); |
395 | set_bit(BTN_MIDDLE, input->keybit); | 395 | __set_bit(BTN_MIDDLE, input->keybit); |
396 | 396 | ||
397 | /* Pad */ | 397 | /* Pad */ |
398 | input->evbit[0] |= BIT(EV_MSC); | 398 | input->evbit[0] |= BIT(EV_MSC); |
399 | input->mscbit[0] |= BIT(MSC_SERIAL); | ||
400 | set_bit(BTN_0, input->keybit); | ||
401 | set_bit(BTN_1, input->keybit); | ||
402 | set_bit(BTN_TOOL_FINGER, input->keybit); | ||
403 | 399 | ||
404 | /* Distance, rubber and mouse */ | 400 | __set_bit(MSC_SERIAL, input->mscbit); |
405 | input->absbit[0] |= BIT(ABS_DISTANCE); | ||
406 | set_bit(BTN_TOOL_RUBBER, input->keybit); | ||
407 | set_bit(BTN_TOOL_MOUSE, input->keybit); | ||
408 | 401 | ||
409 | input->absmax[ABS_PRESSURE] = 511; | 402 | __set_bit(BTN_0, input->keybit); |
410 | input->absmax[ABS_DISTANCE] = 32; | 403 | __set_bit(BTN_1, input->keybit); |
404 | __set_bit(BTN_TOOL_FINGER, input->keybit); | ||
411 | 405 | ||
412 | input->absmax[ABS_X] = 16704; | 406 | /* Distance, rubber and mouse */ |
413 | input->absmax[ABS_Y] = 12064; | 407 | __set_bit(BTN_TOOL_RUBBER, input->keybit); |
414 | input->absfuzz[ABS_X] = 4; | 408 | __set_bit(BTN_TOOL_MOUSE, input->keybit); |
415 | input->absfuzz[ABS_Y] = 4; | 409 | |
410 | input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); | ||
411 | input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); | ||
412 | input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); | ||
413 | input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); | ||
416 | 414 | ||
417 | return 0; | 415 | return 0; |
416 | |||
418 | err_free: | 417 | err_free: |
419 | kfree(wdata); | 418 | kfree(wdata); |
420 | return ret; | 419 | return ret; |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 4d382ae53092..f3adf18bfa05 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -332,11 +332,11 @@ config SENSORS_F71805F | |||
332 | will be called f71805f. | 332 | will be called f71805f. |
333 | 333 | ||
334 | config SENSORS_F71882FG | 334 | config SENSORS_F71882FG |
335 | tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000" | 335 | tristate "Fintek F71808E, F71858FG, F71862FG, F71882FG, F71889FG and F8000" |
336 | depends on EXPERIMENTAL | 336 | depends on EXPERIMENTAL |
337 | help | 337 | help |
338 | If you say yes here you get support for hardware monitoring | 338 | If you say yes here you get support for hardware monitoring features |
339 | features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG, | 339 | of the Fintek F71808E, F71858FG, F71862FG/71863FG, F71882FG/F71883FG, |
340 | F71889FG and F8000 Super-I/O chips. | 340 | F71889FG and F8000 Super-I/O chips. |
341 | 341 | ||
342 | This driver can also be built as a module. If so, the module | 342 | This driver can also be built as a module. If so, the module |
@@ -405,7 +405,7 @@ config SENSORS_CORETEMP | |||
405 | help | 405 | help |
406 | If you say yes here you get support for the temperature | 406 | If you say yes here you get support for the temperature |
407 | sensor inside your CPU. Most of the family 6 CPUs | 407 | sensor inside your CPU. Most of the family 6 CPUs |
408 | are supported. Check documentation/driver for details. | 408 | are supported. Check Documentation/hwmon/coretemp for details. |
409 | 409 | ||
410 | config SENSORS_PKGTEMP | 410 | config SENSORS_PKGTEMP |
411 | tristate "Intel processor package temperature sensor" | 411 | tristate "Intel processor package temperature sensor" |
@@ -463,6 +463,17 @@ config SENSORS_JZ4740 | |||
463 | This driver can also be build as a module. If so, the module will be | 463 | This driver can also be build as a module. If so, the module will be |
464 | called jz4740-hwmon. | 464 | called jz4740-hwmon. |
465 | 465 | ||
466 | config SENSORS_JC42 | ||
467 | tristate "JEDEC JC42.4 compliant temperature sensors" | ||
468 | help | ||
469 | If you say yes here you get support for Jedec JC42.4 compliant | ||
470 | temperature sensors. Support will include, but not be limited to, | ||
471 | ADT7408, CAT34TS02,, CAT6095, MAX6604, MCP9805, MCP98242, MCP98243, | ||
472 | MCP9843, SE97, SE98, STTS424, TSE2002B3, and TS3000B3. | ||
473 | |||
474 | This driver can also be built as a module. If so, the module | ||
475 | will be called jc42. | ||
476 | |||
466 | config SENSORS_LM63 | 477 | config SENSORS_LM63 |
467 | tristate "National Semiconductor LM63 and LM64" | 478 | tristate "National Semiconductor LM63 and LM64" |
468 | depends on I2C | 479 | depends on I2C |
@@ -756,6 +767,21 @@ config SENSORS_SIS5595 | |||
756 | This driver can also be built as a module. If so, the module | 767 | This driver can also be built as a module. If so, the module |
757 | will be called sis5595. | 768 | will be called sis5595. |
758 | 769 | ||
770 | config SENSORS_SMM665 | ||
771 | tristate "Summit Microelectronics SMM665" | ||
772 | depends on I2C && EXPERIMENTAL | ||
773 | default n | ||
774 | help | ||
775 | If you say yes here you get support for the hardware monitoring | ||
776 | features of the Summit Microelectronics SMM665/SMM665B Six-Channel | ||
777 | Active DC Output Controller / Monitor. | ||
778 | |||
779 | Other supported chips are SMM465, SMM665C, SMM764, and SMM766. | ||
780 | Support for those chips is untested. | ||
781 | |||
782 | This driver can also be built as a module. If so, the module will | ||
783 | be called smm665. | ||
784 | |||
759 | config SENSORS_DME1737 | 785 | config SENSORS_DME1737 |
760 | tristate "SMSC DME1737, SCH311x and compatibles" | 786 | tristate "SMSC DME1737, SCH311x and compatibles" |
761 | depends on I2C && EXPERIMENTAL | 787 | depends on I2C && EXPERIMENTAL |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 9103bd6ea73a..13d913e34dbf 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -56,6 +56,7 @@ obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o | |||
56 | obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o | 56 | obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o |
57 | obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o | 57 | obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o |
58 | obj-$(CONFIG_SENSORS_IT87) += it87.o | 58 | obj-$(CONFIG_SENSORS_IT87) += it87.o |
59 | obj-$(CONFIG_SENSORS_JC42) += jc42.o | ||
59 | obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o | 60 | obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o |
60 | obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o | 61 | obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o |
61 | obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o | 62 | obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o |
@@ -88,6 +89,7 @@ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o | |||
88 | obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o | 89 | obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o |
89 | obj-$(CONFIG_SENSORS_SHT15) += sht15.o | 90 | obj-$(CONFIG_SENSORS_SHT15) += sht15.o |
90 | obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o | 91 | obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o |
92 | obj-$(CONFIG_SENSORS_SMM665) += smm665.o | ||
91 | obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o | 93 | obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o |
92 | obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o | 94 | obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o |
93 | obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o | 95 | obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o |
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 05344af50734..a92e28a35767 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -480,7 +480,6 @@ exit: | |||
480 | return err; | 480 | return err; |
481 | } | 481 | } |
482 | 482 | ||
483 | #ifdef CONFIG_HOTPLUG_CPU | ||
484 | static void coretemp_device_remove(unsigned int cpu) | 483 | static void coretemp_device_remove(unsigned int cpu) |
485 | { | 484 | { |
486 | struct pdev_entry *p, *n; | 485 | struct pdev_entry *p, *n; |
@@ -502,10 +501,13 @@ static int __cpuinit coretemp_cpu_callback(struct notifier_block *nfb, | |||
502 | 501 | ||
503 | switch (action) { | 502 | switch (action) { |
504 | case CPU_ONLINE: | 503 | case CPU_ONLINE: |
504 | case CPU_ONLINE_FROZEN: | ||
505 | case CPU_DOWN_FAILED: | 505 | case CPU_DOWN_FAILED: |
506 | case CPU_DOWN_FAILED_FROZEN: | ||
506 | coretemp_device_add(cpu); | 507 | coretemp_device_add(cpu); |
507 | break; | 508 | break; |
508 | case CPU_DOWN_PREPARE: | 509 | case CPU_DOWN_PREPARE: |
510 | case CPU_DOWN_PREPARE_FROZEN: | ||
509 | coretemp_device_remove(cpu); | 511 | coretemp_device_remove(cpu); |
510 | break; | 512 | break; |
511 | } | 513 | } |
@@ -515,7 +517,6 @@ static int __cpuinit coretemp_cpu_callback(struct notifier_block *nfb, | |||
515 | static struct notifier_block coretemp_cpu_notifier __refdata = { | 517 | static struct notifier_block coretemp_cpu_notifier __refdata = { |
516 | .notifier_call = coretemp_cpu_callback, | 518 | .notifier_call = coretemp_cpu_callback, |
517 | }; | 519 | }; |
518 | #endif /* !CONFIG_HOTPLUG_CPU */ | ||
519 | 520 | ||
520 | static int __init coretemp_init(void) | 521 | static int __init coretemp_init(void) |
521 | { | 522 | { |
@@ -537,12 +538,9 @@ static int __init coretemp_init(void) | |||
537 | * sensors. We check this bit only, all the early CPUs | 538 | * sensors. We check this bit only, all the early CPUs |
538 | * without thermal sensors will be filtered out. | 539 | * without thermal sensors will be filtered out. |
539 | */ | 540 | */ |
540 | if (c->cpuid_level >= 6 && (cpuid_eax(0x06) & 0x01)) { | 541 | if (c->cpuid_level >= 6 && (cpuid_eax(0x06) & 0x01)) |
541 | err = coretemp_device_add(i); | 542 | coretemp_device_add(i); |
542 | if (err) | 543 | else { |
543 | goto exit_devices_unreg; | ||
544 | |||
545 | } else { | ||
546 | printk(KERN_INFO DRVNAME ": CPU (model=0x%x)" | 544 | printk(KERN_INFO DRVNAME ": CPU (model=0x%x)" |
547 | " has no thermal sensor.\n", c->x86_model); | 545 | " has no thermal sensor.\n", c->x86_model); |
548 | } | 546 | } |
@@ -552,21 +550,13 @@ static int __init coretemp_init(void) | |||
552 | goto exit_driver_unreg; | 550 | goto exit_driver_unreg; |
553 | } | 551 | } |
554 | 552 | ||
555 | #ifdef CONFIG_HOTPLUG_CPU | ||
556 | register_hotcpu_notifier(&coretemp_cpu_notifier); | 553 | register_hotcpu_notifier(&coretemp_cpu_notifier); |
557 | #endif | ||
558 | return 0; | 554 | return 0; |
559 | 555 | ||
560 | exit_devices_unreg: | ||
561 | mutex_lock(&pdev_list_mutex); | ||
562 | list_for_each_entry_safe(p, n, &pdev_list, list) { | ||
563 | platform_device_unregister(p->pdev); | ||
564 | list_del(&p->list); | ||
565 | kfree(p); | ||
566 | } | ||
567 | mutex_unlock(&pdev_list_mutex); | ||
568 | exit_driver_unreg: | 556 | exit_driver_unreg: |
557 | #ifndef CONFIG_HOTPLUG_CPU | ||
569 | platform_driver_unregister(&coretemp_driver); | 558 | platform_driver_unregister(&coretemp_driver); |
559 | #endif | ||
570 | exit: | 560 | exit: |
571 | return err; | 561 | return err; |
572 | } | 562 | } |
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 537841ef44b9..6207120dcd4d 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ | 45 | #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ |
46 | 46 | ||
47 | #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ | 47 | #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ |
48 | #define SIO_F71808_ID 0x0901 /* Chipset ID */ | ||
48 | #define SIO_F71858_ID 0x0507 /* Chipset ID */ | 49 | #define SIO_F71858_ID 0x0507 /* Chipset ID */ |
49 | #define SIO_F71862_ID 0x0601 /* Chipset ID */ | 50 | #define SIO_F71862_ID 0x0601 /* Chipset ID */ |
50 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ | 51 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ |
@@ -96,9 +97,10 @@ static unsigned short force_id; | |||
96 | module_param(force_id, ushort, 0); | 97 | module_param(force_id, ushort, 0); |
97 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); | 98 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); |
98 | 99 | ||
99 | enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; | 100 | enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; |
100 | 101 | ||
101 | static const char *f71882fg_names[] = { | 102 | static const char *f71882fg_names[] = { |
103 | "f71808fg", | ||
102 | "f71858fg", | 104 | "f71858fg", |
103 | "f71862fg", | 105 | "f71862fg", |
104 | "f71882fg", | 106 | "f71882fg", |
@@ -306,8 +308,8 @@ static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = { | |||
306 | SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), | 308 | SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), |
307 | }; | 309 | }; |
308 | 310 | ||
309 | /* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ | 311 | /* In attr common to the f71862fg, f71882fg and f71889fg */ |
310 | static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { | 312 | static struct sensor_device_attribute_2 fxxxx_in_attr[] = { |
311 | SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), | 313 | SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), |
312 | SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), | 314 | SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), |
313 | SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), | 315 | SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), |
@@ -317,6 +319,22 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { | |||
317 | SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), | 319 | SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), |
318 | SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), | 320 | SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), |
319 | SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), | 321 | SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), |
322 | }; | ||
323 | |||
324 | /* In attr for the f71808fg */ | ||
325 | static struct sensor_device_attribute_2 f71808_in_attr[] = { | ||
326 | SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), | ||
327 | SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), | ||
328 | SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), | ||
329 | SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), | ||
330 | SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), | ||
331 | SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5), | ||
332 | SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 7), | ||
333 | SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 8), | ||
334 | }; | ||
335 | |||
336 | /* Temp attr common to the f71808fg, f71862fg, f71882fg and f71889fg */ | ||
337 | static struct sensor_device_attribute_2 fxxxx_temp_attr[] = { | ||
320 | SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), | 338 | SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), |
321 | SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, | 339 | SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, |
322 | store_temp_max, 0, 1), | 340 | store_temp_max, 0, 1), |
@@ -355,6 +373,10 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { | |||
355 | store_temp_beep, 0, 6), | 373 | store_temp_beep, 0, 6), |
356 | SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), | 374 | SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), |
357 | SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), | 375 | SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), |
376 | }; | ||
377 | |||
378 | /* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ | ||
379 | static struct sensor_device_attribute_2 f71862_temp_attr[] = { | ||
358 | SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), | 380 | SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), |
359 | SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, | 381 | SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, |
360 | store_temp_max, 0, 3), | 382 | store_temp_max, 0, 3), |
@@ -989,6 +1011,11 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) | |||
989 | data->temp_type[1] = 6; | 1011 | data->temp_type[1] = 6; |
990 | break; | 1012 | break; |
991 | } | 1013 | } |
1014 | } else if (data->type == f71808fg) { | ||
1015 | reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); | ||
1016 | data->temp_type[1] = (reg & 0x02) ? 2 : 4; | ||
1017 | data->temp_type[2] = (reg & 0x04) ? 2 : 4; | ||
1018 | |||
992 | } else { | 1019 | } else { |
993 | reg2 = f71882fg_read8(data, F71882FG_REG_PECI); | 1020 | reg2 = f71882fg_read8(data, F71882FG_REG_PECI); |
994 | if ((reg2 & 0x03) == 0x01) | 1021 | if ((reg2 & 0x03) == 0x01) |
@@ -1871,7 +1898,8 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, | |||
1871 | 1898 | ||
1872 | val /= 1000; | 1899 | val /= 1000; |
1873 | 1900 | ||
1874 | if (data->type == f71889fg) | 1901 | if (data->type == f71889fg |
1902 | || data->type == f71808fg) | ||
1875 | val = SENSORS_LIMIT(val, -128, 127); | 1903 | val = SENSORS_LIMIT(val, -128, 127); |
1876 | else | 1904 | else |
1877 | val = SENSORS_LIMIT(val, 0, 127); | 1905 | val = SENSORS_LIMIT(val, 0, 127); |
@@ -1974,8 +2002,28 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) | |||
1974 | /* fall through! */ | 2002 | /* fall through! */ |
1975 | case f71862fg: | 2003 | case f71862fg: |
1976 | err = f71882fg_create_sysfs_files(pdev, | 2004 | err = f71882fg_create_sysfs_files(pdev, |
1977 | fxxxx_in_temp_attr, | 2005 | f71862_temp_attr, |
1978 | ARRAY_SIZE(fxxxx_in_temp_attr)); | 2006 | ARRAY_SIZE(f71862_temp_attr)); |
2007 | if (err) | ||
2008 | goto exit_unregister_sysfs; | ||
2009 | err = f71882fg_create_sysfs_files(pdev, | ||
2010 | fxxxx_in_attr, | ||
2011 | ARRAY_SIZE(fxxxx_in_attr)); | ||
2012 | if (err) | ||
2013 | goto exit_unregister_sysfs; | ||
2014 | err = f71882fg_create_sysfs_files(pdev, | ||
2015 | fxxxx_temp_attr, | ||
2016 | ARRAY_SIZE(fxxxx_temp_attr)); | ||
2017 | break; | ||
2018 | case f71808fg: | ||
2019 | err = f71882fg_create_sysfs_files(pdev, | ||
2020 | f71808_in_attr, | ||
2021 | ARRAY_SIZE(f71808_in_attr)); | ||
2022 | if (err) | ||
2023 | goto exit_unregister_sysfs; | ||
2024 | err = f71882fg_create_sysfs_files(pdev, | ||
2025 | fxxxx_temp_attr, | ||
2026 | ARRAY_SIZE(fxxxx_temp_attr)); | ||
1979 | break; | 2027 | break; |
1980 | case f8000: | 2028 | case f8000: |
1981 | err = f71882fg_create_sysfs_files(pdev, | 2029 | err = f71882fg_create_sysfs_files(pdev, |
@@ -2002,6 +2050,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) | |||
2002 | case f71862fg: | 2050 | case f71862fg: |
2003 | err = (data->pwm_enable & 0x15) != 0x15; | 2051 | err = (data->pwm_enable & 0x15) != 0x15; |
2004 | break; | 2052 | break; |
2053 | case f71808fg: | ||
2005 | case f71882fg: | 2054 | case f71882fg: |
2006 | case f71889fg: | 2055 | case f71889fg: |
2007 | err = 0; | 2056 | err = 0; |
@@ -2047,6 +2096,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) | |||
2047 | f8000_auto_pwm_attr, | 2096 | f8000_auto_pwm_attr, |
2048 | ARRAY_SIZE(f8000_auto_pwm_attr)); | 2097 | ARRAY_SIZE(f8000_auto_pwm_attr)); |
2049 | break; | 2098 | break; |
2099 | case f71808fg: | ||
2050 | case f71889fg: | 2100 | case f71889fg: |
2051 | for (i = 0; i < nr_fans; i++) { | 2101 | for (i = 0; i < nr_fans; i++) { |
2052 | data->pwm_auto_point_mapping[i] = | 2102 | data->pwm_auto_point_mapping[i] = |
@@ -2126,8 +2176,22 @@ static int f71882fg_remove(struct platform_device *pdev) | |||
2126 | /* fall through! */ | 2176 | /* fall through! */ |
2127 | case f71862fg: | 2177 | case f71862fg: |
2128 | f71882fg_remove_sysfs_files(pdev, | 2178 | f71882fg_remove_sysfs_files(pdev, |
2129 | fxxxx_in_temp_attr, | 2179 | f71862_temp_attr, |
2130 | ARRAY_SIZE(fxxxx_in_temp_attr)); | 2180 | ARRAY_SIZE(f71862_temp_attr)); |
2181 | f71882fg_remove_sysfs_files(pdev, | ||
2182 | fxxxx_in_attr, | ||
2183 | ARRAY_SIZE(fxxxx_in_attr)); | ||
2184 | f71882fg_remove_sysfs_files(pdev, | ||
2185 | fxxxx_temp_attr, | ||
2186 | ARRAY_SIZE(fxxxx_temp_attr)); | ||
2187 | break; | ||
2188 | case f71808fg: | ||
2189 | f71882fg_remove_sysfs_files(pdev, | ||
2190 | f71808_in_attr, | ||
2191 | ARRAY_SIZE(f71808_in_attr)); | ||
2192 | f71882fg_remove_sysfs_files(pdev, | ||
2193 | fxxxx_temp_attr, | ||
2194 | ARRAY_SIZE(fxxxx_temp_attr)); | ||
2131 | break; | 2195 | break; |
2132 | case f8000: | 2196 | case f8000: |
2133 | f71882fg_remove_sysfs_files(pdev, | 2197 | f71882fg_remove_sysfs_files(pdev, |
@@ -2195,6 +2259,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, | |||
2195 | 2259 | ||
2196 | devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); | 2260 | devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); |
2197 | switch (devid) { | 2261 | switch (devid) { |
2262 | case SIO_F71808_ID: | ||
2263 | sio_data->type = f71808fg; | ||
2264 | break; | ||
2198 | case SIO_F71858_ID: | 2265 | case SIO_F71858_ID: |
2199 | sio_data->type = f71858fg; | 2266 | sio_data->type = f71858fg; |
2200 | break; | 2267 | break; |
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index be2d131e405c..bfd42f18924b 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c | |||
@@ -522,6 +522,7 @@ static struct dmi_system_id __initdata hdaps_whitelist[] = { | |||
522 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p", HDAPS_BOTH_AXES), | 522 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p", HDAPS_BOTH_AXES), |
523 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"), | 523 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"), |
524 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"), | 524 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"), |
525 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T400", HDAPS_BOTH_AXES), | ||
525 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60", HDAPS_BOTH_AXES), | 526 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60", HDAPS_BOTH_AXES), |
526 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61p", HDAPS_BOTH_AXES), | 527 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61p", HDAPS_BOTH_AXES), |
527 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61", HDAPS_BOTH_AXES), | 528 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61", HDAPS_BOTH_AXES), |
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c new file mode 100644 index 000000000000..340fc78c8dde --- /dev/null +++ b/drivers/hwmon/jc42.c | |||
@@ -0,0 +1,593 @@ | |||
1 | /* | ||
2 | * jc42.c - driver for Jedec JC42.4 compliant temperature sensors | ||
3 | * | ||
4 | * Copyright (c) 2010 Ericsson AB. | ||
5 | * | ||
6 | * Derived from lm77.c by Andras BALI <drewie@freemail.hu>. | ||
7 | * | ||
8 | * JC42.4 compliant temperature sensors are typically used on memory modules. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU 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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/jiffies.h> | ||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/hwmon.h> | ||
31 | #include <linux/hwmon-sysfs.h> | ||
32 | #include <linux/err.h> | ||
33 | #include <linux/mutex.h> | ||
34 | |||
35 | /* Addresses to scan */ | ||
36 | static const unsigned short normal_i2c[] = { | ||
37 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, I2C_CLIENT_END }; | ||
38 | |||
39 | /* JC42 registers. All registers are 16 bit. */ | ||
40 | #define JC42_REG_CAP 0x00 | ||
41 | #define JC42_REG_CONFIG 0x01 | ||
42 | #define JC42_REG_TEMP_UPPER 0x02 | ||
43 | #define JC42_REG_TEMP_LOWER 0x03 | ||
44 | #define JC42_REG_TEMP_CRITICAL 0x04 | ||
45 | #define JC42_REG_TEMP 0x05 | ||
46 | #define JC42_REG_MANID 0x06 | ||
47 | #define JC42_REG_DEVICEID 0x07 | ||
48 | |||
49 | /* Status bits in temperature register */ | ||
50 | #define JC42_ALARM_CRIT_BIT 15 | ||
51 | #define JC42_ALARM_MAX_BIT 14 | ||
52 | #define JC42_ALARM_MIN_BIT 13 | ||
53 | |||
54 | /* Configuration register defines */ | ||
55 | #define JC42_CFG_CRIT_ONLY (1 << 2) | ||
56 | #define JC42_CFG_SHUTDOWN (1 << 8) | ||
57 | #define JC42_CFG_HYST_SHIFT 9 | ||
58 | #define JC42_CFG_HYST_MASK 0x03 | ||
59 | |||
60 | /* Capabilities */ | ||
61 | #define JC42_CAP_RANGE (1 << 2) | ||
62 | |||
63 | /* Manufacturer IDs */ | ||
64 | #define ADT_MANID 0x11d4 /* Analog Devices */ | ||
65 | #define MAX_MANID 0x004d /* Maxim */ | ||
66 | #define IDT_MANID 0x00b3 /* IDT */ | ||
67 | #define MCP_MANID 0x0054 /* Microchip */ | ||
68 | #define NXP_MANID 0x1131 /* NXP Semiconductors */ | ||
69 | #define ONS_MANID 0x1b09 /* ON Semiconductor */ | ||
70 | #define STM_MANID 0x104a /* ST Microelectronics */ | ||
71 | |||
72 | /* Supported chips */ | ||
73 | |||
74 | /* Analog Devices */ | ||
75 | #define ADT7408_DEVID 0x0801 | ||
76 | #define ADT7408_DEVID_MASK 0xffff | ||
77 | |||
78 | /* IDT */ | ||
79 | #define TS3000B3_DEVID 0x2903 /* Also matches TSE2002B3 */ | ||
80 | #define TS3000B3_DEVID_MASK 0xffff | ||
81 | |||
82 | /* Maxim */ | ||
83 | #define MAX6604_DEVID 0x3e00 | ||
84 | #define MAX6604_DEVID_MASK 0xffff | ||
85 | |||
86 | /* Microchip */ | ||
87 | #define MCP98242_DEVID 0x2000 | ||
88 | #define MCP98242_DEVID_MASK 0xfffc | ||
89 | |||
90 | #define MCP98243_DEVID 0x2100 | ||
91 | #define MCP98243_DEVID_MASK 0xfffc | ||
92 | |||
93 | #define MCP9843_DEVID 0x0000 /* Also matches mcp9805 */ | ||
94 | #define MCP9843_DEVID_MASK 0xfffe | ||
95 | |||
96 | /* NXP */ | ||
97 | #define SE97_DEVID 0xa200 | ||
98 | #define SE97_DEVID_MASK 0xfffc | ||
99 | |||
100 | #define SE98_DEVID 0xa100 | ||
101 | #define SE98_DEVID_MASK 0xfffc | ||
102 | |||
103 | /* ON Semiconductor */ | ||
104 | #define CAT6095_DEVID 0x0800 /* Also matches CAT34TS02 */ | ||
105 | #define CAT6095_DEVID_MASK 0xffe0 | ||
106 | |||
107 | /* ST Microelectronics */ | ||
108 | #define STTS424_DEVID 0x0101 | ||
109 | #define STTS424_DEVID_MASK 0xffff | ||
110 | |||
111 | #define STTS424E_DEVID 0x0000 | ||
112 | #define STTS424E_DEVID_MASK 0xfffe | ||
113 | |||
114 | static u16 jc42_hysteresis[] = { 0, 1500, 3000, 6000 }; | ||
115 | |||
116 | struct jc42_chips { | ||
117 | u16 manid; | ||
118 | u16 devid; | ||
119 | u16 devid_mask; | ||
120 | }; | ||
121 | |||
122 | static struct jc42_chips jc42_chips[] = { | ||
123 | { ADT_MANID, ADT7408_DEVID, ADT7408_DEVID_MASK }, | ||
124 | { IDT_MANID, TS3000B3_DEVID, TS3000B3_DEVID_MASK }, | ||
125 | { MAX_MANID, MAX6604_DEVID, MAX6604_DEVID_MASK }, | ||
126 | { MCP_MANID, MCP98242_DEVID, MCP98242_DEVID_MASK }, | ||
127 | { MCP_MANID, MCP98243_DEVID, MCP98243_DEVID_MASK }, | ||
128 | { MCP_MANID, MCP9843_DEVID, MCP9843_DEVID_MASK }, | ||
129 | { NXP_MANID, SE97_DEVID, SE97_DEVID_MASK }, | ||
130 | { ONS_MANID, CAT6095_DEVID, CAT6095_DEVID_MASK }, | ||
131 | { NXP_MANID, SE98_DEVID, SE98_DEVID_MASK }, | ||
132 | { STM_MANID, STTS424_DEVID, STTS424_DEVID_MASK }, | ||
133 | { STM_MANID, STTS424E_DEVID, STTS424E_DEVID_MASK }, | ||
134 | }; | ||
135 | |||
136 | /* Each client has this additional data */ | ||
137 | struct jc42_data { | ||
138 | struct device *hwmon_dev; | ||
139 | struct mutex update_lock; /* protect register access */ | ||
140 | bool extended; /* true if extended range supported */ | ||
141 | bool valid; | ||
142 | unsigned long last_updated; /* In jiffies */ | ||
143 | u16 orig_config; /* original configuration */ | ||
144 | u16 config; /* current configuration */ | ||
145 | u16 temp_input; /* Temperatures */ | ||
146 | u16 temp_crit; | ||
147 | u16 temp_min; | ||
148 | u16 temp_max; | ||
149 | }; | ||
150 | |||
151 | static int jc42_probe(struct i2c_client *client, | ||
152 | const struct i2c_device_id *id); | ||
153 | static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info); | ||
154 | static int jc42_remove(struct i2c_client *client); | ||
155 | static int jc42_read_value(struct i2c_client *client, u8 reg); | ||
156 | static int jc42_write_value(struct i2c_client *client, u8 reg, u16 value); | ||
157 | |||
158 | static struct jc42_data *jc42_update_device(struct device *dev); | ||
159 | |||
160 | static const struct i2c_device_id jc42_id[] = { | ||
161 | { "adt7408", 0 }, | ||
162 | { "cat94ts02", 0 }, | ||
163 | { "cat6095", 0 }, | ||
164 | { "jc42", 0 }, | ||
165 | { "max6604", 0 }, | ||
166 | { "mcp9805", 0 }, | ||
167 | { "mcp98242", 0 }, | ||
168 | { "mcp98243", 0 }, | ||
169 | { "mcp9843", 0 }, | ||
170 | { "se97", 0 }, | ||
171 | { "se97b", 0 }, | ||
172 | { "se98", 0 }, | ||
173 | { "stts424", 0 }, | ||
174 | { "tse2002b3", 0 }, | ||
175 | { "ts3000b3", 0 }, | ||
176 | { } | ||
177 | }; | ||
178 | MODULE_DEVICE_TABLE(i2c, jc42_id); | ||
179 | |||
180 | #ifdef CONFIG_PM | ||
181 | |||
182 | static int jc42_suspend(struct device *dev) | ||
183 | { | ||
184 | struct i2c_client *client = to_i2c_client(dev); | ||
185 | struct jc42_data *data = i2c_get_clientdata(client); | ||
186 | |||
187 | data->config |= JC42_CFG_SHUTDOWN; | ||
188 | jc42_write_value(client, JC42_REG_CONFIG, data->config); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int jc42_resume(struct device *dev) | ||
193 | { | ||
194 | struct i2c_client *client = to_i2c_client(dev); | ||
195 | struct jc42_data *data = i2c_get_clientdata(client); | ||
196 | |||
197 | data->config &= ~JC42_CFG_SHUTDOWN; | ||
198 | jc42_write_value(client, JC42_REG_CONFIG, data->config); | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static const struct dev_pm_ops jc42_dev_pm_ops = { | ||
203 | .suspend = jc42_suspend, | ||
204 | .resume = jc42_resume, | ||
205 | }; | ||
206 | |||
207 | #define JC42_DEV_PM_OPS (&jc42_dev_pm_ops) | ||
208 | #else | ||
209 | #define JC42_DEV_PM_OPS NULL | ||
210 | #endif /* CONFIG_PM */ | ||
211 | |||
212 | /* This is the driver that will be inserted */ | ||
213 | static struct i2c_driver jc42_driver = { | ||
214 | .class = I2C_CLASS_HWMON, | ||
215 | .driver = { | ||
216 | .name = "jc42", | ||
217 | .pm = JC42_DEV_PM_OPS, | ||
218 | }, | ||
219 | .probe = jc42_probe, | ||
220 | .remove = jc42_remove, | ||
221 | .id_table = jc42_id, | ||
222 | .detect = jc42_detect, | ||
223 | .address_list = normal_i2c, | ||
224 | }; | ||
225 | |||
226 | #define JC42_TEMP_MIN_EXTENDED (-40000) | ||
227 | #define JC42_TEMP_MIN 0 | ||
228 | #define JC42_TEMP_MAX 125000 | ||
229 | |||
230 | static u16 jc42_temp_to_reg(int temp, bool extended) | ||
231 | { | ||
232 | int ntemp = SENSORS_LIMIT(temp, | ||
233 | extended ? JC42_TEMP_MIN_EXTENDED : | ||
234 | JC42_TEMP_MIN, JC42_TEMP_MAX); | ||
235 | |||
236 | /* convert from 0.001 to 0.0625 resolution */ | ||
237 | return (ntemp * 2 / 125) & 0x1fff; | ||
238 | } | ||
239 | |||
240 | static int jc42_temp_from_reg(s16 reg) | ||
241 | { | ||
242 | reg &= 0x1fff; | ||
243 | |||
244 | /* sign extend register */ | ||
245 | if (reg & 0x1000) | ||
246 | reg |= 0xf000; | ||
247 | |||
248 | /* convert from 0.0625 to 0.001 resolution */ | ||
249 | return reg * 125 / 2; | ||
250 | } | ||
251 | |||
252 | /* sysfs stuff */ | ||
253 | |||
254 | /* read routines for temperature limits */ | ||
255 | #define show(value) \ | ||
256 | static ssize_t show_##value(struct device *dev, \ | ||
257 | struct device_attribute *attr, \ | ||
258 | char *buf) \ | ||
259 | { \ | ||
260 | struct jc42_data *data = jc42_update_device(dev); \ | ||
261 | if (IS_ERR(data)) \ | ||
262 | return PTR_ERR(data); \ | ||
263 | return sprintf(buf, "%d\n", jc42_temp_from_reg(data->value)); \ | ||
264 | } | ||
265 | |||
266 | show(temp_input); | ||
267 | show(temp_crit); | ||
268 | show(temp_min); | ||
269 | show(temp_max); | ||
270 | |||
271 | /* read routines for hysteresis values */ | ||
272 | static ssize_t show_temp_crit_hyst(struct device *dev, | ||
273 | struct device_attribute *attr, char *buf) | ||
274 | { | ||
275 | struct jc42_data *data = jc42_update_device(dev); | ||
276 | int temp, hyst; | ||
277 | |||
278 | if (IS_ERR(data)) | ||
279 | return PTR_ERR(data); | ||
280 | |||
281 | temp = jc42_temp_from_reg(data->temp_crit); | ||
282 | hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT) | ||
283 | & JC42_CFG_HYST_MASK]; | ||
284 | return sprintf(buf, "%d\n", temp - hyst); | ||
285 | } | ||
286 | |||
287 | static ssize_t show_temp_max_hyst(struct device *dev, | ||
288 | struct device_attribute *attr, char *buf) | ||
289 | { | ||
290 | struct jc42_data *data = jc42_update_device(dev); | ||
291 | int temp, hyst; | ||
292 | |||
293 | if (IS_ERR(data)) | ||
294 | return PTR_ERR(data); | ||
295 | |||
296 | temp = jc42_temp_from_reg(data->temp_max); | ||
297 | hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT) | ||
298 | & JC42_CFG_HYST_MASK]; | ||
299 | return sprintf(buf, "%d\n", temp - hyst); | ||
300 | } | ||
301 | |||
302 | /* write routines */ | ||
303 | #define set(value, reg) \ | ||
304 | static ssize_t set_##value(struct device *dev, \ | ||
305 | struct device_attribute *attr, \ | ||
306 | const char *buf, size_t count) \ | ||
307 | { \ | ||
308 | struct i2c_client *client = to_i2c_client(dev); \ | ||
309 | struct jc42_data *data = i2c_get_clientdata(client); \ | ||
310 | int err, ret = count; \ | ||
311 | long val; \ | ||
312 | if (strict_strtol(buf, 10, &val) < 0) \ | ||
313 | return -EINVAL; \ | ||
314 | mutex_lock(&data->update_lock); \ | ||
315 | data->value = jc42_temp_to_reg(val, data->extended); \ | ||
316 | err = jc42_write_value(client, reg, data->value); \ | ||
317 | if (err < 0) \ | ||
318 | ret = err; \ | ||
319 | mutex_unlock(&data->update_lock); \ | ||
320 | return ret; \ | ||
321 | } | ||
322 | |||
323 | set(temp_min, JC42_REG_TEMP_LOWER); | ||
324 | set(temp_max, JC42_REG_TEMP_UPPER); | ||
325 | set(temp_crit, JC42_REG_TEMP_CRITICAL); | ||
326 | |||
327 | /* JC42.4 compliant chips only support four hysteresis values. | ||
328 | * Pick best choice and go from there. */ | ||
329 | static ssize_t set_temp_crit_hyst(struct device *dev, | ||
330 | struct device_attribute *attr, | ||
331 | const char *buf, size_t count) | ||
332 | { | ||
333 | struct i2c_client *client = to_i2c_client(dev); | ||
334 | struct jc42_data *data = i2c_get_clientdata(client); | ||
335 | long val; | ||
336 | int diff, hyst; | ||
337 | int err; | ||
338 | int ret = count; | ||
339 | |||
340 | if (strict_strtoul(buf, 10, &val) < 0) | ||
341 | return -EINVAL; | ||
342 | |||
343 | diff = jc42_temp_from_reg(data->temp_crit) - val; | ||
344 | hyst = 0; | ||
345 | if (diff > 0) { | ||
346 | if (diff < 2250) | ||
347 | hyst = 1; /* 1.5 degrees C */ | ||
348 | else if (diff < 4500) | ||
349 | hyst = 2; /* 3.0 degrees C */ | ||
350 | else | ||
351 | hyst = 3; /* 6.0 degrees C */ | ||
352 | } | ||
353 | |||
354 | mutex_lock(&data->update_lock); | ||
355 | data->config = (data->config | ||
356 | & ~(JC42_CFG_HYST_MASK << JC42_CFG_HYST_SHIFT)) | ||
357 | | (hyst << JC42_CFG_HYST_SHIFT); | ||
358 | err = jc42_write_value(client, JC42_REG_CONFIG, data->config); | ||
359 | if (err < 0) | ||
360 | ret = err; | ||
361 | mutex_unlock(&data->update_lock); | ||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | static ssize_t show_alarm(struct device *dev, | ||
366 | struct device_attribute *attr, char *buf) | ||
367 | { | ||
368 | u16 bit = to_sensor_dev_attr(attr)->index; | ||
369 | struct jc42_data *data = jc42_update_device(dev); | ||
370 | u16 val; | ||
371 | |||
372 | if (IS_ERR(data)) | ||
373 | return PTR_ERR(data); | ||
374 | |||
375 | val = data->temp_input; | ||
376 | if (bit != JC42_ALARM_CRIT_BIT && (data->config & JC42_CFG_CRIT_ONLY)) | ||
377 | val = 0; | ||
378 | return sprintf(buf, "%u\n", (val >> bit) & 1); | ||
379 | } | ||
380 | |||
381 | static DEVICE_ATTR(temp1_input, S_IRUGO, | ||
382 | show_temp_input, NULL); | ||
383 | static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, | ||
384 | show_temp_crit, set_temp_crit); | ||
385 | static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, | ||
386 | show_temp_min, set_temp_min); | ||
387 | static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, | ||
388 | show_temp_max, set_temp_max); | ||
389 | |||
390 | static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, | ||
391 | show_temp_crit_hyst, set_temp_crit_hyst); | ||
392 | static DEVICE_ATTR(temp1_max_hyst, S_IRUGO, | ||
393 | show_temp_max_hyst, NULL); | ||
394 | |||
395 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, | ||
396 | JC42_ALARM_CRIT_BIT); | ||
397 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, | ||
398 | JC42_ALARM_MIN_BIT); | ||
399 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, | ||
400 | JC42_ALARM_MAX_BIT); | ||
401 | |||
402 | static struct attribute *jc42_attributes[] = { | ||
403 | &dev_attr_temp1_input.attr, | ||
404 | &dev_attr_temp1_crit.attr, | ||
405 | &dev_attr_temp1_min.attr, | ||
406 | &dev_attr_temp1_max.attr, | ||
407 | &dev_attr_temp1_crit_hyst.attr, | ||
408 | &dev_attr_temp1_max_hyst.attr, | ||
409 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | ||
410 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | ||
411 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | ||
412 | NULL | ||
413 | }; | ||
414 | |||
415 | static const struct attribute_group jc42_group = { | ||
416 | .attrs = jc42_attributes, | ||
417 | }; | ||
418 | |||
419 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
420 | static int jc42_detect(struct i2c_client *new_client, | ||
421 | struct i2c_board_info *info) | ||
422 | { | ||
423 | struct i2c_adapter *adapter = new_client->adapter; | ||
424 | int i, config, cap, manid, devid; | ||
425 | |||
426 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | | ||
427 | I2C_FUNC_SMBUS_WORD_DATA)) | ||
428 | return -ENODEV; | ||
429 | |||
430 | cap = jc42_read_value(new_client, JC42_REG_CAP); | ||
431 | config = jc42_read_value(new_client, JC42_REG_CONFIG); | ||
432 | manid = jc42_read_value(new_client, JC42_REG_MANID); | ||
433 | devid = jc42_read_value(new_client, JC42_REG_DEVICEID); | ||
434 | |||
435 | if (cap < 0 || config < 0 || manid < 0 || devid < 0) | ||
436 | return -ENODEV; | ||
437 | |||
438 | if ((cap & 0xff00) || (config & 0xf800)) | ||
439 | return -ENODEV; | ||
440 | |||
441 | for (i = 0; i < ARRAY_SIZE(jc42_chips); i++) { | ||
442 | struct jc42_chips *chip = &jc42_chips[i]; | ||
443 | if (manid == chip->manid && | ||
444 | (devid & chip->devid_mask) == chip->devid) { | ||
445 | strlcpy(info->type, "jc42", I2C_NAME_SIZE); | ||
446 | return 0; | ||
447 | } | ||
448 | } | ||
449 | return -ENODEV; | ||
450 | } | ||
451 | |||
452 | static int jc42_probe(struct i2c_client *new_client, | ||
453 | const struct i2c_device_id *id) | ||
454 | { | ||
455 | struct jc42_data *data; | ||
456 | int config, cap, err; | ||
457 | |||
458 | data = kzalloc(sizeof(struct jc42_data), GFP_KERNEL); | ||
459 | if (!data) { | ||
460 | err = -ENOMEM; | ||
461 | goto exit; | ||
462 | } | ||
463 | |||
464 | i2c_set_clientdata(new_client, data); | ||
465 | mutex_init(&data->update_lock); | ||
466 | |||
467 | cap = jc42_read_value(new_client, JC42_REG_CAP); | ||
468 | if (cap < 0) { | ||
469 | err = -EINVAL; | ||
470 | goto exit_free; | ||
471 | } | ||
472 | data->extended = !!(cap & JC42_CAP_RANGE); | ||
473 | |||
474 | config = jc42_read_value(new_client, JC42_REG_CONFIG); | ||
475 | if (config < 0) { | ||
476 | err = -EINVAL; | ||
477 | goto exit_free; | ||
478 | } | ||
479 | data->orig_config = config; | ||
480 | if (config & JC42_CFG_SHUTDOWN) { | ||
481 | config &= ~JC42_CFG_SHUTDOWN; | ||
482 | jc42_write_value(new_client, JC42_REG_CONFIG, config); | ||
483 | } | ||
484 | data->config = config; | ||
485 | |||
486 | /* Register sysfs hooks */ | ||
487 | err = sysfs_create_group(&new_client->dev.kobj, &jc42_group); | ||
488 | if (err) | ||
489 | goto exit_free; | ||
490 | |||
491 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | ||
492 | if (IS_ERR(data->hwmon_dev)) { | ||
493 | err = PTR_ERR(data->hwmon_dev); | ||
494 | goto exit_remove; | ||
495 | } | ||
496 | |||
497 | return 0; | ||
498 | |||
499 | exit_remove: | ||
500 | sysfs_remove_group(&new_client->dev.kobj, &jc42_group); | ||
501 | exit_free: | ||
502 | kfree(data); | ||
503 | exit: | ||
504 | return err; | ||
505 | } | ||
506 | |||
507 | static int jc42_remove(struct i2c_client *client) | ||
508 | { | ||
509 | struct jc42_data *data = i2c_get_clientdata(client); | ||
510 | hwmon_device_unregister(data->hwmon_dev); | ||
511 | sysfs_remove_group(&client->dev.kobj, &jc42_group); | ||
512 | if (data->config != data->orig_config) | ||
513 | jc42_write_value(client, JC42_REG_CONFIG, data->orig_config); | ||
514 | kfree(data); | ||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | /* All registers are word-sized. */ | ||
519 | static int jc42_read_value(struct i2c_client *client, u8 reg) | ||
520 | { | ||
521 | int ret = i2c_smbus_read_word_data(client, reg); | ||
522 | if (ret < 0) | ||
523 | return ret; | ||
524 | return swab16(ret); | ||
525 | } | ||
526 | |||
527 | static int jc42_write_value(struct i2c_client *client, u8 reg, u16 value) | ||
528 | { | ||
529 | return i2c_smbus_write_word_data(client, reg, swab16(value)); | ||
530 | } | ||
531 | |||
532 | static struct jc42_data *jc42_update_device(struct device *dev) | ||
533 | { | ||
534 | struct i2c_client *client = to_i2c_client(dev); | ||
535 | struct jc42_data *data = i2c_get_clientdata(client); | ||
536 | struct jc42_data *ret = data; | ||
537 | int val; | ||
538 | |||
539 | mutex_lock(&data->update_lock); | ||
540 | |||
541 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { | ||
542 | val = jc42_read_value(client, JC42_REG_TEMP); | ||
543 | if (val < 0) { | ||
544 | ret = ERR_PTR(val); | ||
545 | goto abort; | ||
546 | } | ||
547 | data->temp_input = val; | ||
548 | |||
549 | val = jc42_read_value(client, JC42_REG_TEMP_CRITICAL); | ||
550 | if (val < 0) { | ||
551 | ret = ERR_PTR(val); | ||
552 | goto abort; | ||
553 | } | ||
554 | data->temp_crit = val; | ||
555 | |||
556 | val = jc42_read_value(client, JC42_REG_TEMP_LOWER); | ||
557 | if (val < 0) { | ||
558 | ret = ERR_PTR(val); | ||
559 | goto abort; | ||
560 | } | ||
561 | data->temp_min = val; | ||
562 | |||
563 | val = jc42_read_value(client, JC42_REG_TEMP_UPPER); | ||
564 | if (val < 0) { | ||
565 | ret = ERR_PTR(val); | ||
566 | goto abort; | ||
567 | } | ||
568 | data->temp_max = val; | ||
569 | |||
570 | data->last_updated = jiffies; | ||
571 | data->valid = true; | ||
572 | } | ||
573 | abort: | ||
574 | mutex_unlock(&data->update_lock); | ||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | static int __init sensors_jc42_init(void) | ||
579 | { | ||
580 | return i2c_add_driver(&jc42_driver); | ||
581 | } | ||
582 | |||
583 | static void __exit sensors_jc42_exit(void) | ||
584 | { | ||
585 | i2c_del_driver(&jc42_driver); | ||
586 | } | ||
587 | |||
588 | MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>"); | ||
589 | MODULE_DESCRIPTION("JC42 driver"); | ||
590 | MODULE_LICENSE("GPL"); | ||
591 | |||
592 | module_init(sensors_jc42_init); | ||
593 | module_exit(sensors_jc42_exit); | ||
diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c new file mode 100644 index 000000000000..425df5bccd45 --- /dev/null +++ b/drivers/hwmon/smm665.c | |||
@@ -0,0 +1,743 @@ | |||
1 | /* | ||
2 | * Driver for SMM665 Power Controller / Monitor | ||
3 | * | ||
4 | * Copyright (C) 2010 Ericsson AB. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * This driver should also work for SMM465, SMM764, and SMM766, but is untested | ||
11 | * for those chips. Only monitoring functionality is implemented. | ||
12 | * | ||
13 | * Datasheets: | ||
14 | * http://www.summitmicro.com/prod_select/summary/SMM665/SMM665B_2089_20.pdf | ||
15 | * http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/hwmon.h> | ||
25 | #include <linux/hwmon-sysfs.h> | ||
26 | #include <linux/delay.h> | ||
27 | |||
28 | /* Internal reference voltage (VREF, x 1000 */ | ||
29 | #define SMM665_VREF_ADC_X1000 1250 | ||
30 | |||
31 | /* module parameters */ | ||
32 | static int vref = SMM665_VREF_ADC_X1000; | ||
33 | module_param(vref, int, 0); | ||
34 | MODULE_PARM_DESC(vref, "Reference voltage in mV"); | ||
35 | |||
36 | enum chips { smm465, smm665, smm665c, smm764, smm766 }; | ||
37 | |||
38 | /* | ||
39 | * ADC channel addresses | ||
40 | */ | ||
41 | #define SMM665_MISC16_ADC_DATA_A 0x00 | ||
42 | #define SMM665_MISC16_ADC_DATA_B 0x01 | ||
43 | #define SMM665_MISC16_ADC_DATA_C 0x02 | ||
44 | #define SMM665_MISC16_ADC_DATA_D 0x03 | ||
45 | #define SMM665_MISC16_ADC_DATA_E 0x04 | ||
46 | #define SMM665_MISC16_ADC_DATA_F 0x05 | ||
47 | #define SMM665_MISC16_ADC_DATA_VDD 0x06 | ||
48 | #define SMM665_MISC16_ADC_DATA_12V 0x07 | ||
49 | #define SMM665_MISC16_ADC_DATA_INT_TEMP 0x08 | ||
50 | #define SMM665_MISC16_ADC_DATA_AIN1 0x09 | ||
51 | #define SMM665_MISC16_ADC_DATA_AIN2 0x0a | ||
52 | |||
53 | /* | ||
54 | * Command registers | ||
55 | */ | ||
56 | #define SMM665_MISC8_CMD_STS 0x80 | ||
57 | #define SMM665_MISC8_STATUS1 0x81 | ||
58 | #define SMM665_MISC8_STATUSS2 0x82 | ||
59 | #define SMM665_MISC8_IO_POLARITY 0x83 | ||
60 | #define SMM665_MISC8_PUP_POLARITY 0x84 | ||
61 | #define SMM665_MISC8_ADOC_STATUS1 0x85 | ||
62 | #define SMM665_MISC8_ADOC_STATUS2 0x86 | ||
63 | #define SMM665_MISC8_WRITE_PROT 0x87 | ||
64 | #define SMM665_MISC8_STS_TRACK 0x88 | ||
65 | |||
66 | /* | ||
67 | * Configuration registers and register groups | ||
68 | */ | ||
69 | #define SMM665_ADOC_ENABLE 0x0d | ||
70 | #define SMM665_LIMIT_BASE 0x80 /* First limit register */ | ||
71 | |||
72 | /* | ||
73 | * Limit register bit masks | ||
74 | */ | ||
75 | #define SMM665_TRIGGER_RST 0x8000 | ||
76 | #define SMM665_TRIGGER_HEALTHY 0x4000 | ||
77 | #define SMM665_TRIGGER_POWEROFF 0x2000 | ||
78 | #define SMM665_TRIGGER_SHUTDOWN 0x1000 | ||
79 | #define SMM665_ADC_MASK 0x03ff | ||
80 | |||
81 | #define smm665_is_critical(lim) ((lim) & (SMM665_TRIGGER_RST \ | ||
82 | | SMM665_TRIGGER_POWEROFF \ | ||
83 | | SMM665_TRIGGER_SHUTDOWN)) | ||
84 | /* | ||
85 | * Fault register bit definitions | ||
86 | * Values are merged from status registers 1/2, | ||
87 | * with status register 1 providing the upper 8 bits. | ||
88 | */ | ||
89 | #define SMM665_FAULT_A 0x0001 | ||
90 | #define SMM665_FAULT_B 0x0002 | ||
91 | #define SMM665_FAULT_C 0x0004 | ||
92 | #define SMM665_FAULT_D 0x0008 | ||
93 | #define SMM665_FAULT_E 0x0010 | ||
94 | #define SMM665_FAULT_F 0x0020 | ||
95 | #define SMM665_FAULT_VDD 0x0040 | ||
96 | #define SMM665_FAULT_12V 0x0080 | ||
97 | #define SMM665_FAULT_TEMP 0x0100 | ||
98 | #define SMM665_FAULT_AIN1 0x0200 | ||
99 | #define SMM665_FAULT_AIN2 0x0400 | ||
100 | |||
101 | /* | ||
102 | * I2C Register addresses | ||
103 | * | ||
104 | * The configuration register needs to be the configured base register. | ||
105 | * The command/status register address is derived from it. | ||
106 | */ | ||
107 | #define SMM665_REGMASK 0x78 | ||
108 | #define SMM665_CMDREG_BASE 0x48 | ||
109 | #define SMM665_CONFREG_BASE 0x50 | ||
110 | |||
111 | /* | ||
112 | * Equations given by chip manufacturer to calculate voltage/temperature values | ||
113 | * vref = Reference voltage on VREF_ADC pin (module parameter) | ||
114 | * adc = 10bit ADC value read back from registers | ||
115 | */ | ||
116 | |||
117 | /* Voltage A-F and VDD */ | ||
118 | #define SMM665_VMON_ADC_TO_VOLTS(adc) ((adc) * vref / 256) | ||
119 | |||
120 | /* Voltage 12VIN */ | ||
121 | #define SMM665_12VIN_ADC_TO_VOLTS(adc) ((adc) * vref * 3 / 256) | ||
122 | |||
123 | /* Voltage AIN1, AIN2 */ | ||
124 | #define SMM665_AIN_ADC_TO_VOLTS(adc) ((adc) * vref / 512) | ||
125 | |||
126 | /* Temp Sensor */ | ||
127 | #define SMM665_TEMP_ADC_TO_CELSIUS(adc) ((adc) <= 511) ? \ | ||
128 | ((int)(adc) * 1000 / 4) : \ | ||
129 | (((int)(adc) - 0x400) * 1000 / 4) | ||
130 | |||
131 | #define SMM665_NUM_ADC 11 | ||
132 | |||
133 | /* | ||
134 | * Chip dependent ADC conversion time, in uS | ||
135 | */ | ||
136 | #define SMM665_ADC_WAIT_SMM665 70 | ||
137 | #define SMM665_ADC_WAIT_SMM766 185 | ||
138 | |||
139 | struct smm665_data { | ||
140 | enum chips type; | ||
141 | int conversion_time; /* ADC conversion time */ | ||
142 | struct device *hwmon_dev; | ||
143 | struct mutex update_lock; | ||
144 | bool valid; | ||
145 | unsigned long last_updated; /* in jiffies */ | ||
146 | u16 adc[SMM665_NUM_ADC]; /* adc values (raw) */ | ||
147 | u16 faults; /* fault status */ | ||
148 | /* The following values are in mV */ | ||
149 | int critical_min_limit[SMM665_NUM_ADC]; | ||
150 | int alarm_min_limit[SMM665_NUM_ADC]; | ||
151 | int critical_max_limit[SMM665_NUM_ADC]; | ||
152 | int alarm_max_limit[SMM665_NUM_ADC]; | ||
153 | struct i2c_client *cmdreg; | ||
154 | }; | ||
155 | |||
156 | /* | ||
157 | * smm665_read16() | ||
158 | * | ||
159 | * Read 16 bit value from <reg>, <reg+1>. Upper 8 bits are in <reg>. | ||
160 | */ | ||
161 | static int smm665_read16(struct i2c_client *client, int reg) | ||
162 | { | ||
163 | int rv, val; | ||
164 | |||
165 | rv = i2c_smbus_read_byte_data(client, reg); | ||
166 | if (rv < 0) | ||
167 | return rv; | ||
168 | val = rv << 8; | ||
169 | rv = i2c_smbus_read_byte_data(client, reg + 1); | ||
170 | if (rv < 0) | ||
171 | return rv; | ||
172 | val |= rv; | ||
173 | return val; | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * Read adc value. | ||
178 | */ | ||
179 | static int smm665_read_adc(struct smm665_data *data, int adc) | ||
180 | { | ||
181 | struct i2c_client *client = data->cmdreg; | ||
182 | int rv; | ||
183 | int radc; | ||
184 | |||
185 | /* | ||
186 | * Algorithm for reading ADC, per SMM665 datasheet | ||
187 | * | ||
188 | * {[S][addr][W][Ack]} {[offset][Ack]} {[S][addr][R][Nack]} | ||
189 | * [wait conversion time] | ||
190 | * {[S][addr][R][Ack]} {[datahi][Ack]} {[datalo][Ack][P]} | ||
191 | * | ||
192 | * To implement the first part of this exchange, | ||
193 | * do a full read transaction and expect a failure/Nack. | ||
194 | * This sets up the address pointer on the SMM665 | ||
195 | * and starts the ADC conversion. | ||
196 | * Then do a two-byte read transaction. | ||
197 | */ | ||
198 | rv = i2c_smbus_read_byte_data(client, adc << 3); | ||
199 | if (rv != -ENXIO) { | ||
200 | /* | ||
201 | * We expect ENXIO to reflect NACK | ||
202 | * (per Documentation/i2c/fault-codes). | ||
203 | * Everything else is an error. | ||
204 | */ | ||
205 | dev_dbg(&client->dev, | ||
206 | "Unexpected return code %d when setting ADC index", rv); | ||
207 | return (rv < 0) ? rv : -EIO; | ||
208 | } | ||
209 | |||
210 | udelay(data->conversion_time); | ||
211 | |||
212 | /* | ||
213 | * Now read two bytes. | ||
214 | * | ||
215 | * Neither i2c_smbus_read_byte() nor | ||
216 | * i2c_smbus_read_block_data() worked here, | ||
217 | * so use i2c_smbus_read_word_data() instead. | ||
218 | * We could also try to use i2c_master_recv(), | ||
219 | * but that is not always supported. | ||
220 | */ | ||
221 | rv = i2c_smbus_read_word_data(client, 0); | ||
222 | if (rv < 0) { | ||
223 | dev_dbg(&client->dev, "Failed to read ADC value: error %d", rv); | ||
224 | return -1; | ||
225 | } | ||
226 | /* | ||
227 | * Validate/verify readback adc channel (in bit 11..14). | ||
228 | * High byte is in lower 8 bit of rv, so only shift by 3. | ||
229 | */ | ||
230 | radc = (rv >> 3) & 0x0f; | ||
231 | if (radc != adc) { | ||
232 | dev_dbg(&client->dev, "Unexpected RADC: Expected %d got %d", | ||
233 | adc, radc); | ||
234 | return -EIO; | ||
235 | } | ||
236 | /* | ||
237 | * Chip replies with H/L, while SMBus expects L/H. | ||
238 | * Thus, byte order is reversed, and we have to swap | ||
239 | * the result. | ||
240 | */ | ||
241 | rv = swab16(rv) & SMM665_ADC_MASK; | ||
242 | |||
243 | return rv; | ||
244 | } | ||
245 | |||
246 | static struct smm665_data *smm665_update_device(struct device *dev) | ||
247 | { | ||
248 | struct i2c_client *client = to_i2c_client(dev); | ||
249 | struct smm665_data *data = i2c_get_clientdata(client); | ||
250 | struct smm665_data *ret = data; | ||
251 | |||
252 | mutex_lock(&data->update_lock); | ||
253 | |||
254 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { | ||
255 | int i, val; | ||
256 | |||
257 | /* | ||
258 | * read status registers | ||
259 | */ | ||
260 | val = smm665_read16(client, SMM665_MISC8_STATUS1); | ||
261 | if (unlikely(val < 0)) { | ||
262 | ret = ERR_PTR(val); | ||
263 | goto abort; | ||
264 | } | ||
265 | data->faults = val; | ||
266 | |||
267 | /* Read adc registers */ | ||
268 | for (i = 0; i < SMM665_NUM_ADC; i++) { | ||
269 | val = smm665_read_adc(data, i); | ||
270 | if (unlikely(val < 0)) { | ||
271 | ret = ERR_PTR(val); | ||
272 | goto abort; | ||
273 | } | ||
274 | data->adc[i] = val; | ||
275 | } | ||
276 | data->last_updated = jiffies; | ||
277 | data->valid = 1; | ||
278 | } | ||
279 | abort: | ||
280 | mutex_unlock(&data->update_lock); | ||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | /* Return converted value from given adc */ | ||
285 | static int smm665_convert(u16 adcval, int index) | ||
286 | { | ||
287 | int val = 0; | ||
288 | |||
289 | switch (index) { | ||
290 | case SMM665_MISC16_ADC_DATA_12V: | ||
291 | val = SMM665_12VIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK); | ||
292 | break; | ||
293 | |||
294 | case SMM665_MISC16_ADC_DATA_VDD: | ||
295 | case SMM665_MISC16_ADC_DATA_A: | ||
296 | case SMM665_MISC16_ADC_DATA_B: | ||
297 | case SMM665_MISC16_ADC_DATA_C: | ||
298 | case SMM665_MISC16_ADC_DATA_D: | ||
299 | case SMM665_MISC16_ADC_DATA_E: | ||
300 | case SMM665_MISC16_ADC_DATA_F: | ||
301 | val = SMM665_VMON_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK); | ||
302 | break; | ||
303 | |||
304 | case SMM665_MISC16_ADC_DATA_AIN1: | ||
305 | case SMM665_MISC16_ADC_DATA_AIN2: | ||
306 | val = SMM665_AIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK); | ||
307 | break; | ||
308 | |||
309 | case SMM665_MISC16_ADC_DATA_INT_TEMP: | ||
310 | val = SMM665_TEMP_ADC_TO_CELSIUS(adcval & SMM665_ADC_MASK); | ||
311 | break; | ||
312 | |||
313 | default: | ||
314 | /* If we get here, the developer messed up */ | ||
315 | WARN_ON_ONCE(1); | ||
316 | break; | ||
317 | } | ||
318 | |||
319 | return val; | ||
320 | } | ||
321 | |||
322 | static int smm665_get_min(struct device *dev, int index) | ||
323 | { | ||
324 | struct i2c_client *client = to_i2c_client(dev); | ||
325 | struct smm665_data *data = i2c_get_clientdata(client); | ||
326 | |||
327 | return data->alarm_min_limit[index]; | ||
328 | } | ||
329 | |||
330 | static int smm665_get_max(struct device *dev, int index) | ||
331 | { | ||
332 | struct i2c_client *client = to_i2c_client(dev); | ||
333 | struct smm665_data *data = i2c_get_clientdata(client); | ||
334 | |||
335 | return data->alarm_max_limit[index]; | ||
336 | } | ||
337 | |||
338 | static int smm665_get_lcrit(struct device *dev, int index) | ||
339 | { | ||
340 | struct i2c_client *client = to_i2c_client(dev); | ||
341 | struct smm665_data *data = i2c_get_clientdata(client); | ||
342 | |||
343 | return data->critical_min_limit[index]; | ||
344 | } | ||
345 | |||
346 | static int smm665_get_crit(struct device *dev, int index) | ||
347 | { | ||
348 | struct i2c_client *client = to_i2c_client(dev); | ||
349 | struct smm665_data *data = i2c_get_clientdata(client); | ||
350 | |||
351 | return data->critical_max_limit[index]; | ||
352 | } | ||
353 | |||
354 | static ssize_t smm665_show_crit_alarm(struct device *dev, | ||
355 | struct device_attribute *da, char *buf) | ||
356 | { | ||
357 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
358 | struct smm665_data *data = smm665_update_device(dev); | ||
359 | int val = 0; | ||
360 | |||
361 | if (IS_ERR(data)) | ||
362 | return PTR_ERR(data); | ||
363 | |||
364 | if (data->faults & (1 << attr->index)) | ||
365 | val = 1; | ||
366 | |||
367 | return snprintf(buf, PAGE_SIZE, "%d\n", val); | ||
368 | } | ||
369 | |||
370 | static ssize_t smm665_show_input(struct device *dev, | ||
371 | struct device_attribute *da, char *buf) | ||
372 | { | ||
373 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
374 | struct smm665_data *data = smm665_update_device(dev); | ||
375 | int adc = attr->index; | ||
376 | int val; | ||
377 | |||
378 | if (IS_ERR(data)) | ||
379 | return PTR_ERR(data); | ||
380 | |||
381 | val = smm665_convert(data->adc[adc], adc); | ||
382 | return snprintf(buf, PAGE_SIZE, "%d\n", val); | ||
383 | } | ||
384 | |||
385 | #define SMM665_SHOW(what) \ | ||
386 | static ssize_t smm665_show_##what(struct device *dev, \ | ||
387 | struct device_attribute *da, char *buf) \ | ||
388 | { \ | ||
389 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ | ||
390 | const int val = smm665_get_##what(dev, attr->index); \ | ||
391 | return snprintf(buf, PAGE_SIZE, "%d\n", val); \ | ||
392 | } | ||
393 | |||
394 | SMM665_SHOW(min); | ||
395 | SMM665_SHOW(max); | ||
396 | SMM665_SHOW(lcrit); | ||
397 | SMM665_SHOW(crit); | ||
398 | |||
399 | /* These macros are used below in constructing device attribute objects | ||
400 | * for use with sysfs_create_group() to make a sysfs device file | ||
401 | * for each register. | ||
402 | */ | ||
403 | |||
404 | #define SMM665_ATTR(name, type, cmd_idx) \ | ||
405 | static SENSOR_DEVICE_ATTR(name##_##type, S_IRUGO, \ | ||
406 | smm665_show_##type, NULL, cmd_idx) | ||
407 | |||
408 | /* Construct a sensor_device_attribute structure for each register */ | ||
409 | |||
410 | /* Input voltages */ | ||
411 | SMM665_ATTR(in1, input, SMM665_MISC16_ADC_DATA_12V); | ||
412 | SMM665_ATTR(in2, input, SMM665_MISC16_ADC_DATA_VDD); | ||
413 | SMM665_ATTR(in3, input, SMM665_MISC16_ADC_DATA_A); | ||
414 | SMM665_ATTR(in4, input, SMM665_MISC16_ADC_DATA_B); | ||
415 | SMM665_ATTR(in5, input, SMM665_MISC16_ADC_DATA_C); | ||
416 | SMM665_ATTR(in6, input, SMM665_MISC16_ADC_DATA_D); | ||
417 | SMM665_ATTR(in7, input, SMM665_MISC16_ADC_DATA_E); | ||
418 | SMM665_ATTR(in8, input, SMM665_MISC16_ADC_DATA_F); | ||
419 | SMM665_ATTR(in9, input, SMM665_MISC16_ADC_DATA_AIN1); | ||
420 | SMM665_ATTR(in10, input, SMM665_MISC16_ADC_DATA_AIN2); | ||
421 | |||
422 | /* Input voltages min */ | ||
423 | SMM665_ATTR(in1, min, SMM665_MISC16_ADC_DATA_12V); | ||
424 | SMM665_ATTR(in2, min, SMM665_MISC16_ADC_DATA_VDD); | ||
425 | SMM665_ATTR(in3, min, SMM665_MISC16_ADC_DATA_A); | ||
426 | SMM665_ATTR(in4, min, SMM665_MISC16_ADC_DATA_B); | ||
427 | SMM665_ATTR(in5, min, SMM665_MISC16_ADC_DATA_C); | ||
428 | SMM665_ATTR(in6, min, SMM665_MISC16_ADC_DATA_D); | ||
429 | SMM665_ATTR(in7, min, SMM665_MISC16_ADC_DATA_E); | ||
430 | SMM665_ATTR(in8, min, SMM665_MISC16_ADC_DATA_F); | ||
431 | SMM665_ATTR(in9, min, SMM665_MISC16_ADC_DATA_AIN1); | ||
432 | SMM665_ATTR(in10, min, SMM665_MISC16_ADC_DATA_AIN2); | ||
433 | |||
434 | /* Input voltages max */ | ||
435 | SMM665_ATTR(in1, max, SMM665_MISC16_ADC_DATA_12V); | ||
436 | SMM665_ATTR(in2, max, SMM665_MISC16_ADC_DATA_VDD); | ||
437 | SMM665_ATTR(in3, max, SMM665_MISC16_ADC_DATA_A); | ||
438 | SMM665_ATTR(in4, max, SMM665_MISC16_ADC_DATA_B); | ||
439 | SMM665_ATTR(in5, max, SMM665_MISC16_ADC_DATA_C); | ||
440 | SMM665_ATTR(in6, max, SMM665_MISC16_ADC_DATA_D); | ||
441 | SMM665_ATTR(in7, max, SMM665_MISC16_ADC_DATA_E); | ||
442 | SMM665_ATTR(in8, max, SMM665_MISC16_ADC_DATA_F); | ||
443 | SMM665_ATTR(in9, max, SMM665_MISC16_ADC_DATA_AIN1); | ||
444 | SMM665_ATTR(in10, max, SMM665_MISC16_ADC_DATA_AIN2); | ||
445 | |||
446 | /* Input voltages lcrit */ | ||
447 | SMM665_ATTR(in1, lcrit, SMM665_MISC16_ADC_DATA_12V); | ||
448 | SMM665_ATTR(in2, lcrit, SMM665_MISC16_ADC_DATA_VDD); | ||
449 | SMM665_ATTR(in3, lcrit, SMM665_MISC16_ADC_DATA_A); | ||
450 | SMM665_ATTR(in4, lcrit, SMM665_MISC16_ADC_DATA_B); | ||
451 | SMM665_ATTR(in5, lcrit, SMM665_MISC16_ADC_DATA_C); | ||
452 | SMM665_ATTR(in6, lcrit, SMM665_MISC16_ADC_DATA_D); | ||
453 | SMM665_ATTR(in7, lcrit, SMM665_MISC16_ADC_DATA_E); | ||
454 | SMM665_ATTR(in8, lcrit, SMM665_MISC16_ADC_DATA_F); | ||
455 | SMM665_ATTR(in9, lcrit, SMM665_MISC16_ADC_DATA_AIN1); | ||
456 | SMM665_ATTR(in10, lcrit, SMM665_MISC16_ADC_DATA_AIN2); | ||
457 | |||
458 | /* Input voltages crit */ | ||
459 | SMM665_ATTR(in1, crit, SMM665_MISC16_ADC_DATA_12V); | ||
460 | SMM665_ATTR(in2, crit, SMM665_MISC16_ADC_DATA_VDD); | ||
461 | SMM665_ATTR(in3, crit, SMM665_MISC16_ADC_DATA_A); | ||
462 | SMM665_ATTR(in4, crit, SMM665_MISC16_ADC_DATA_B); | ||
463 | SMM665_ATTR(in5, crit, SMM665_MISC16_ADC_DATA_C); | ||
464 | SMM665_ATTR(in6, crit, SMM665_MISC16_ADC_DATA_D); | ||
465 | SMM665_ATTR(in7, crit, SMM665_MISC16_ADC_DATA_E); | ||
466 | SMM665_ATTR(in8, crit, SMM665_MISC16_ADC_DATA_F); | ||
467 | SMM665_ATTR(in9, crit, SMM665_MISC16_ADC_DATA_AIN1); | ||
468 | SMM665_ATTR(in10, crit, SMM665_MISC16_ADC_DATA_AIN2); | ||
469 | |||
470 | /* critical alarms */ | ||
471 | SMM665_ATTR(in1, crit_alarm, SMM665_FAULT_12V); | ||
472 | SMM665_ATTR(in2, crit_alarm, SMM665_FAULT_VDD); | ||
473 | SMM665_ATTR(in3, crit_alarm, SMM665_FAULT_A); | ||
474 | SMM665_ATTR(in4, crit_alarm, SMM665_FAULT_B); | ||
475 | SMM665_ATTR(in5, crit_alarm, SMM665_FAULT_C); | ||
476 | SMM665_ATTR(in6, crit_alarm, SMM665_FAULT_D); | ||
477 | SMM665_ATTR(in7, crit_alarm, SMM665_FAULT_E); | ||
478 | SMM665_ATTR(in8, crit_alarm, SMM665_FAULT_F); | ||
479 | SMM665_ATTR(in9, crit_alarm, SMM665_FAULT_AIN1); | ||
480 | SMM665_ATTR(in10, crit_alarm, SMM665_FAULT_AIN2); | ||
481 | |||
482 | /* Temperature */ | ||
483 | SMM665_ATTR(temp1, input, SMM665_MISC16_ADC_DATA_INT_TEMP); | ||
484 | SMM665_ATTR(temp1, min, SMM665_MISC16_ADC_DATA_INT_TEMP); | ||
485 | SMM665_ATTR(temp1, max, SMM665_MISC16_ADC_DATA_INT_TEMP); | ||
486 | SMM665_ATTR(temp1, lcrit, SMM665_MISC16_ADC_DATA_INT_TEMP); | ||
487 | SMM665_ATTR(temp1, crit, SMM665_MISC16_ADC_DATA_INT_TEMP); | ||
488 | SMM665_ATTR(temp1, crit_alarm, SMM665_FAULT_TEMP); | ||
489 | |||
490 | /* | ||
491 | * Finally, construct an array of pointers to members of the above objects, | ||
492 | * as required for sysfs_create_group() | ||
493 | */ | ||
494 | static struct attribute *smm665_attributes[] = { | ||
495 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
496 | &sensor_dev_attr_in1_min.dev_attr.attr, | ||
497 | &sensor_dev_attr_in1_max.dev_attr.attr, | ||
498 | &sensor_dev_attr_in1_lcrit.dev_attr.attr, | ||
499 | &sensor_dev_attr_in1_crit.dev_attr.attr, | ||
500 | &sensor_dev_attr_in1_crit_alarm.dev_attr.attr, | ||
501 | |||
502 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
503 | &sensor_dev_attr_in2_min.dev_attr.attr, | ||
504 | &sensor_dev_attr_in2_max.dev_attr.attr, | ||
505 | &sensor_dev_attr_in2_lcrit.dev_attr.attr, | ||
506 | &sensor_dev_attr_in2_crit.dev_attr.attr, | ||
507 | &sensor_dev_attr_in2_crit_alarm.dev_attr.attr, | ||
508 | |||
509 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
510 | &sensor_dev_attr_in3_min.dev_attr.attr, | ||
511 | &sensor_dev_attr_in3_max.dev_attr.attr, | ||
512 | &sensor_dev_attr_in3_lcrit.dev_attr.attr, | ||
513 | &sensor_dev_attr_in3_crit.dev_attr.attr, | ||
514 | &sensor_dev_attr_in3_crit_alarm.dev_attr.attr, | ||
515 | |||
516 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
517 | &sensor_dev_attr_in4_min.dev_attr.attr, | ||
518 | &sensor_dev_attr_in4_max.dev_attr.attr, | ||
519 | &sensor_dev_attr_in4_lcrit.dev_attr.attr, | ||
520 | &sensor_dev_attr_in4_crit.dev_attr.attr, | ||
521 | &sensor_dev_attr_in4_crit_alarm.dev_attr.attr, | ||
522 | |||
523 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
524 | &sensor_dev_attr_in5_min.dev_attr.attr, | ||
525 | &sensor_dev_attr_in5_max.dev_attr.attr, | ||
526 | &sensor_dev_attr_in5_lcrit.dev_attr.attr, | ||
527 | &sensor_dev_attr_in5_crit.dev_attr.attr, | ||
528 | &sensor_dev_attr_in5_crit_alarm.dev_attr.attr, | ||
529 | |||
530 | &sensor_dev_attr_in6_input.dev_attr.attr, | ||
531 | &sensor_dev_attr_in6_min.dev_attr.attr, | ||
532 | &sensor_dev_attr_in6_max.dev_attr.attr, | ||
533 | &sensor_dev_attr_in6_lcrit.dev_attr.attr, | ||
534 | &sensor_dev_attr_in6_crit.dev_attr.attr, | ||
535 | &sensor_dev_attr_in6_crit_alarm.dev_attr.attr, | ||
536 | |||
537 | &sensor_dev_attr_in7_input.dev_attr.attr, | ||
538 | &sensor_dev_attr_in7_min.dev_attr.attr, | ||
539 | &sensor_dev_attr_in7_max.dev_attr.attr, | ||
540 | &sensor_dev_attr_in7_lcrit.dev_attr.attr, | ||
541 | &sensor_dev_attr_in7_crit.dev_attr.attr, | ||
542 | &sensor_dev_attr_in7_crit_alarm.dev_attr.attr, | ||
543 | |||
544 | &sensor_dev_attr_in8_input.dev_attr.attr, | ||
545 | &sensor_dev_attr_in8_min.dev_attr.attr, | ||
546 | &sensor_dev_attr_in8_max.dev_attr.attr, | ||
547 | &sensor_dev_attr_in8_lcrit.dev_attr.attr, | ||
548 | &sensor_dev_attr_in8_crit.dev_attr.attr, | ||
549 | &sensor_dev_attr_in8_crit_alarm.dev_attr.attr, | ||
550 | |||
551 | &sensor_dev_attr_in9_input.dev_attr.attr, | ||
552 | &sensor_dev_attr_in9_min.dev_attr.attr, | ||
553 | &sensor_dev_attr_in9_max.dev_attr.attr, | ||
554 | &sensor_dev_attr_in9_lcrit.dev_attr.attr, | ||
555 | &sensor_dev_attr_in9_crit.dev_attr.attr, | ||
556 | &sensor_dev_attr_in9_crit_alarm.dev_attr.attr, | ||
557 | |||
558 | &sensor_dev_attr_in10_input.dev_attr.attr, | ||
559 | &sensor_dev_attr_in10_min.dev_attr.attr, | ||
560 | &sensor_dev_attr_in10_max.dev_attr.attr, | ||
561 | &sensor_dev_attr_in10_lcrit.dev_attr.attr, | ||
562 | &sensor_dev_attr_in10_crit.dev_attr.attr, | ||
563 | &sensor_dev_attr_in10_crit_alarm.dev_attr.attr, | ||
564 | |||
565 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
566 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
567 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
568 | &sensor_dev_attr_temp1_lcrit.dev_attr.attr, | ||
569 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
570 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | ||
571 | |||
572 | NULL, | ||
573 | }; | ||
574 | |||
575 | static const struct attribute_group smm665_group = { | ||
576 | .attrs = smm665_attributes, | ||
577 | }; | ||
578 | |||
579 | static int smm665_probe(struct i2c_client *client, | ||
580 | const struct i2c_device_id *id) | ||
581 | { | ||
582 | struct i2c_adapter *adapter = client->adapter; | ||
583 | struct smm665_data *data; | ||
584 | int i, ret; | ||
585 | |||
586 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | ||
587 | | I2C_FUNC_SMBUS_WORD_DATA)) | ||
588 | return -ENODEV; | ||
589 | |||
590 | if (i2c_smbus_read_byte_data(client, SMM665_ADOC_ENABLE) < 0) | ||
591 | return -ENODEV; | ||
592 | |||
593 | ret = -ENOMEM; | ||
594 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
595 | if (!data) | ||
596 | goto out_return; | ||
597 | |||
598 | i2c_set_clientdata(client, data); | ||
599 | mutex_init(&data->update_lock); | ||
600 | |||
601 | data->type = id->driver_data; | ||
602 | data->cmdreg = i2c_new_dummy(adapter, (client->addr & ~SMM665_REGMASK) | ||
603 | | SMM665_CMDREG_BASE); | ||
604 | if (!data->cmdreg) | ||
605 | goto out_kfree; | ||
606 | |||
607 | switch (data->type) { | ||
608 | case smm465: | ||
609 | case smm665: | ||
610 | data->conversion_time = SMM665_ADC_WAIT_SMM665; | ||
611 | break; | ||
612 | case smm665c: | ||
613 | case smm764: | ||
614 | case smm766: | ||
615 | data->conversion_time = SMM665_ADC_WAIT_SMM766; | ||
616 | break; | ||
617 | } | ||
618 | |||
619 | ret = -ENODEV; | ||
620 | if (i2c_smbus_read_byte_data(data->cmdreg, SMM665_MISC8_CMD_STS) < 0) | ||
621 | goto out_unregister; | ||
622 | |||
623 | /* | ||
624 | * Read limits. | ||
625 | * | ||
626 | * Limit registers start with register SMM665_LIMIT_BASE. | ||
627 | * Each channel uses 8 registers, providing four limit values | ||
628 | * per channel. Each limit value requires two registers, with the | ||
629 | * high byte in the first register and the low byte in the second | ||
630 | * register. The first two limits are under limit values, followed | ||
631 | * by two over limit values. | ||
632 | * | ||
633 | * Limit register order matches the ADC register order, so we use | ||
634 | * ADC register defines throughout the code to index limit registers. | ||
635 | * | ||
636 | * We save the first retrieved value both as "critical" and "alarm" | ||
637 | * value. The second value overwrites either the critical or the | ||
638 | * alarm value, depending on its configuration. This ensures that both | ||
639 | * critical and alarm values are initialized, even if both registers are | ||
640 | * configured as critical or non-critical. | ||
641 | */ | ||
642 | for (i = 0; i < SMM665_NUM_ADC; i++) { | ||
643 | int val; | ||
644 | |||
645 | val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8); | ||
646 | if (unlikely(val < 0)) | ||
647 | goto out_unregister; | ||
648 | data->critical_min_limit[i] = data->alarm_min_limit[i] | ||
649 | = smm665_convert(val, i); | ||
650 | val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 2); | ||
651 | if (unlikely(val < 0)) | ||
652 | goto out_unregister; | ||
653 | if (smm665_is_critical(val)) | ||
654 | data->critical_min_limit[i] = smm665_convert(val, i); | ||
655 | else | ||
656 | data->alarm_min_limit[i] = smm665_convert(val, i); | ||
657 | val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 4); | ||
658 | if (unlikely(val < 0)) | ||
659 | goto out_unregister; | ||
660 | data->critical_max_limit[i] = data->alarm_max_limit[i] | ||
661 | = smm665_convert(val, i); | ||
662 | val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 6); | ||
663 | if (unlikely(val < 0)) | ||
664 | goto out_unregister; | ||
665 | if (smm665_is_critical(val)) | ||
666 | data->critical_max_limit[i] = smm665_convert(val, i); | ||
667 | else | ||
668 | data->alarm_max_limit[i] = smm665_convert(val, i); | ||
669 | } | ||
670 | |||
671 | /* Register sysfs hooks */ | ||
672 | ret = sysfs_create_group(&client->dev.kobj, &smm665_group); | ||
673 | if (ret) | ||
674 | goto out_unregister; | ||
675 | |||
676 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
677 | if (IS_ERR(data->hwmon_dev)) { | ||
678 | ret = PTR_ERR(data->hwmon_dev); | ||
679 | goto out_remove_group; | ||
680 | } | ||
681 | |||
682 | return 0; | ||
683 | |||
684 | out_remove_group: | ||
685 | sysfs_remove_group(&client->dev.kobj, &smm665_group); | ||
686 | out_unregister: | ||
687 | i2c_unregister_device(data->cmdreg); | ||
688 | out_kfree: | ||
689 | kfree(data); | ||
690 | out_return: | ||
691 | return ret; | ||
692 | } | ||
693 | |||
694 | static int smm665_remove(struct i2c_client *client) | ||
695 | { | ||
696 | struct smm665_data *data = i2c_get_clientdata(client); | ||
697 | |||
698 | i2c_unregister_device(data->cmdreg); | ||
699 | hwmon_device_unregister(data->hwmon_dev); | ||
700 | sysfs_remove_group(&client->dev.kobj, &smm665_group); | ||
701 | |||
702 | kfree(data); | ||
703 | |||
704 | return 0; | ||
705 | } | ||
706 | |||
707 | static const struct i2c_device_id smm665_id[] = { | ||
708 | {"smm465", smm465}, | ||
709 | {"smm665", smm665}, | ||
710 | {"smm665c", smm665c}, | ||
711 | {"smm764", smm764}, | ||
712 | {"smm766", smm766}, | ||
713 | {} | ||
714 | }; | ||
715 | |||
716 | MODULE_DEVICE_TABLE(i2c, smm665_id); | ||
717 | |||
718 | /* This is the driver that will be inserted */ | ||
719 | static struct i2c_driver smm665_driver = { | ||
720 | .driver = { | ||
721 | .name = "smm665", | ||
722 | }, | ||
723 | .probe = smm665_probe, | ||
724 | .remove = smm665_remove, | ||
725 | .id_table = smm665_id, | ||
726 | }; | ||
727 | |||
728 | static int __init smm665_init(void) | ||
729 | { | ||
730 | return i2c_add_driver(&smm665_driver); | ||
731 | } | ||
732 | |||
733 | static void __exit smm665_exit(void) | ||
734 | { | ||
735 | i2c_del_driver(&smm665_driver); | ||
736 | } | ||
737 | |||
738 | MODULE_AUTHOR("Guenter Roeck"); | ||
739 | MODULE_DESCRIPTION("SMM665 driver"); | ||
740 | MODULE_LICENSE("GPL"); | ||
741 | |||
742 | module_init(smm665_init); | ||
743 | module_exit(smm665_exit); | ||
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 64207df8da82..2de76cc08f61 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -506,15 +506,22 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, | |||
506 | return (flags & REQ_FAILED) ? -EIO : 0; | 506 | return (flags & REQ_FAILED) ? -EIO : 0; |
507 | } | 507 | } |
508 | 508 | ||
509 | static void ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd) | 509 | /* |
510 | * returns true if rq has been completed | ||
511 | */ | ||
512 | static bool ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd) | ||
510 | { | 513 | { |
511 | unsigned int nr_bytes = cmd->nbytes - cmd->nleft; | 514 | unsigned int nr_bytes = cmd->nbytes - cmd->nleft; |
512 | 515 | ||
513 | if (cmd->tf_flags & IDE_TFLAG_WRITE) | 516 | if (cmd->tf_flags & IDE_TFLAG_WRITE) |
514 | nr_bytes -= cmd->last_xfer_len; | 517 | nr_bytes -= cmd->last_xfer_len; |
515 | 518 | ||
516 | if (nr_bytes > 0) | 519 | if (nr_bytes > 0) { |
517 | ide_complete_rq(drive, 0, nr_bytes); | 520 | ide_complete_rq(drive, 0, nr_bytes); |
521 | return true; | ||
522 | } | ||
523 | |||
524 | return false; | ||
518 | } | 525 | } |
519 | 526 | ||
520 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | 527 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) |
@@ -679,7 +686,8 @@ out_end: | |||
679 | } | 686 | } |
680 | 687 | ||
681 | if (uptodate == 0 && rq->bio) | 688 | if (uptodate == 0 && rq->bio) |
682 | ide_cd_error_cmd(drive, cmd); | 689 | if (ide_cd_error_cmd(drive, cmd)) |
690 | return ide_stopped; | ||
683 | 691 | ||
684 | /* make sure it's fully ended */ | 692 | /* make sure it's fully ended */ |
685 | if (blk_fs_request(rq) == 0) { | 693 | if (blk_fs_request(rq) == 0) { |
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 67fb73559fd5..34b9872f35d1 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
@@ -480,13 +480,9 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg) | |||
480 | u16 nsect = 0; | 480 | u16 nsect = 0; |
481 | char __user *buf = (char __user *)arg; | 481 | char __user *buf = (char __user *)arg; |
482 | 482 | ||
483 | req_task = kzalloc(tasksize, GFP_KERNEL); | 483 | req_task = memdup_user(buf, tasksize); |
484 | if (req_task == NULL) | 484 | if (IS_ERR(req_task)) |
485 | return -ENOMEM; | 485 | return PTR_ERR(req_task); |
486 | if (copy_from_user(req_task, buf, tasksize)) { | ||
487 | kfree(req_task); | ||
488 | return -EFAULT; | ||
489 | } | ||
490 | 486 | ||
491 | taskout = req_task->out_size; | 487 | taskout = req_task->out_size; |
492 | taskin = req_task->in_size; | 488 | taskin = req_task->in_size; |
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index 1d80f1fdbc97..7002765b593c 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c | |||
@@ -64,7 +64,7 @@ static void tx4938ide_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) | |||
64 | 64 | ||
65 | pair = ide_get_pair_dev(drive); | 65 | pair = ide_get_pair_dev(drive); |
66 | if (pair) | 66 | if (pair) |
67 | safe = min(safe, pair->pio_mode - XFER_PIO_0); | 67 | safe = min_t(u8, safe, pair->pio_mode - XFER_PIO_0); |
68 | tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, safe); | 68 | tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, safe); |
69 | } | 69 | } |
70 | 70 | ||
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c index 3c7367751873..bed3e39aac96 100644 --- a/drivers/ide/tx4939ide.c +++ b/drivers/ide/tx4939ide.c | |||
@@ -114,7 +114,7 @@ static void tx4939ide_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) | |||
114 | 114 | ||
115 | pair = ide_get_pair_dev(drive); | 115 | pair = ide_get_pair_dev(drive); |
116 | if (pair) | 116 | if (pair) |
117 | safe = min(safe, pair->pio_mode - XFER_PIO_0); | 117 | safe = min_t(u8, safe, pair->pio_mode - XFER_PIO_0); |
118 | /* | 118 | /* |
119 | * Update Command Transfer Mode for master/slave and Data | 119 | * Update Command Transfer Mode for master/slave and Data |
120 | * Transfer Mode for this drive. | 120 | * Transfer Mode for this drive. |
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index 101f40022386..d2a0997b78f8 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c | |||
@@ -79,7 +79,7 @@ static struct via_isa_bridge { | |||
79 | { "vt8261", PCI_DEVICE_ID_VIA_8261, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 79 | { "vt8261", PCI_DEVICE_ID_VIA_8261, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, |
80 | { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 80 | { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, |
81 | { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 81 | { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, |
82 | { "vt6415", PCI_DEVICE_ID_VIA_6410, 0x00, 0xff, ATA_UDMA6, VIA_BAD_AST }, | 82 | { "vt6415", PCI_DEVICE_ID_VIA_6415, 0x00, 0xff, ATA_UDMA6, VIA_BAD_AST }, |
83 | { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 83 | { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, |
84 | { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 84 | { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, |
85 | { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, | 85 | { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST }, |
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index d870f9c17c1e..9bbf491d5d9e 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c | |||
@@ -250,12 +250,17 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev) | |||
250 | rdev->cqshift = PAGE_SHIFT - ilog2(rdev->lldi.ucq_density); | 250 | rdev->cqshift = PAGE_SHIFT - ilog2(rdev->lldi.ucq_density); |
251 | rdev->cqmask = rdev->lldi.ucq_density - 1; | 251 | rdev->cqmask = rdev->lldi.ucq_density - 1; |
252 | PDBG("%s dev %s stag start 0x%0x size 0x%0x num stags %d " | 252 | PDBG("%s dev %s stag start 0x%0x size 0x%0x num stags %d " |
253 | "pbl start 0x%0x size 0x%0x rq start 0x%0x size 0x%0x\n", | 253 | "pbl start 0x%0x size 0x%0x rq start 0x%0x size 0x%0x " |
254 | "qp qid start %u size %u cq qid start %u size %u\n", | ||
254 | __func__, pci_name(rdev->lldi.pdev), rdev->lldi.vr->stag.start, | 255 | __func__, pci_name(rdev->lldi.pdev), rdev->lldi.vr->stag.start, |
255 | rdev->lldi.vr->stag.size, c4iw_num_stags(rdev), | 256 | rdev->lldi.vr->stag.size, c4iw_num_stags(rdev), |
256 | rdev->lldi.vr->pbl.start, | 257 | rdev->lldi.vr->pbl.start, |
257 | rdev->lldi.vr->pbl.size, rdev->lldi.vr->rq.start, | 258 | rdev->lldi.vr->pbl.size, rdev->lldi.vr->rq.start, |
258 | rdev->lldi.vr->rq.size); | 259 | rdev->lldi.vr->rq.size, |
260 | rdev->lldi.vr->qp.start, | ||
261 | rdev->lldi.vr->qp.size, | ||
262 | rdev->lldi.vr->cq.start, | ||
263 | rdev->lldi.vr->cq.size); | ||
259 | PDBG("udb len 0x%x udb base %p db_reg %p gts_reg %p qpshift %lu " | 264 | PDBG("udb len 0x%x udb base %p db_reg %p gts_reg %p qpshift %lu " |
260 | "qpmask 0x%x cqshift %lu cqmask 0x%x\n", | 265 | "qpmask 0x%x cqshift %lu cqmask 0x%x\n", |
261 | (unsigned)pci_resource_len(rdev->lldi.pdev, 2), | 266 | (unsigned)pci_resource_len(rdev->lldi.pdev, 2), |
diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c index fb195d1d9015..83b23dfa250d 100644 --- a/drivers/infiniband/hw/cxgb4/resource.c +++ b/drivers/infiniband/hw/cxgb4/resource.c | |||
@@ -110,11 +110,12 @@ static int c4iw_init_qid_fifo(struct c4iw_rdev *rdev) | |||
110 | 110 | ||
111 | spin_lock_init(&rdev->resource.qid_fifo_lock); | 111 | spin_lock_init(&rdev->resource.qid_fifo_lock); |
112 | 112 | ||
113 | if (kfifo_alloc(&rdev->resource.qid_fifo, T4_MAX_QIDS * sizeof(u32), | 113 | if (kfifo_alloc(&rdev->resource.qid_fifo, rdev->lldi.vr->qp.size * |
114 | GFP_KERNEL)) | 114 | sizeof(u32), GFP_KERNEL)) |
115 | return -ENOMEM; | 115 | return -ENOMEM; |
116 | 116 | ||
117 | for (i = T4_QID_BASE; i < T4_QID_BASE + T4_MAX_QIDS; i++) | 117 | for (i = rdev->lldi.vr->qp.start; |
118 | i < rdev->lldi.vr->qp.start + rdev->lldi.vr->qp.size; i++) | ||
118 | if (!(i & rdev->qpmask)) | 119 | if (!(i & rdev->qpmask)) |
119 | kfifo_in(&rdev->resource.qid_fifo, | 120 | kfifo_in(&rdev->resource.qid_fifo, |
120 | (unsigned char *) &i, sizeof(u32)); | 121 | (unsigned char *) &i, sizeof(u32)); |
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h index aef55f42bea4..24f369046ef3 100644 --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h | |||
@@ -36,8 +36,6 @@ | |||
36 | #include "t4_msg.h" | 36 | #include "t4_msg.h" |
37 | #include "t4fw_ri_api.h" | 37 | #include "t4fw_ri_api.h" |
38 | 38 | ||
39 | #define T4_QID_BASE 1024 | ||
40 | #define T4_MAX_QIDS 256 | ||
41 | #define T4_MAX_NUM_QP (1<<16) | 39 | #define T4_MAX_NUM_QP (1<<16) |
42 | #define T4_MAX_NUM_CQ (1<<15) | 40 | #define T4_MAX_NUM_CQ (1<<15) |
43 | #define T4_MAX_NUM_PD (1<<15) | 41 | #define T4_MAX_NUM_PD (1<<15) |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 054edf346e0b..c908c5f83645 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -492,13 +492,15 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) | |||
492 | } | 492 | } |
493 | 493 | ||
494 | #define OLD_KEY_MAX 0x1ff | 494 | #define OLD_KEY_MAX 0x1ff |
495 | static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode) | 495 | static int handle_eviocgbit(struct input_dev *dev, |
496 | unsigned int type, unsigned int size, | ||
497 | void __user *p, int compat_mode) | ||
496 | { | 498 | { |
497 | static unsigned long keymax_warn_time; | 499 | static unsigned long keymax_warn_time; |
498 | unsigned long *bits; | 500 | unsigned long *bits; |
499 | int len; | 501 | int len; |
500 | 502 | ||
501 | switch (_IOC_NR(cmd) & EV_MAX) { | 503 | switch (type) { |
502 | 504 | ||
503 | case 0: bits = dev->evbit; len = EV_MAX; break; | 505 | case 0: bits = dev->evbit; len = EV_MAX; break; |
504 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | 506 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; |
@@ -517,7 +519,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user | |||
517 | * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len' | 519 | * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len' |
518 | * should be in bytes, not in bits. | 520 | * should be in bytes, not in bits. |
519 | */ | 521 | */ |
520 | if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) { | 522 | if (type == EV_KEY && size == OLD_KEY_MAX) { |
521 | len = OLD_KEY_MAX; | 523 | len = OLD_KEY_MAX; |
522 | if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) | 524 | if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) |
523 | printk(KERN_WARNING | 525 | printk(KERN_WARNING |
@@ -528,7 +530,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user | |||
528 | BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); | 530 | BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); |
529 | } | 531 | } |
530 | 532 | ||
531 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | 533 | return bits_to_user(bits, len, size, p, compat_mode); |
532 | } | 534 | } |
533 | #undef OLD_KEY_MAX | 535 | #undef OLD_KEY_MAX |
534 | 536 | ||
@@ -542,8 +544,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
542 | struct ff_effect effect; | 544 | struct ff_effect effect; |
543 | int __user *ip = (int __user *)p; | 545 | int __user *ip = (int __user *)p; |
544 | unsigned int i, t, u, v; | 546 | unsigned int i, t, u, v; |
547 | unsigned int size; | ||
545 | int error; | 548 | int error; |
546 | 549 | ||
550 | /* First we check for fixed-length commands */ | ||
547 | switch (cmd) { | 551 | switch (cmd) { |
548 | 552 | ||
549 | case EVIOCGVERSION: | 553 | case EVIOCGVERSION: |
@@ -610,112 +614,102 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
610 | return evdev_grab(evdev, client); | 614 | return evdev_grab(evdev, client); |
611 | else | 615 | else |
612 | return evdev_ungrab(evdev, client); | 616 | return evdev_ungrab(evdev, client); |
617 | } | ||
613 | 618 | ||
614 | default: | 619 | size = _IOC_SIZE(cmd); |
615 | |||
616 | if (_IOC_TYPE(cmd) != 'E') | ||
617 | return -EINVAL; | ||
618 | |||
619 | if (_IOC_DIR(cmd) == _IOC_READ) { | ||
620 | 620 | ||
621 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) | 621 | /* Now check variable-length commands */ |
622 | return handle_eviocgbit(dev, cmd, p, compat_mode); | 622 | #define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) |
623 | 623 | ||
624 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) | 624 | switch (EVIOC_MASK_SIZE(cmd)) { |
625 | return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), | ||
626 | p, compat_mode); | ||
627 | 625 | ||
628 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) | 626 | case EVIOCGKEY(0): |
629 | return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), | 627 | return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); |
630 | p, compat_mode); | ||
631 | 628 | ||
632 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) | 629 | case EVIOCGLED(0): |
633 | return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), | 630 | return bits_to_user(dev->led, LED_MAX, size, p, compat_mode); |
634 | p, compat_mode); | ||
635 | 631 | ||
636 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) | 632 | case EVIOCGSND(0): |
637 | return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), | 633 | return bits_to_user(dev->snd, SND_MAX, size, p, compat_mode); |
638 | p, compat_mode); | ||
639 | 634 | ||
640 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) | 635 | case EVIOCGSW(0): |
641 | return str_to_user(dev->name, _IOC_SIZE(cmd), p); | 636 | return bits_to_user(dev->sw, SW_MAX, size, p, compat_mode); |
642 | 637 | ||
643 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) | 638 | case EVIOCGNAME(0): |
644 | return str_to_user(dev->phys, _IOC_SIZE(cmd), p); | 639 | return str_to_user(dev->name, size, p); |
645 | 640 | ||
646 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) | 641 | case EVIOCGPHYS(0): |
647 | return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); | 642 | return str_to_user(dev->phys, size, p); |
648 | 643 | ||
649 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | 644 | case EVIOCGUNIQ(0): |
645 | return str_to_user(dev->uniq, size, p); | ||
650 | 646 | ||
651 | t = _IOC_NR(cmd) & ABS_MAX; | 647 | case EVIOC_MASK_SIZE(EVIOCSFF): |
648 | if (input_ff_effect_from_user(p, size, &effect)) | ||
649 | return -EFAULT; | ||
652 | 650 | ||
653 | abs.value = dev->abs[t]; | 651 | error = input_ff_upload(dev, &effect, file); |
654 | abs.minimum = dev->absmin[t]; | ||
655 | abs.maximum = dev->absmax[t]; | ||
656 | abs.fuzz = dev->absfuzz[t]; | ||
657 | abs.flat = dev->absflat[t]; | ||
658 | abs.resolution = dev->absres[t]; | ||
659 | 652 | ||
660 | if (copy_to_user(p, &abs, min_t(size_t, | 653 | if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) |
661 | _IOC_SIZE(cmd), | 654 | return -EFAULT; |
662 | sizeof(struct input_absinfo)))) | ||
663 | return -EFAULT; | ||
664 | 655 | ||
665 | return 0; | 656 | return error; |
666 | } | 657 | } |
667 | 658 | ||
668 | } | 659 | /* Multi-number variable-length handlers */ |
660 | if (_IOC_TYPE(cmd) != 'E') | ||
661 | return -EINVAL; | ||
669 | 662 | ||
670 | if (_IOC_DIR(cmd) == _IOC_WRITE) { | 663 | if (_IOC_DIR(cmd) == _IOC_READ) { |
671 | 664 | ||
672 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) { | 665 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) |
666 | return handle_eviocgbit(dev, | ||
667 | _IOC_NR(cmd) & EV_MAX, size, | ||
668 | p, compat_mode); | ||
673 | 669 | ||
674 | if (input_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect)) | 670 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { |
675 | return -EFAULT; | ||
676 | 671 | ||
677 | error = input_ff_upload(dev, &effect, file); | 672 | t = _IOC_NR(cmd) & ABS_MAX; |
673 | abs = dev->absinfo[t]; | ||
678 | 674 | ||
679 | if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) | 675 | if (copy_to_user(p, &abs, min_t(size_t, |
680 | return -EFAULT; | 676 | size, sizeof(struct input_absinfo)))) |
677 | return -EFAULT; | ||
681 | 678 | ||
682 | return error; | 679 | return 0; |
683 | } | 680 | } |
681 | } | ||
684 | 682 | ||
685 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | 683 | if (_IOC_DIR(cmd) == _IOC_READ) { |
686 | 684 | ||
687 | t = _IOC_NR(cmd) & ABS_MAX; | 685 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
688 | 686 | ||
689 | if (copy_from_user(&abs, p, min_t(size_t, | 687 | t = _IOC_NR(cmd) & ABS_MAX; |
690 | _IOC_SIZE(cmd), | ||
691 | sizeof(struct input_absinfo)))) | ||
692 | return -EFAULT; | ||
693 | 688 | ||
694 | /* We can't change number of reserved MT slots */ | 689 | if (copy_from_user(&abs, p, min_t(size_t, |
695 | if (t == ABS_MT_SLOT) | 690 | size, sizeof(struct input_absinfo)))) |
696 | return -EINVAL; | 691 | return -EFAULT; |
697 | 692 | ||
698 | /* | 693 | if (size < sizeof(struct input_absinfo)) |
699 | * Take event lock to ensure that we are not | 694 | abs.resolution = 0; |
700 | * changing device parameters in the middle | ||
701 | * of event. | ||
702 | */ | ||
703 | spin_lock_irq(&dev->event_lock); | ||
704 | 695 | ||
705 | dev->abs[t] = abs.value; | 696 | /* We can't change number of reserved MT slots */ |
706 | dev->absmin[t] = abs.minimum; | 697 | if (t == ABS_MT_SLOT) |
707 | dev->absmax[t] = abs.maximum; | 698 | return -EINVAL; |
708 | dev->absfuzz[t] = abs.fuzz; | ||
709 | dev->absflat[t] = abs.flat; | ||
710 | dev->absres[t] = _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ? | ||
711 | 0 : abs.resolution; | ||
712 | 699 | ||
713 | spin_unlock_irq(&dev->event_lock); | 700 | /* |
701 | * Take event lock to ensure that we are not | ||
702 | * changing device parameters in the middle | ||
703 | * of event. | ||
704 | */ | ||
705 | spin_lock_irq(&dev->event_lock); | ||
706 | dev->absinfo[t] = abs; | ||
707 | spin_unlock_irq(&dev->event_lock); | ||
714 | 708 | ||
715 | return 0; | 709 | return 0; |
716 | } | ||
717 | } | 710 | } |
718 | } | 711 | } |
712 | |||
719 | return -EINVAL; | 713 | return -EINVAL; |
720 | } | 714 | } |
721 | 715 | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index e1243b4b32a5..a9b025f4147a 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -182,7 +182,7 @@ static int input_handle_abs_event(struct input_dev *dev, | |||
182 | is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST; | 182 | is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST; |
183 | 183 | ||
184 | if (!is_mt_event) { | 184 | if (!is_mt_event) { |
185 | pold = &dev->abs[code]; | 185 | pold = &dev->absinfo[code].value; |
186 | } else if (dev->mt) { | 186 | } else if (dev->mt) { |
187 | struct input_mt_slot *mtslot = &dev->mt[dev->slot]; | 187 | struct input_mt_slot *mtslot = &dev->mt[dev->slot]; |
188 | pold = &mtslot->abs[code - ABS_MT_FIRST]; | 188 | pold = &mtslot->abs[code - ABS_MT_FIRST]; |
@@ -196,7 +196,7 @@ static int input_handle_abs_event(struct input_dev *dev, | |||
196 | 196 | ||
197 | if (pold) { | 197 | if (pold) { |
198 | *pval = input_defuzz_abs_event(*pval, *pold, | 198 | *pval = input_defuzz_abs_event(*pval, *pold, |
199 | dev->absfuzz[code]); | 199 | dev->absinfo[code].fuzz); |
200 | if (*pold == *pval) | 200 | if (*pold == *pval) |
201 | return INPUT_IGNORE_EVENT; | 201 | return INPUT_IGNORE_EVENT; |
202 | 202 | ||
@@ -204,8 +204,8 @@ static int input_handle_abs_event(struct input_dev *dev, | |||
204 | } | 204 | } |
205 | 205 | ||
206 | /* Flush pending "slot" event */ | 206 | /* Flush pending "slot" event */ |
207 | if (is_mt_event && dev->slot != dev->abs[ABS_MT_SLOT]) { | 207 | if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { |
208 | dev->abs[ABS_MT_SLOT] = dev->slot; | 208 | input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); |
209 | input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); | 209 | input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); |
210 | } | 210 | } |
211 | 211 | ||
@@ -391,6 +391,43 @@ void input_inject_event(struct input_handle *handle, | |||
391 | EXPORT_SYMBOL(input_inject_event); | 391 | EXPORT_SYMBOL(input_inject_event); |
392 | 392 | ||
393 | /** | 393 | /** |
394 | * input_alloc_absinfo - allocates array of input_absinfo structs | ||
395 | * @dev: the input device emitting absolute events | ||
396 | * | ||
397 | * If the absinfo struct the caller asked for is already allocated, this | ||
398 | * functions will not do anything. | ||
399 | */ | ||
400 | void input_alloc_absinfo(struct input_dev *dev) | ||
401 | { | ||
402 | if (!dev->absinfo) | ||
403 | dev->absinfo = kcalloc(ABS_CNT, sizeof(struct input_absinfo), | ||
404 | GFP_KERNEL); | ||
405 | |||
406 | WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__); | ||
407 | } | ||
408 | EXPORT_SYMBOL(input_alloc_absinfo); | ||
409 | |||
410 | void input_set_abs_params(struct input_dev *dev, unsigned int axis, | ||
411 | int min, int max, int fuzz, int flat) | ||
412 | { | ||
413 | struct input_absinfo *absinfo; | ||
414 | |||
415 | input_alloc_absinfo(dev); | ||
416 | if (!dev->absinfo) | ||
417 | return; | ||
418 | |||
419 | absinfo = &dev->absinfo[axis]; | ||
420 | absinfo->minimum = min; | ||
421 | absinfo->maximum = max; | ||
422 | absinfo->fuzz = fuzz; | ||
423 | absinfo->flat = flat; | ||
424 | |||
425 | dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis); | ||
426 | } | ||
427 | EXPORT_SYMBOL(input_set_abs_params); | ||
428 | |||
429 | |||
430 | /** | ||
394 | * input_grab_device - grabs device for exclusive use | 431 | * input_grab_device - grabs device for exclusive use |
395 | * @handle: input handle that wants to own the device | 432 | * @handle: input handle that wants to own the device |
396 | * | 433 | * |
@@ -1308,6 +1345,7 @@ static void input_dev_release(struct device *device) | |||
1308 | 1345 | ||
1309 | input_ff_destroy(dev); | 1346 | input_ff_destroy(dev); |
1310 | input_mt_destroy_slots(dev); | 1347 | input_mt_destroy_slots(dev); |
1348 | kfree(dev->absinfo); | ||
1311 | kfree(dev); | 1349 | kfree(dev); |
1312 | 1350 | ||
1313 | module_put(THIS_MODULE); | 1351 | module_put(THIS_MODULE); |
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 63834585c283..d85bd8a7967d 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -530,7 +530,7 @@ static int joydev_ioctl_common(struct joydev *joydev, | |||
530 | { | 530 | { |
531 | struct input_dev *dev = joydev->handle.dev; | 531 | struct input_dev *dev = joydev->handle.dev; |
532 | size_t len; | 532 | size_t len; |
533 | int i, j; | 533 | int i; |
534 | const char *name; | 534 | const char *name; |
535 | 535 | ||
536 | /* Process fixed-sized commands. */ | 536 | /* Process fixed-sized commands. */ |
@@ -562,12 +562,11 @@ static int joydev_ioctl_common(struct joydev *joydev, | |||
562 | case JSIOCSCORR: | 562 | case JSIOCSCORR: |
563 | if (copy_from_user(joydev->corr, argp, | 563 | if (copy_from_user(joydev->corr, argp, |
564 | sizeof(joydev->corr[0]) * joydev->nabs)) | 564 | sizeof(joydev->corr[0]) * joydev->nabs)) |
565 | return -EFAULT; | 565 | return -EFAULT; |
566 | 566 | ||
567 | for (i = 0; i < joydev->nabs; i++) { | 567 | for (i = 0; i < joydev->nabs; i++) { |
568 | j = joydev->abspam[i]; | 568 | int val = input_abs_get_val(dev, joydev->abspam[i]); |
569 | joydev->abs[i] = joydev_correct(dev->abs[j], | 569 | joydev->abs[i] = joydev_correct(val, &joydev->corr[i]); |
570 | &joydev->corr[i]); | ||
571 | } | 570 | } |
572 | return 0; | 571 | return 0; |
573 | 572 | ||
@@ -848,25 +847,27 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
848 | 847 | ||
849 | for (i = 0; i < joydev->nabs; i++) { | 848 | for (i = 0; i < joydev->nabs; i++) { |
850 | j = joydev->abspam[i]; | 849 | j = joydev->abspam[i]; |
851 | if (dev->absmax[j] == dev->absmin[j]) { | 850 | if (input_abs_get_max(dev, j) == input_abs_get_min(dev, j)) { |
852 | joydev->corr[i].type = JS_CORR_NONE; | 851 | joydev->corr[i].type = JS_CORR_NONE; |
853 | joydev->abs[i] = dev->abs[j]; | 852 | joydev->abs[i] = input_abs_get_val(dev, j); |
854 | continue; | 853 | continue; |
855 | } | 854 | } |
856 | joydev->corr[i].type = JS_CORR_BROKEN; | 855 | joydev->corr[i].type = JS_CORR_BROKEN; |
857 | joydev->corr[i].prec = dev->absfuzz[j]; | 856 | joydev->corr[i].prec = input_abs_get_fuzz(dev, j); |
858 | joydev->corr[i].coef[0] = | 857 | |
859 | (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j]; | 858 | t = (input_abs_get_max(dev, j) + input_abs_get_min(dev, j)) / 2; |
860 | joydev->corr[i].coef[1] = | 859 | joydev->corr[i].coef[0] = t - input_abs_get_flat(dev, j); |
861 | (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j]; | 860 | joydev->corr[i].coef[1] = t + input_abs_get_flat(dev, j); |
862 | 861 | ||
863 | t = (dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]; | 862 | t = (input_abs_get_max(dev, j) - input_abs_get_min(dev, j)) / 2 |
863 | - 2 * input_abs_get_flat(dev, j); | ||
864 | if (t) { | 864 | if (t) { |
865 | joydev->corr[i].coef[2] = (1 << 29) / t; | 865 | joydev->corr[i].coef[2] = (1 << 29) / t; |
866 | joydev->corr[i].coef[3] = (1 << 29) / t; | 866 | joydev->corr[i].coef[3] = (1 << 29) / t; |
867 | 867 | ||
868 | joydev->abs[i] = joydev_correct(dev->abs[j], | 868 | joydev->abs[i] = |
869 | joydev->corr + i); | 869 | joydev_correct(input_abs_get_val(dev, j), |
870 | joydev->corr + i); | ||
870 | } | 871 | } |
871 | } | 872 | } |
872 | 873 | ||
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index 6489f4010c4f..d259b41354b8 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c | |||
@@ -342,7 +342,8 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
342 | 342 | ||
343 | for (i = 0; i < 4; i++) { | 343 | for (i = 0; i < 4; i++) { |
344 | if (i < 2) | 344 | if (i < 2) |
345 | input_set_abs_params(input_dev, axes[i], 48, input_dev->abs[axes[i]] * 2 - 48, 0, 8); | 345 | input_set_abs_params(input_dev, axes[i], |
346 | 48, input_abs_get_val(input_dev, axes[i]) * 2 - 48, 0, 8); | ||
346 | else | 347 | else |
347 | input_set_abs_params(input_dev, axes[i], 2, 253, 0, 0); | 348 | input_set_abs_params(input_dev, axes[i], 2, 253, 0, 0); |
348 | input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); | 349 | input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); |
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index 89c4c084d4ad..b992fbf91f2f 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c | |||
@@ -452,7 +452,7 @@ static void adi_init_center(struct adi *adi) | |||
452 | for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) { | 452 | for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) { |
453 | 453 | ||
454 | t = adi->abs[i]; | 454 | t = adi->abs[i]; |
455 | x = adi->dev->abs[t]; | 455 | x = input_abs_get_val(adi->dev, t); |
456 | 456 | ||
457 | if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE) | 457 | if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE) |
458 | x = i < adi->axes10 ? 512 : 128; | 458 | x = i < adi->axes10 ? 512 : 128; |
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index 05022f07ec77..e90694fe0d5c 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c | |||
@@ -139,8 +139,8 @@ static int __init amijoy_init(void) | |||
139 | amijoy_dev[i]->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | | 139 | amijoy_dev[i]->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | |
140 | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 140 | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); |
141 | for (j = 0; j < 2; j++) { | 141 | for (j = 0; j < 2; j++) { |
142 | amijoy_dev[i]->absmin[ABS_X + j] = -1; | 142 | XXinput_set_abs_params(amijoy_dev[i], ABS_X + j, |
143 | amijoy_dev[i]->absmax[ABS_X + j] = 1; | 143 | -1, 1, 0, 0); |
144 | } | 144 | } |
145 | 145 | ||
146 | err = input_register_device(amijoy_dev[i]); | 146 | err = input_register_device(amijoy_dev[i]); |
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index 45ac70eae0aa..0536b1b2f018 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c | |||
@@ -318,11 +318,8 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
318 | for (i = 0; i < gf2k_axes[gf2k->id]; i++) | 318 | for (i = 0; i < gf2k_axes[gf2k->id]; i++) |
319 | set_bit(gf2k_abs[i], input_dev->absbit); | 319 | set_bit(gf2k_abs[i], input_dev->absbit); |
320 | 320 | ||
321 | for (i = 0; i < gf2k_hats[gf2k->id]; i++) { | 321 | for (i = 0; i < gf2k_hats[gf2k->id]; i++) |
322 | set_bit(ABS_HAT0X + i, input_dev->absbit); | 322 | input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); |
323 | input_dev->absmin[ABS_HAT0X + i] = -1; | ||
324 | input_dev->absmax[ABS_HAT0X + i] = 1; | ||
325 | } | ||
326 | 323 | ||
327 | for (i = 0; i < gf2k_joys[gf2k->id]; i++) | 324 | for (i = 0; i < gf2k_joys[gf2k->id]; i++) |
328 | set_bit(gf2k_btn_joy[i], input_dev->keybit); | 325 | set_bit(gf2k_btn_joy[i], input_dev->keybit); |
@@ -334,11 +331,14 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
334 | gf2k_read(gf2k, data); | 331 | gf2k_read(gf2k, data); |
335 | 332 | ||
336 | for (i = 0; i < gf2k_axes[gf2k->id]; i++) { | 333 | for (i = 0; i < gf2k_axes[gf2k->id]; i++) { |
337 | input_dev->absmax[gf2k_abs[i]] = (i < 2) ? input_dev->abs[gf2k_abs[i]] * 2 - 32 : | 334 | int max = i < 2 ? |
338 | input_dev->abs[gf2k_abs[0]] + input_dev->abs[gf2k_abs[1]] - 32; | 335 | input_abs_get_val(input_dev, gf2k_abs[i]) * 2 : |
339 | input_dev->absmin[gf2k_abs[i]] = 32; | 336 | input_abs_get_val(input_dev, gf2k_abs[0]) + |
340 | input_dev->absfuzz[gf2k_abs[i]] = 8; | 337 | input_abs_get_val(input_dev, gf2k_abs[1]); |
341 | input_dev->absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; | 338 | int flat = i < 2 ? 24 : 0; |
339 | |||
340 | input_set_abs_params(input_dev, gf2k_abs[i], | ||
341 | 32, max - 32, 8, flat); | ||
342 | } | 342 | } |
343 | 343 | ||
344 | err = input_register_device(gf2k->dev); | 344 | err = input_register_device(gf2k->dev); |
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index 2478289aeeea..16fb19d1ca25 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c | |||
@@ -270,18 +270,14 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d | |||
270 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 270 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
271 | 271 | ||
272 | for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) { | 272 | for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) { |
273 | set_bit(t, input_dev->absbit); | 273 | if (i < interact_type[interact->type].b8) |
274 | if (i < interact_type[interact->type].b8) { | 274 | input_set_abs_params(input_dev, t, 0, 255, 0, 0); |
275 | input_dev->absmin[t] = 0; | 275 | else |
276 | input_dev->absmax[t] = 255; | 276 | input_set_abs_params(input_dev, t, -1, 1, 0, 0); |
277 | } else { | ||
278 | input_dev->absmin[t] = -1; | ||
279 | input_dev->absmax[t] = 1; | ||
280 | } | ||
281 | } | 277 | } |
282 | 278 | ||
283 | for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++) | 279 | for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++) |
284 | set_bit(t, input_dev->keybit); | 280 | __set_bit(t, input_dev->keybit); |
285 | 281 | ||
286 | err = input_register_device(interact->dev); | 282 | err = input_register_device(interact->dev); |
287 | if (err) | 283 | if (err) |
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index ca13a6bec33e..b8d86115644b 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c | |||
@@ -761,17 +761,21 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
761 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 761 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
762 | 762 | ||
763 | for (j = 0; (bits = sw_bit[sw->type][j]); j++) { | 763 | for (j = 0; (bits = sw_bit[sw->type][j]); j++) { |
764 | int min, max, fuzz, flat; | ||
765 | |||
764 | code = sw_abs[sw->type][j]; | 766 | code = sw_abs[sw->type][j]; |
765 | set_bit(code, input_dev->absbit); | 767 | min = bits == 1 ? -1 : 0; |
766 | input_dev->absmax[code] = (1 << bits) - 1; | 768 | max = (1 << bits) - 1; |
767 | input_dev->absmin[code] = (bits == 1) ? -1 : 0; | 769 | fuzz = (bits >> 1) >= 2 ? 1 << ((bits >> 1) - 2) : 0; |
768 | input_dev->absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0; | 770 | flat = code == ABS_THROTTLE || bits < 5 ? |
769 | if (code != ABS_THROTTLE) | 771 | 0 : 1 << (bits - 5); |
770 | input_dev->absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0; | 772 | |
773 | input_set_abs_params(input_dev, code, | ||
774 | min, max, fuzz, flat); | ||
771 | } | 775 | } |
772 | 776 | ||
773 | for (j = 0; (code = sw_btn[sw->type][j]); j++) | 777 | for (j = 0; (code = sw_btn[sw->type][j]); j++) |
774 | set_bit(code, input_dev->keybit); | 778 | __set_bit(code, input_dev->keybit); |
775 | 779 | ||
776 | dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k); | 780 | dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k); |
777 | 781 | ||
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 269a846f3694..f9fb7fa10af3 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -148,6 +148,7 @@ static const struct xpad_device { | |||
148 | { 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX }, | 148 | { 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX }, |
149 | { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, | 149 | { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, |
150 | { 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, | 150 | { 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, |
151 | { 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, | ||
151 | { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, | 152 | { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, |
152 | { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, | 153 | { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, |
153 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, | 154 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, |
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index a9fd147f2ba7..6069abe31e42 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -39,6 +39,8 @@ struct gpio_keys_drvdata { | |||
39 | struct input_dev *input; | 39 | struct input_dev *input; |
40 | struct mutex disable_lock; | 40 | struct mutex disable_lock; |
41 | unsigned int n_buttons; | 41 | unsigned int n_buttons; |
42 | int (*enable)(struct device *dev); | ||
43 | void (*disable)(struct device *dev); | ||
42 | struct gpio_button_data data[0]; | 44 | struct gpio_button_data data[0]; |
43 | }; | 45 | }; |
44 | 46 | ||
@@ -423,6 +425,21 @@ fail2: | |||
423 | return error; | 425 | return error; |
424 | } | 426 | } |
425 | 427 | ||
428 | static int gpio_keys_open(struct input_dev *input) | ||
429 | { | ||
430 | struct gpio_keys_drvdata *ddata = input_get_drvdata(input); | ||
431 | |||
432 | return ddata->enable ? ddata->enable(input->dev.parent) : 0; | ||
433 | } | ||
434 | |||
435 | static void gpio_keys_close(struct input_dev *input) | ||
436 | { | ||
437 | struct gpio_keys_drvdata *ddata = input_get_drvdata(input); | ||
438 | |||
439 | if (ddata->disable) | ||
440 | ddata->disable(input->dev.parent); | ||
441 | } | ||
442 | |||
426 | static int __devinit gpio_keys_probe(struct platform_device *pdev) | 443 | static int __devinit gpio_keys_probe(struct platform_device *pdev) |
427 | { | 444 | { |
428 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 445 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
@@ -444,13 +461,18 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
444 | 461 | ||
445 | ddata->input = input; | 462 | ddata->input = input; |
446 | ddata->n_buttons = pdata->nbuttons; | 463 | ddata->n_buttons = pdata->nbuttons; |
464 | ddata->enable = pdata->enable; | ||
465 | ddata->disable = pdata->disable; | ||
447 | mutex_init(&ddata->disable_lock); | 466 | mutex_init(&ddata->disable_lock); |
448 | 467 | ||
449 | platform_set_drvdata(pdev, ddata); | 468 | platform_set_drvdata(pdev, ddata); |
469 | input_set_drvdata(input, ddata); | ||
450 | 470 | ||
451 | input->name = pdev->name; | 471 | input->name = pdev->name; |
452 | input->phys = "gpio-keys/input0"; | 472 | input->phys = "gpio-keys/input0"; |
453 | input->dev.parent = &pdev->dev; | 473 | input->dev.parent = &pdev->dev; |
474 | input->open = gpio_keys_open; | ||
475 | input->close = gpio_keys_close; | ||
454 | 476 | ||
455 | input->id.bustype = BUS_HOST; | 477 | input->id.bustype = BUS_HOST; |
456 | input->id.vendor = 0x0001; | 478 | input->id.vendor = 0x0001; |
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index c83f4b2ec7d3..ddd5afd301d4 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c | |||
@@ -232,15 +232,16 @@ static void hil_dev_handle_ptr_events(struct hil_dev *ptr) | |||
232 | if (absdev) { | 232 | if (absdev) { |
233 | val = lo + (hi << 8); | 233 | val = lo + (hi << 8); |
234 | #ifdef TABLET_AUTOADJUST | 234 | #ifdef TABLET_AUTOADJUST |
235 | if (val < dev->absmin[ABS_X + i]) | 235 | if (val < input_abs_min(dev, ABS_X + i)) |
236 | dev->absmin[ABS_X + i] = val; | 236 | input_abs_set_min(dev, ABS_X + i, val); |
237 | if (val > dev->absmax[ABS_X + i]) | 237 | if (val > input_abs_max(dev, ABS_X + i)) |
238 | dev->absmax[ABS_X + i] = val; | 238 | XXinput_abs_set_max(dev, ABS_X + i, val); |
239 | #endif | 239 | #endif |
240 | if (i%3) val = dev->absmax[ABS_X + i] - val; | 240 | if (i % 3) |
241 | val = input_abs_max(dev, ABS_X + i) - val; | ||
241 | input_report_abs(dev, ABS_X + i, val); | 242 | input_report_abs(dev, ABS_X + i, val); |
242 | } else { | 243 | } else { |
243 | val = (int) (((int8_t)lo) | ((int8_t)hi << 8)); | 244 | val = (int) (((int8_t) lo) | ((int8_t) hi << 8)); |
244 | if (i % 3) | 245 | if (i % 3) |
245 | val *= -1; | 246 | val *= -1; |
246 | input_report_rel(dev, REL_X + i, val); | 247 | input_report_rel(dev, REL_X + i, val); |
@@ -387,9 +388,11 @@ static void hil_dev_pointer_setup(struct hil_dev *ptr) | |||
387 | 388 | ||
388 | #ifdef TABLET_AUTOADJUST | 389 | #ifdef TABLET_AUTOADJUST |
389 | for (i = 0; i < ABS_MAX; i++) { | 390 | for (i = 0; i < ABS_MAX; i++) { |
390 | int diff = input_dev->absmax[ABS_X + i] / 10; | 391 | int diff = input_abs_max(input_dev, ABS_X + i) / 10; |
391 | input_dev->absmin[ABS_X + i] += diff; | 392 | input_abs_set_min(input_dev, ABS_X + i, |
392 | input_dev->absmax[ABS_X + i] -= diff; | 393 | input_abs_min(input_dev, ABS_X + i) + diff) |
394 | XXinput_abs_set_max(input_dev, ABS_X + i, | ||
395 | input_abs_max(input_dev, ABS_X + i) - diff) | ||
393 | } | 396 | } |
394 | #endif | 397 | #endif |
395 | 398 | ||
diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index e2ca01708080..de5900d50788 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c | |||
@@ -724,7 +724,6 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, | |||
724 | pdata = &ac->pdata; | 724 | pdata = &ac->pdata; |
725 | 725 | ||
726 | ac->input = input_dev; | 726 | ac->input = input_dev; |
727 | ac->disabled = true; | ||
728 | ac->dev = dev; | 727 | ac->dev = dev; |
729 | ac->irq = irq; | 728 | ac->irq = irq; |
730 | ac->bops = bops; | 729 | ac->bops = bops; |
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index b71eb55f2dbc..bb53fd33cd1c 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
@@ -304,21 +304,25 @@ static int uinput_validate_absbits(struct input_dev *dev) | |||
304 | if (!test_bit(cnt, dev->absbit)) | 304 | if (!test_bit(cnt, dev->absbit)) |
305 | continue; | 305 | continue; |
306 | 306 | ||
307 | if ((dev->absmax[cnt] <= dev->absmin[cnt])) { | 307 | if (input_abs_get_max(dev, cnt) <= input_abs_get_min(dev, cnt)) { |
308 | printk(KERN_DEBUG | 308 | printk(KERN_DEBUG |
309 | "%s: invalid abs[%02x] min:%d max:%d\n", | 309 | "%s: invalid abs[%02x] min:%d max:%d\n", |
310 | UINPUT_NAME, cnt, | 310 | UINPUT_NAME, cnt, |
311 | dev->absmin[cnt], dev->absmax[cnt]); | 311 | input_abs_get_min(dev, cnt), |
312 | input_abs_get_max(dev, cnt)); | ||
312 | retval = -EINVAL; | 313 | retval = -EINVAL; |
313 | break; | 314 | break; |
314 | } | 315 | } |
315 | 316 | ||
316 | if (dev->absflat[cnt] > (dev->absmax[cnt] - dev->absmin[cnt])) { | 317 | if (input_abs_get_flat(dev, cnt) > |
318 | input_abs_get_max(dev, cnt) - input_abs_get_min(dev, cnt)) { | ||
317 | printk(KERN_DEBUG | 319 | printk(KERN_DEBUG |
318 | "%s: absflat[%02x] out of range: %d " | 320 | "%s: abs_flat #%02x out of range: %d " |
319 | "(min:%d/max:%d)\n", | 321 | "(min:%d/max:%d)\n", |
320 | UINPUT_NAME, cnt, dev->absflat[cnt], | 322 | UINPUT_NAME, cnt, |
321 | dev->absmin[cnt], dev->absmax[cnt]); | 323 | input_abs_get_flat(dev, cnt), |
324 | input_abs_get_min(dev, cnt), | ||
325 | input_abs_get_max(dev, cnt)); | ||
322 | retval = -EINVAL; | 326 | retval = -EINVAL; |
323 | break; | 327 | break; |
324 | } | 328 | } |
@@ -343,7 +347,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu | |||
343 | struct uinput_user_dev *user_dev; | 347 | struct uinput_user_dev *user_dev; |
344 | struct input_dev *dev; | 348 | struct input_dev *dev; |
345 | char *name; | 349 | char *name; |
346 | int size; | 350 | int i, size; |
347 | int retval; | 351 | int retval; |
348 | 352 | ||
349 | if (count != sizeof(struct uinput_user_dev)) | 353 | if (count != sizeof(struct uinput_user_dev)) |
@@ -387,11 +391,12 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu | |||
387 | dev->id.product = user_dev->id.product; | 391 | dev->id.product = user_dev->id.product; |
388 | dev->id.version = user_dev->id.version; | 392 | dev->id.version = user_dev->id.version; |
389 | 393 | ||
390 | size = sizeof(int) * ABS_CNT; | 394 | for (i = 0; i < ABS_CNT; i++) { |
391 | memcpy(dev->absmax, user_dev->absmax, size); | 395 | input_abs_set_max(dev, i, user_dev->absmax[i]); |
392 | memcpy(dev->absmin, user_dev->absmin, size); | 396 | input_abs_set_min(dev, i, user_dev->absmin[i]); |
393 | memcpy(dev->absfuzz, user_dev->absfuzz, size); | 397 | input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]); |
394 | memcpy(dev->absflat, user_dev->absflat, size); | 398 | input_abs_set_flat(dev, i, user_dev->absflat[i]); |
399 | } | ||
395 | 400 | ||
396 | /* check if absmin/absmax/absfuzz/absflat are filled as | 401 | /* check if absmin/absmax/absfuzz/absflat are filled as |
397 | * told in Documentation/input/input-programming.txt */ | 402 | * told in Documentation/input/input-programming.txt */ |
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 05edd75abca0..a9cf76831634 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
@@ -205,8 +205,8 @@ struct atp { | |||
205 | bool overflow_warned; | 205 | bool overflow_warned; |
206 | int x_old; /* last reported x/y, */ | 206 | int x_old; /* last reported x/y, */ |
207 | int y_old; /* used for smoothing */ | 207 | int y_old; /* used for smoothing */ |
208 | u8 xy_cur[ATP_XSENSORS + ATP_YSENSORS]; | 208 | signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; |
209 | u8 xy_old[ATP_XSENSORS + ATP_YSENSORS]; | 209 | signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; |
210 | int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; | 210 | int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; |
211 | int idlecount; /* number of empty packets */ | 211 | int idlecount; /* number of empty packets */ |
212 | struct work_struct work; | 212 | struct work_struct work; |
@@ -531,7 +531,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
531 | 531 | ||
532 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { | 532 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { |
533 | /* accumulate the change */ | 533 | /* accumulate the change */ |
534 | int change = dev->xy_old[i] - dev->xy_cur[i]; | 534 | signed char change = dev->xy_old[i] - dev->xy_cur[i]; |
535 | dev->xy_acc[i] -= change; | 535 | dev->xy_acc[i] -= change; |
536 | 536 | ||
537 | /* prevent down drifting */ | 537 | /* prevent down drifting */ |
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index b18862b2a70e..48311204ba51 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -185,7 +185,6 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
185 | struct elantech_data *etd = psmouse->private; | 185 | struct elantech_data *etd = psmouse->private; |
186 | unsigned char *packet = psmouse->packet; | 186 | unsigned char *packet = psmouse->packet; |
187 | int fingers; | 187 | int fingers; |
188 | static int old_fingers; | ||
189 | 188 | ||
190 | if (etd->fw_version < 0x020000) { | 189 | if (etd->fw_version < 0x020000) { |
191 | /* | 190 | /* |
@@ -203,10 +202,13 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
203 | } | 202 | } |
204 | 203 | ||
205 | if (etd->jumpy_cursor) { | 204 | if (etd->jumpy_cursor) { |
206 | /* Discard packets that are likely to have bogus coordinates */ | 205 | if (fingers != 1) { |
207 | if (fingers > old_fingers) { | 206 | etd->single_finger_reports = 0; |
207 | } else if (etd->single_finger_reports < 2) { | ||
208 | /* Discard first 2 reports of one finger, bogus */ | ||
209 | etd->single_finger_reports++; | ||
208 | elantech_debug("discarding packet\n"); | 210 | elantech_debug("discarding packet\n"); |
209 | goto discard_packet_v1; | 211 | return; |
210 | } | 212 | } |
211 | } | 213 | } |
212 | 214 | ||
@@ -238,9 +240,6 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
238 | } | 240 | } |
239 | 241 | ||
240 | input_sync(dev); | 242 | input_sync(dev); |
241 | |||
242 | discard_packet_v1: | ||
243 | old_fingers = fingers; | ||
244 | } | 243 | } |
245 | 244 | ||
246 | /* | 245 | /* |
@@ -258,6 +257,14 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
258 | input_report_key(dev, BTN_TOUCH, fingers != 0); | 257 | input_report_key(dev, BTN_TOUCH, fingers != 0); |
259 | 258 | ||
260 | switch (fingers) { | 259 | switch (fingers) { |
260 | case 3: | ||
261 | /* | ||
262 | * Same as one finger, except report of more than 3 fingers: | ||
263 | * byte 3: n4 . w1 w0 . . . . | ||
264 | */ | ||
265 | if (packet[3] & 0x80) | ||
266 | fingers = 4; | ||
267 | /* pass through... */ | ||
261 | case 1: | 268 | case 1: |
262 | /* | 269 | /* |
263 | * byte 1: . . . . . x10 x9 x8 | 270 | * byte 1: . . . . . x10 x9 x8 |
@@ -310,6 +317,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
310 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | 317 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
311 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); | 318 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); |
312 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); | 319 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); |
320 | input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); | ||
313 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | 321 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
314 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | 322 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
315 | 323 | ||
@@ -467,6 +475,7 @@ static void elantech_set_input_params(struct psmouse *psmouse) | |||
467 | break; | 475 | break; |
468 | 476 | ||
469 | case 2: | 477 | case 2: |
478 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | ||
470 | input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); | 479 | input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); |
471 | input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); | 480 | input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); |
472 | input_set_abs_params(dev, ABS_HAT0X, ETP_2FT_XMIN, ETP_2FT_XMAX, 0, 0); | 481 | input_set_abs_params(dev, ABS_HAT0X, ETP_2FT_XMIN, ETP_2FT_XMAX, 0, 0); |
@@ -733,13 +742,13 @@ int elantech_init(struct psmouse *psmouse) | |||
733 | etd->capabilities = param[0]; | 742 | etd->capabilities = param[0]; |
734 | 743 | ||
735 | /* | 744 | /* |
736 | * This firmware seems to suffer from misreporting coordinates when | 745 | * This firmware suffers from misreporting coordinates when |
737 | * a touch action starts causing the mouse cursor or scrolled page | 746 | * a touch action starts causing the mouse cursor or scrolled page |
738 | * to jump. Enable a workaround. | 747 | * to jump. Enable a workaround. |
739 | */ | 748 | */ |
740 | if (etd->fw_version == 0x020022) { | 749 | if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) { |
741 | pr_info("firmware version 2.0.34 detected, enabling jumpy cursor workaround\n"); | 750 | pr_info("firmware version 2.0.34/2.6.0 detected, enabling jumpy cursor workaround\n"); |
742 | etd->jumpy_cursor = 1; | 751 | etd->jumpy_cursor = true; |
743 | } | 752 | } |
744 | 753 | ||
745 | if (elantech_set_absolute_mode(psmouse)) { | 754 | if (elantech_set_absolute_mode(psmouse)) { |
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index ac57bde1bb9f..aa4aac5d2198 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
@@ -100,10 +100,11 @@ struct elantech_data { | |||
100 | unsigned char reg_26; | 100 | unsigned char reg_26; |
101 | unsigned char debug; | 101 | unsigned char debug; |
102 | unsigned char capabilities; | 102 | unsigned char capabilities; |
103 | unsigned char paritycheck; | 103 | bool paritycheck; |
104 | unsigned char jumpy_cursor; | 104 | bool jumpy_cursor; |
105 | unsigned char hw_version; | 105 | unsigned char hw_version; |
106 | unsigned int fw_version; | 106 | unsigned int fw_version; |
107 | unsigned int single_finger_reports; | ||
107 | unsigned char parity[256]; | 108 | unsigned char parity[256]; |
108 | }; | 109 | }; |
109 | 110 | ||
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c index 3941f97cfa60..7b02b652e267 100644 --- a/drivers/input/mouse/pc110pad.c +++ b/drivers/input/mouse/pc110pad.c | |||
@@ -145,8 +145,8 @@ static int __init pc110pad_init(void) | |||
145 | pc110pad_dev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y); | 145 | pc110pad_dev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y); |
146 | pc110pad_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 146 | pc110pad_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
147 | 147 | ||
148 | pc110pad_dev->absmax[ABS_X] = 0x1ff; | 148 | input_abs_set_max(pc110pad_dev, ABS_X, 0x1ff); |
149 | pc110pad_dev->absmax[ABS_Y] = 0x0ff; | 149 | input_abs_set_max(pc110pad_dev, ABS_Y, 0x0ff); |
150 | 150 | ||
151 | pc110pad_dev->open = pc110pad_open; | 151 | pc110pad_dev->open = pc110pad_open; |
152 | pc110pad_dev->close = pc110pad_close; | 152 | pc110pad_dev->close = pc110pad_close; |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 8c324403b9f2..96b70a43515f 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -635,8 +635,8 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
635 | __clear_bit(REL_X, dev->relbit); | 635 | __clear_bit(REL_X, dev->relbit); |
636 | __clear_bit(REL_Y, dev->relbit); | 636 | __clear_bit(REL_Y, dev->relbit); |
637 | 637 | ||
638 | dev->absres[ABS_X] = priv->x_res; | 638 | input_abs_set_res(dev, ABS_X, priv->x_res); |
639 | dev->absres[ABS_Y] = priv->y_res; | 639 | input_abs_set_res(dev, ABS_Y, priv->y_res); |
640 | 640 | ||
641 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | 641 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { |
642 | /* Clickpads report only left button */ | 642 | /* Clickpads report only left button */ |
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index d8f68f77007b..83c24cca234a 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/random.h> | 22 | #include <linux/random.h> |
23 | #include <linux/major.h> | 23 | #include <linux/major.h> |
24 | #include <linux/device.h> | 24 | #include <linux/device.h> |
25 | #include <linux/kernel.h> | ||
25 | #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX | 26 | #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX |
26 | #include <linux/miscdevice.h> | 27 | #include <linux/miscdevice.h> |
27 | #endif | 28 | #endif |
@@ -134,11 +135,14 @@ static void mousedev_touchpad_event(struct input_dev *dev, | |||
134 | switch (code) { | 135 | switch (code) { |
135 | 136 | ||
136 | case ABS_X: | 137 | case ABS_X: |
138 | |||
137 | fx(0) = value; | 139 | fx(0) = value; |
138 | if (mousedev->touch && mousedev->pkt_count >= 2) { | 140 | if (mousedev->touch && mousedev->pkt_count >= 2) { |
139 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; | 141 | size = input_abs_get_min(dev, ABS_X) - |
142 | input_abs_get_max(dev, ABS_X); | ||
140 | if (size == 0) | 143 | if (size == 0) |
141 | size = 256 * 2; | 144 | size = 256 * 2; |
145 | |||
142 | tmp = ((value - fx(2)) * 256 * FRACTION_DENOM) / size; | 146 | tmp = ((value - fx(2)) * 256 * FRACTION_DENOM) / size; |
143 | tmp += mousedev->frac_dx; | 147 | tmp += mousedev->frac_dx; |
144 | mousedev->packet.dx = tmp / FRACTION_DENOM; | 148 | mousedev->packet.dx = tmp / FRACTION_DENOM; |
@@ -150,10 +154,12 @@ static void mousedev_touchpad_event(struct input_dev *dev, | |||
150 | case ABS_Y: | 154 | case ABS_Y: |
151 | fy(0) = value; | 155 | fy(0) = value; |
152 | if (mousedev->touch && mousedev->pkt_count >= 2) { | 156 | if (mousedev->touch && mousedev->pkt_count >= 2) { |
153 | /* use X size to keep the same scale */ | 157 | /* use X size for ABS_Y to keep the same scale */ |
154 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; | 158 | size = input_abs_get_min(dev, ABS_X) - |
159 | input_abs_get_max(dev, ABS_X); | ||
155 | if (size == 0) | 160 | if (size == 0) |
156 | size = 256 * 2; | 161 | size = 256 * 2; |
162 | |||
157 | tmp = -((value - fy(2)) * 256 * FRACTION_DENOM) / size; | 163 | tmp = -((value - fy(2)) * 256 * FRACTION_DENOM) / size; |
158 | tmp += mousedev->frac_dy; | 164 | tmp += mousedev->frac_dy; |
159 | mousedev->packet.dy = tmp / FRACTION_DENOM; | 165 | mousedev->packet.dy = tmp / FRACTION_DENOM; |
@@ -167,33 +173,35 @@ static void mousedev_touchpad_event(struct input_dev *dev, | |||
167 | static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, | 173 | static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, |
168 | unsigned int code, int value) | 174 | unsigned int code, int value) |
169 | { | 175 | { |
170 | int size; | 176 | int min, max, size; |
171 | 177 | ||
172 | switch (code) { | 178 | switch (code) { |
173 | 179 | ||
174 | case ABS_X: | 180 | case ABS_X: |
175 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; | 181 | min = input_abs_get_min(dev, ABS_X); |
182 | max = input_abs_get_max(dev, ABS_X); | ||
183 | |||
184 | size = max - min; | ||
176 | if (size == 0) | 185 | if (size == 0) |
177 | size = xres ? : 1; | 186 | size = xres ? : 1; |
178 | if (value > dev->absmax[ABS_X]) | 187 | |
179 | value = dev->absmax[ABS_X]; | 188 | clamp(value, min, max); |
180 | if (value < dev->absmin[ABS_X]) | 189 | |
181 | value = dev->absmin[ABS_X]; | 190 | mousedev->packet.x = ((value - min) * xres) / size; |
182 | mousedev->packet.x = | ||
183 | ((value - dev->absmin[ABS_X]) * xres) / size; | ||
184 | mousedev->packet.abs_event = 1; | 191 | mousedev->packet.abs_event = 1; |
185 | break; | 192 | break; |
186 | 193 | ||
187 | case ABS_Y: | 194 | case ABS_Y: |
188 | size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; | 195 | min = input_abs_get_min(dev, ABS_Y); |
196 | max = input_abs_get_max(dev, ABS_Y); | ||
197 | |||
198 | size = max - min; | ||
189 | if (size == 0) | 199 | if (size == 0) |
190 | size = yres ? : 1; | 200 | size = yres ? : 1; |
191 | if (value > dev->absmax[ABS_Y]) | 201 | |
192 | value = dev->absmax[ABS_Y]; | 202 | clamp(value, min, max); |
193 | if (value < dev->absmin[ABS_Y]) | 203 | |
194 | value = dev->absmin[ABS_Y]; | 204 | mousedev->packet.y = yres - ((value - min) * yres) / size; |
195 | mousedev->packet.y = yres - | ||
196 | ((value - dev->absmin[ABS_Y]) * yres) / size; | ||
197 | mousedev->packet.abs_event = 1; | 205 | mousedev->packet.abs_event = 1; |
198 | break; | 206 | break; |
199 | } | 207 | } |
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 51b80b08d467..57b25b84d1fc 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c | |||
@@ -987,20 +987,17 @@ static int aiptek_program_tablet(struct aiptek *aiptek) | |||
987 | /* Query getXextension */ | 987 | /* Query getXextension */ |
988 | if ((ret = aiptek_query(aiptek, 0x01, 0x00)) < 0) | 988 | if ((ret = aiptek_query(aiptek, 0x01, 0x00)) < 0) |
989 | return ret; | 989 | return ret; |
990 | aiptek->inputdev->absmin[ABS_X] = 0; | 990 | input_set_abs_params(aiptek->inputdev, ABS_X, 0, ret - 1, 0, 0); |
991 | aiptek->inputdev->absmax[ABS_X] = ret - 1; | ||
992 | 991 | ||
993 | /* Query getYextension */ | 992 | /* Query getYextension */ |
994 | if ((ret = aiptek_query(aiptek, 0x01, 0x01)) < 0) | 993 | if ((ret = aiptek_query(aiptek, 0x01, 0x01)) < 0) |
995 | return ret; | 994 | return ret; |
996 | aiptek->inputdev->absmin[ABS_Y] = 0; | 995 | input_set_abs_params(aiptek->inputdev, ABS_Y, 0, ret - 1, 0, 0); |
997 | aiptek->inputdev->absmax[ABS_Y] = ret - 1; | ||
998 | 996 | ||
999 | /* Query getPressureLevels */ | 997 | /* Query getPressureLevels */ |
1000 | if ((ret = aiptek_query(aiptek, 0x08, 0x00)) < 0) | 998 | if ((ret = aiptek_query(aiptek, 0x08, 0x00)) < 0) |
1001 | return ret; | 999 | return ret; |
1002 | aiptek->inputdev->absmin[ABS_PRESSURE] = 0; | 1000 | input_set_abs_params(aiptek->inputdev, ABS_PRESSURE, 0, ret - 1, 0, 0); |
1003 | aiptek->inputdev->absmax[ABS_PRESSURE] = ret - 1; | ||
1004 | 1001 | ||
1005 | /* Depending on whether we are in absolute or relative mode, we will | 1002 | /* Depending on whether we are in absolute or relative mode, we will |
1006 | * do a switchToTablet(absolute) or switchToMouse(relative) command. | 1003 | * do a switchToTablet(absolute) or switchToMouse(relative) command. |
@@ -1054,8 +1051,8 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr | |||
1054 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1051 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1055 | 1052 | ||
1056 | return snprintf(buf, PAGE_SIZE, "%dx%d\n", | 1053 | return snprintf(buf, PAGE_SIZE, "%dx%d\n", |
1057 | aiptek->inputdev->absmax[ABS_X] + 1, | 1054 | input_abs_get_max(aiptek->inputdev, ABS_X) + 1, |
1058 | aiptek->inputdev->absmax[ABS_Y] + 1); | 1055 | input_abs_get_max(aiptek->inputdev, ABS_Y) + 1); |
1059 | } | 1056 | } |
1060 | 1057 | ||
1061 | /* These structs define the sysfs files, param #1 is the name of the | 1058 | /* These structs define the sysfs files, param #1 is the name of the |
@@ -1843,7 +1840,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1843 | for (i = 0; i < ARRAY_SIZE(speeds); ++i) { | 1840 | for (i = 0; i < ARRAY_SIZE(speeds); ++i) { |
1844 | aiptek->curSetting.programmableDelay = speeds[i]; | 1841 | aiptek->curSetting.programmableDelay = speeds[i]; |
1845 | (void)aiptek_program_tablet(aiptek); | 1842 | (void)aiptek_program_tablet(aiptek); |
1846 | if (aiptek->inputdev->absmax[ABS_X] > 0) { | 1843 | if (input_abs_get_max(aiptek->inputdev, ABS_X) > 0) { |
1847 | dev_info(&intf->dev, | 1844 | dev_info(&intf->dev, |
1848 | "Aiptek using %d ms programming speed\n", | 1845 | "Aiptek using %d ms programming speed\n", |
1849 | aiptek->curSetting.programmableDelay); | 1846 | aiptek->curSetting.programmableDelay); |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index ce0b4608dad9..40d77ba8fdc1 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -687,10 +687,10 @@ static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx) | |||
687 | * protocol. | 687 | * protocol. |
688 | */ | 688 | */ |
689 | if (wacom->last_finger != finger) { | 689 | if (wacom->last_finger != finger) { |
690 | if (x == input->abs[ABS_X]) | 690 | if (x == input_abs_get_val(input, ABS_X)) |
691 | x++; | 691 | x++; |
692 | 692 | ||
693 | if (y == input->abs[ABS_Y]) | 693 | if (y == input_abs_get_val(input, ABS_Y)) |
694 | y++; | 694 | y++; |
695 | } | 695 | } |
696 | 696 | ||
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index 4eb7df0b7f87..5ec0946938fe 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c | |||
@@ -75,7 +75,7 @@ static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg, | |||
75 | unsigned char len, unsigned char *value) | 75 | unsigned char len, unsigned char *value) |
76 | { | 76 | { |
77 | struct i2c_client *client = tsc->client; | 77 | struct i2c_client *client = tsc->client; |
78 | unsigned int ret; | 78 | int ret; |
79 | unsigned char i2c_data[6]; | 79 | unsigned char i2c_data[6]; |
80 | 80 | ||
81 | BUG_ON(len > 5); | 81 | BUG_ON(len > 5); |
@@ -86,7 +86,7 @@ static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg, | |||
86 | ret = i2c_master_send(client, i2c_data, len + 1); | 86 | ret = i2c_master_send(client, i2c_data, len + 1); |
87 | if (ret != 1) { | 87 | if (ret != 1) { |
88 | dev_err(&client->dev, "i2c write data cmd failed\n"); | 88 | dev_err(&client->dev, "i2c write data cmd failed\n"); |
89 | return ret; | 89 | return ret ? ret : -EIO; |
90 | } | 90 | } |
91 | 91 | ||
92 | return 0; | 92 | return 0; |
@@ -96,7 +96,7 @@ static int cy8ctmg110_read_regs(struct cy8ctmg110 *tsc, | |||
96 | unsigned char *data, unsigned char len, unsigned char cmd) | 96 | unsigned char *data, unsigned char len, unsigned char cmd) |
97 | { | 97 | { |
98 | struct i2c_client *client = tsc->client; | 98 | struct i2c_client *client = tsc->client; |
99 | unsigned int ret; | 99 | int ret; |
100 | struct i2c_msg msg[2] = { | 100 | struct i2c_msg msg[2] = { |
101 | /* first write slave position to i2c devices */ | 101 | /* first write slave position to i2c devices */ |
102 | { client->addr, 0, 1, &cmd }, | 102 | { client->addr, 0, 1, &cmd }, |
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 0ded3640b926..707d9c94cf9e 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c | |||
@@ -1914,11 +1914,13 @@ static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb) | |||
1914 | * The next command will reopen the AT channel automatically. | 1914 | * The next command will reopen the AT channel automatically. |
1915 | */ | 1915 | */ |
1916 | if (cb->len == 3 && !memcmp(cb->buf, "+++", 3)) { | 1916 | if (cb->len == 3 && !memcmp(cb->buf, "+++", 3)) { |
1917 | kfree(cb); | ||
1918 | rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT); | 1917 | rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT); |
1919 | if (cb->wake_tasklet) | 1918 | if (cb->wake_tasklet) |
1920 | tasklet_schedule(cb->wake_tasklet); | 1919 | tasklet_schedule(cb->wake_tasklet); |
1921 | return rc < 0 ? rc : cb->len; | 1920 | if (!rc) |
1921 | rc = cb->len; | ||
1922 | kfree(cb); | ||
1923 | return rc; | ||
1922 | } | 1924 | } |
1923 | 1925 | ||
1924 | spin_lock_irqsave(&cs->cmdlock, flags); | 1926 | spin_lock_irqsave(&cs->cmdlock, flags); |
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index e5ea344a551a..bcc174e4f3b1 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c | |||
@@ -1052,6 +1052,7 @@ static inline void remove_appl_from_channel(struct bc_state *bcs, | |||
1052 | do { | 1052 | do { |
1053 | if (bcap->bcnext == ap) { | 1053 | if (bcap->bcnext == ap) { |
1054 | bcap->bcnext = bcap->bcnext->bcnext; | 1054 | bcap->bcnext = bcap->bcnext->bcnext; |
1055 | spin_unlock_irqrestore(&bcs->aplock, flags); | ||
1055 | return; | 1056 | return; |
1056 | } | 1057 | } |
1057 | bcap = bcap->bcnext; | 1058 | bcap = bcap->bcnext; |
diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c index 43c5dc3516e5..4cfdbe08ffd1 100644 --- a/drivers/isdn/sc/ioctl.c +++ b/drivers/isdn/sc/ioctl.c | |||
@@ -174,7 +174,7 @@ int sc_ioctl(int card, scs_ioctl *data) | |||
174 | pr_debug("%s: SCIOGETSPID: ioctl received\n", | 174 | pr_debug("%s: SCIOGETSPID: ioctl received\n", |
175 | sc_adapter[card]->devicename); | 175 | sc_adapter[card]->devicename); |
176 | 176 | ||
177 | spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL); | 177 | spid = kzalloc(SCIOC_SPIDSIZE, GFP_KERNEL); |
178 | if (!spid) { | 178 | if (!spid) { |
179 | kfree(rcvmsg); | 179 | kfree(rcvmsg); |
180 | return -ENOMEM; | 180 | return -ENOMEM; |
@@ -194,7 +194,7 @@ int sc_ioctl(int card, scs_ioctl *data) | |||
194 | kfree(rcvmsg); | 194 | kfree(rcvmsg); |
195 | return status; | 195 | return status; |
196 | } | 196 | } |
197 | strcpy(spid, rcvmsg->msg_data.byte_array); | 197 | strlcpy(spid, rcvmsg->msg_data.byte_array, SCIOC_SPIDSIZE); |
198 | 198 | ||
199 | /* | 199 | /* |
200 | * Package the switch type and send to user space | 200 | * Package the switch type and send to user space |
@@ -266,12 +266,12 @@ int sc_ioctl(int card, scs_ioctl *data) | |||
266 | return status; | 266 | return status; |
267 | } | 267 | } |
268 | 268 | ||
269 | dn = kmalloc(SCIOC_DNSIZE, GFP_KERNEL); | 269 | dn = kzalloc(SCIOC_DNSIZE, GFP_KERNEL); |
270 | if (!dn) { | 270 | if (!dn) { |
271 | kfree(rcvmsg); | 271 | kfree(rcvmsg); |
272 | return -ENOMEM; | 272 | return -ENOMEM; |
273 | } | 273 | } |
274 | strcpy(dn, rcvmsg->msg_data.byte_array); | 274 | strlcpy(dn, rcvmsg->msg_data.byte_array, SCIOC_DNSIZE); |
275 | kfree(rcvmsg); | 275 | kfree(rcvmsg); |
276 | 276 | ||
277 | /* | 277 | /* |
@@ -337,7 +337,7 @@ int sc_ioctl(int card, scs_ioctl *data) | |||
337 | pr_debug("%s: SCIOSTAT: ioctl received\n", | 337 | pr_debug("%s: SCIOSTAT: ioctl received\n", |
338 | sc_adapter[card]->devicename); | 338 | sc_adapter[card]->devicename); |
339 | 339 | ||
340 | bi = kmalloc (sizeof(boardInfo), GFP_KERNEL); | 340 | bi = kzalloc(sizeof(boardInfo), GFP_KERNEL); |
341 | if (!bi) { | 341 | if (!bi) { |
342 | kfree(rcvmsg); | 342 | kfree(rcvmsg); |
343 | return -ENOMEM; | 343 | return -ENOMEM; |
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 21ffd030611e..cb77197d480e 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/kmod.h> | 26 | #include <linux/kmod.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/smp_lock.h> | ||
28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
29 | #include <asm/system.h> | 30 | #include <asm/system.h> |
30 | 31 | ||
@@ -215,28 +216,24 @@ static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) | |||
215 | return vdev->fops->poll(filp, poll); | 216 | return vdev->fops->poll(filp, poll); |
216 | } | 217 | } |
217 | 218 | ||
218 | static int v4l2_ioctl(struct inode *inode, struct file *filp, | 219 | static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
219 | unsigned int cmd, unsigned long arg) | ||
220 | { | 220 | { |
221 | struct video_device *vdev = video_devdata(filp); | 221 | struct video_device *vdev = video_devdata(filp); |
222 | int ret; | ||
222 | 223 | ||
223 | if (!vdev->fops->ioctl) | ||
224 | return -ENOTTY; | ||
225 | /* Allow ioctl to continue even if the device was unregistered. | 224 | /* Allow ioctl to continue even if the device was unregistered. |
226 | Things like dequeueing buffers might still be useful. */ | 225 | Things like dequeueing buffers might still be useful. */ |
227 | return vdev->fops->ioctl(filp, cmd, arg); | 226 | if (vdev->fops->unlocked_ioctl) { |
228 | } | 227 | ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); |
229 | 228 | } else if (vdev->fops->ioctl) { | |
230 | static long v4l2_unlocked_ioctl(struct file *filp, | 229 | /* TODO: convert all drivers to unlocked_ioctl */ |
231 | unsigned int cmd, unsigned long arg) | 230 | lock_kernel(); |
232 | { | 231 | ret = vdev->fops->ioctl(filp, cmd, arg); |
233 | struct video_device *vdev = video_devdata(filp); | 232 | unlock_kernel(); |
233 | } else | ||
234 | ret = -ENOTTY; | ||
234 | 235 | ||
235 | if (!vdev->fops->unlocked_ioctl) | 236 | return ret; |
236 | return -ENOTTY; | ||
237 | /* Allow ioctl to continue even if the device was unregistered. | ||
238 | Things like dequeueing buffers might still be useful. */ | ||
239 | return vdev->fops->unlocked_ioctl(filp, cmd, arg); | ||
240 | } | 237 | } |
241 | 238 | ||
242 | #ifdef CONFIG_MMU | 239 | #ifdef CONFIG_MMU |
@@ -307,22 +304,6 @@ static int v4l2_release(struct inode *inode, struct file *filp) | |||
307 | return ret; | 304 | return ret; |
308 | } | 305 | } |
309 | 306 | ||
310 | static const struct file_operations v4l2_unlocked_fops = { | ||
311 | .owner = THIS_MODULE, | ||
312 | .read = v4l2_read, | ||
313 | .write = v4l2_write, | ||
314 | .open = v4l2_open, | ||
315 | .get_unmapped_area = v4l2_get_unmapped_area, | ||
316 | .mmap = v4l2_mmap, | ||
317 | .unlocked_ioctl = v4l2_unlocked_ioctl, | ||
318 | #ifdef CONFIG_COMPAT | ||
319 | .compat_ioctl = v4l2_compat_ioctl32, | ||
320 | #endif | ||
321 | .release = v4l2_release, | ||
322 | .poll = v4l2_poll, | ||
323 | .llseek = no_llseek, | ||
324 | }; | ||
325 | |||
326 | static const struct file_operations v4l2_fops = { | 307 | static const struct file_operations v4l2_fops = { |
327 | .owner = THIS_MODULE, | 308 | .owner = THIS_MODULE, |
328 | .read = v4l2_read, | 309 | .read = v4l2_read, |
@@ -330,7 +311,7 @@ static const struct file_operations v4l2_fops = { | |||
330 | .open = v4l2_open, | 311 | .open = v4l2_open, |
331 | .get_unmapped_area = v4l2_get_unmapped_area, | 312 | .get_unmapped_area = v4l2_get_unmapped_area, |
332 | .mmap = v4l2_mmap, | 313 | .mmap = v4l2_mmap, |
333 | .ioctl = v4l2_ioctl, | 314 | .unlocked_ioctl = v4l2_ioctl, |
334 | #ifdef CONFIG_COMPAT | 315 | #ifdef CONFIG_COMPAT |
335 | .compat_ioctl = v4l2_compat_ioctl32, | 316 | .compat_ioctl = v4l2_compat_ioctl32, |
336 | #endif | 317 | #endif |
@@ -525,10 +506,7 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, | |||
525 | ret = -ENOMEM; | 506 | ret = -ENOMEM; |
526 | goto cleanup; | 507 | goto cleanup; |
527 | } | 508 | } |
528 | if (vdev->fops->unlocked_ioctl) | 509 | vdev->cdev->ops = &v4l2_fops; |
529 | vdev->cdev->ops = &v4l2_unlocked_fops; | ||
530 | else | ||
531 | vdev->cdev->ops = &v4l2_fops; | ||
532 | vdev->cdev->owner = vdev->fops->owner; | 510 | vdev->cdev->owner = vdev->fops->owner; |
533 | ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1); | 511 | ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1); |
534 | if (ret < 0) { | 512 | if (ret < 0) { |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 488f25472291..0b591b658243 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -304,6 +304,23 @@ config SENSORS_TSL2550 | |||
304 | This driver can also be built as a module. If so, the module | 304 | This driver can also be built as a module. If so, the module |
305 | will be called tsl2550. | 305 | will be called tsl2550. |
306 | 306 | ||
307 | config SENSORS_BH1780 | ||
308 | tristate "ROHM BH1780GLI ambient light sensor" | ||
309 | depends on I2C && SYSFS | ||
310 | help | ||
311 | If you say yes here you get support for the ROHM BH1780GLI | ||
312 | ambient light sensor. | ||
313 | |||
314 | This driver can also be built as a module. If so, the module | ||
315 | will be called bh1780gli. | ||
316 | |||
317 | config HMC6352 | ||
318 | tristate "Honeywell HMC6352 compass" | ||
319 | depends on I2C | ||
320 | help | ||
321 | This driver provides support for the Honeywell HMC6352 compass, | ||
322 | providing configuration and heading data via sysfs. | ||
323 | |||
307 | config EP93XX_PWM | 324 | config EP93XX_PWM |
308 | tristate "EP93xx PWM support" | 325 | tristate "EP93xx PWM support" |
309 | depends on ARCH_EP93XX | 326 | depends on ARCH_EP93XX |
@@ -363,6 +380,16 @@ config ARM_CHARLCD | |||
363 | line and the Linux version on the second line, but that's | 380 | line and the Linux version on the second line, but that's |
364 | still useful. | 381 | still useful. |
365 | 382 | ||
383 | config BMP085 | ||
384 | tristate "BMP085 digital pressure sensor" | ||
385 | depends on I2C && SYSFS | ||
386 | help | ||
387 | If you say yes here you get support for the Bosch Sensortec | ||
388 | BMP086 digital pressure sensor. | ||
389 | |||
390 | To compile this driver as a module, choose M here: the | ||
391 | module will be called bmp085. | ||
392 | |||
366 | source "drivers/misc/c2port/Kconfig" | 393 | source "drivers/misc/c2port/Kconfig" |
367 | source "drivers/misc/eeprom/Kconfig" | 394 | source "drivers/misc/eeprom/Kconfig" |
368 | source "drivers/misc/cb710/Kconfig" | 395 | source "drivers/misc/cb710/Kconfig" |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 67552d6e9327..255a80dc9d73 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -9,11 +9,13 @@ obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o | |||
9 | obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o | 9 | obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o |
10 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o | 10 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o |
11 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o | 11 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o |
12 | obj-$(CONFIG_BMP085) += bmp085.o | ||
12 | obj-$(CONFIG_ICS932S401) += ics932s401.o | 13 | obj-$(CONFIG_ICS932S401) += ics932s401.o |
13 | obj-$(CONFIG_LKDTM) += lkdtm.o | 14 | obj-$(CONFIG_LKDTM) += lkdtm.o |
14 | obj-$(CONFIG_TIFM_CORE) += tifm_core.o | 15 | obj-$(CONFIG_TIFM_CORE) += tifm_core.o |
15 | obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o | 16 | obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o |
16 | obj-$(CONFIG_PHANTOM) += phantom.o | 17 | obj-$(CONFIG_PHANTOM) += phantom.o |
18 | obj-$(CONFIG_SENSORS_BH1780) += bh1780gli.o | ||
17 | obj-$(CONFIG_SGI_IOC4) += ioc4.o | 19 | obj-$(CONFIG_SGI_IOC4) += ioc4.o |
18 | obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o | 20 | obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o |
19 | obj-$(CONFIG_KGDB_TESTS) += kgdbts.o | 21 | obj-$(CONFIG_KGDB_TESTS) += kgdbts.o |
@@ -28,6 +30,7 @@ obj-$(CONFIG_DS1682) += ds1682.o | |||
28 | obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o | 30 | obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o |
29 | obj-$(CONFIG_C2PORT) += c2port/ | 31 | obj-$(CONFIG_C2PORT) += c2port/ |
30 | obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ | 32 | obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ |
33 | obj-$(CONFIG_HMC6352) += hmc6352.o | ||
31 | obj-y += eeprom/ | 34 | obj-y += eeprom/ |
32 | obj-y += cb710/ | 35 | obj-y += cb710/ |
33 | obj-$(CONFIG_VMWARE_BALLOON) += vmware_balloon.o | 36 | obj-$(CONFIG_VMWARE_BALLOON) += vmware_balloon.o |
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c new file mode 100644 index 000000000000..714c6b487313 --- /dev/null +++ b/drivers/misc/bh1780gli.c | |||
@@ -0,0 +1,273 @@ | |||
1 | /* | ||
2 | * bh1780gli.c | ||
3 | * ROHM Ambient Light Sensor Driver | ||
4 | * | ||
5 | * Copyright (C) 2010 Texas Instruments | ||
6 | * Author: Hemanth V <hemanthv@ti.com> | ||
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 version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/mutex.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/delay.h> | ||
25 | |||
26 | #define BH1780_REG_CONTROL 0x80 | ||
27 | #define BH1780_REG_PARTID 0x8A | ||
28 | #define BH1780_REG_MANFID 0x8B | ||
29 | #define BH1780_REG_DLOW 0x8C | ||
30 | #define BH1780_REG_DHIGH 0x8D | ||
31 | |||
32 | #define BH1780_REVMASK (0xf) | ||
33 | #define BH1780_POWMASK (0x3) | ||
34 | #define BH1780_POFF (0x0) | ||
35 | #define BH1780_PON (0x3) | ||
36 | |||
37 | /* power on settling time in ms */ | ||
38 | #define BH1780_PON_DELAY 2 | ||
39 | |||
40 | struct bh1780_data { | ||
41 | struct i2c_client *client; | ||
42 | int power_state; | ||
43 | /* lock for sysfs operations */ | ||
44 | struct mutex lock; | ||
45 | }; | ||
46 | |||
47 | static int bh1780_write(struct bh1780_data *ddata, u8 reg, u8 val, char *msg) | ||
48 | { | ||
49 | int ret = i2c_smbus_write_byte_data(ddata->client, reg, val); | ||
50 | if (ret < 0) | ||
51 | dev_err(&ddata->client->dev, | ||
52 | "i2c_smbus_write_byte_data failed error %d\ | ||
53 | Register (%s)\n", ret, msg); | ||
54 | return ret; | ||
55 | } | ||
56 | |||
57 | static int bh1780_read(struct bh1780_data *ddata, u8 reg, char *msg) | ||
58 | { | ||
59 | int ret = i2c_smbus_read_byte_data(ddata->client, reg); | ||
60 | if (ret < 0) | ||
61 | dev_err(&ddata->client->dev, | ||
62 | "i2c_smbus_read_byte_data failed error %d\ | ||
63 | Register (%s)\n", ret, msg); | ||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | static ssize_t bh1780_show_lux(struct device *dev, | ||
68 | struct device_attribute *attr, char *buf) | ||
69 | { | ||
70 | struct platform_device *pdev = to_platform_device(dev); | ||
71 | struct bh1780_data *ddata = platform_get_drvdata(pdev); | ||
72 | int lsb, msb; | ||
73 | |||
74 | lsb = bh1780_read(ddata, BH1780_REG_DLOW, "DLOW"); | ||
75 | if (lsb < 0) | ||
76 | return lsb; | ||
77 | |||
78 | msb = bh1780_read(ddata, BH1780_REG_DHIGH, "DHIGH"); | ||
79 | if (msb < 0) | ||
80 | return msb; | ||
81 | |||
82 | return sprintf(buf, "%d\n", (msb << 8) | lsb); | ||
83 | } | ||
84 | |||
85 | static ssize_t bh1780_show_power_state(struct device *dev, | ||
86 | struct device_attribute *attr, | ||
87 | char *buf) | ||
88 | { | ||
89 | struct platform_device *pdev = to_platform_device(dev); | ||
90 | struct bh1780_data *ddata = platform_get_drvdata(pdev); | ||
91 | int state; | ||
92 | |||
93 | state = bh1780_read(ddata, BH1780_REG_CONTROL, "CONTROL"); | ||
94 | if (state < 0) | ||
95 | return state; | ||
96 | |||
97 | return sprintf(buf, "%d\n", state & BH1780_POWMASK); | ||
98 | } | ||
99 | |||
100 | static ssize_t bh1780_store_power_state(struct device *dev, | ||
101 | struct device_attribute *attr, | ||
102 | const char *buf, size_t count) | ||
103 | { | ||
104 | struct platform_device *pdev = to_platform_device(dev); | ||
105 | struct bh1780_data *ddata = platform_get_drvdata(pdev); | ||
106 | unsigned long val; | ||
107 | int error; | ||
108 | |||
109 | error = strict_strtoul(buf, 0, &val); | ||
110 | if (error) | ||
111 | return error; | ||
112 | |||
113 | if (val < BH1780_POFF || val > BH1780_PON) | ||
114 | return -EINVAL; | ||
115 | |||
116 | mutex_lock(&ddata->lock); | ||
117 | |||
118 | error = bh1780_write(ddata, BH1780_REG_CONTROL, val, "CONTROL"); | ||
119 | if (error < 0) { | ||
120 | mutex_unlock(&ddata->lock); | ||
121 | return error; | ||
122 | } | ||
123 | |||
124 | msleep(BH1780_PON_DELAY); | ||
125 | ddata->power_state = val; | ||
126 | mutex_unlock(&ddata->lock); | ||
127 | |||
128 | return count; | ||
129 | } | ||
130 | |||
131 | static DEVICE_ATTR(lux, S_IRUGO, bh1780_show_lux, NULL); | ||
132 | |||
133 | static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO, | ||
134 | bh1780_show_power_state, bh1780_store_power_state); | ||
135 | |||
136 | static struct attribute *bh1780_attributes[] = { | ||
137 | &dev_attr_power_state.attr, | ||
138 | &dev_attr_lux.attr, | ||
139 | NULL | ||
140 | }; | ||
141 | |||
142 | static const struct attribute_group bh1780_attr_group = { | ||
143 | .attrs = bh1780_attributes, | ||
144 | }; | ||
145 | |||
146 | static int __devinit bh1780_probe(struct i2c_client *client, | ||
147 | const struct i2c_device_id *id) | ||
148 | { | ||
149 | int ret; | ||
150 | struct bh1780_data *ddata = NULL; | ||
151 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
152 | |||
153 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) { | ||
154 | ret = -EIO; | ||
155 | goto err_op_failed; | ||
156 | } | ||
157 | |||
158 | ddata = kzalloc(sizeof(struct bh1780_data), GFP_KERNEL); | ||
159 | if (ddata == NULL) { | ||
160 | ret = -ENOMEM; | ||
161 | goto err_op_failed; | ||
162 | } | ||
163 | |||
164 | ddata->client = client; | ||
165 | i2c_set_clientdata(client, ddata); | ||
166 | |||
167 | ret = bh1780_read(ddata, BH1780_REG_PARTID, "PART ID"); | ||
168 | if (ret < 0) | ||
169 | goto err_op_failed; | ||
170 | |||
171 | dev_info(&client->dev, "Ambient Light Sensor, Rev : %d\n", | ||
172 | (ret & BH1780_REVMASK)); | ||
173 | |||
174 | mutex_init(&ddata->lock); | ||
175 | |||
176 | ret = sysfs_create_group(&client->dev.kobj, &bh1780_attr_group); | ||
177 | if (ret) | ||
178 | goto err_op_failed; | ||
179 | |||
180 | return 0; | ||
181 | |||
182 | err_op_failed: | ||
183 | kfree(ddata); | ||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | static int __devexit bh1780_remove(struct i2c_client *client) | ||
188 | { | ||
189 | struct bh1780_data *ddata; | ||
190 | |||
191 | ddata = i2c_get_clientdata(client); | ||
192 | sysfs_remove_group(&client->dev.kobj, &bh1780_attr_group); | ||
193 | i2c_set_clientdata(client, NULL); | ||
194 | kfree(ddata); | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | #ifdef CONFIG_PM | ||
200 | static int bh1780_suspend(struct i2c_client *client, pm_message_t mesg) | ||
201 | { | ||
202 | struct bh1780_data *ddata; | ||
203 | int state, ret; | ||
204 | |||
205 | ddata = i2c_get_clientdata(client); | ||
206 | state = bh1780_read(ddata, BH1780_REG_CONTROL, "CONTROL"); | ||
207 | if (state < 0) | ||
208 | return state; | ||
209 | |||
210 | ddata->power_state = state & BH1780_POWMASK; | ||
211 | |||
212 | ret = bh1780_write(ddata, BH1780_REG_CONTROL, BH1780_POFF, | ||
213 | "CONTROL"); | ||
214 | |||
215 | if (ret < 0) | ||
216 | return ret; | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int bh1780_resume(struct i2c_client *client) | ||
222 | { | ||
223 | struct bh1780_data *ddata; | ||
224 | int state, ret; | ||
225 | |||
226 | ddata = i2c_get_clientdata(client); | ||
227 | state = ddata->power_state; | ||
228 | |||
229 | ret = bh1780_write(ddata, BH1780_REG_CONTROL, state, | ||
230 | "CONTROL"); | ||
231 | |||
232 | if (ret < 0) | ||
233 | return ret; | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | #else | ||
238 | #define bh1780_suspend NULL | ||
239 | #define bh1780_resume NULL | ||
240 | #endif /* CONFIG_PM */ | ||
241 | |||
242 | static const struct i2c_device_id bh1780_id[] = { | ||
243 | { "bh1780", 0 }, | ||
244 | { }, | ||
245 | }; | ||
246 | |||
247 | static struct i2c_driver bh1780_driver = { | ||
248 | .probe = bh1780_probe, | ||
249 | .remove = bh1780_remove, | ||
250 | .id_table = bh1780_id, | ||
251 | .suspend = bh1780_suspend, | ||
252 | .resume = bh1780_resume, | ||
253 | .driver = { | ||
254 | .name = "bh1780" | ||
255 | }, | ||
256 | }; | ||
257 | |||
258 | static int __init bh1780_init(void) | ||
259 | { | ||
260 | return i2c_add_driver(&bh1780_driver); | ||
261 | } | ||
262 | |||
263 | static void __exit bh1780_exit(void) | ||
264 | { | ||
265 | i2c_del_driver(&bh1780_driver); | ||
266 | } | ||
267 | |||
268 | module_init(bh1780_init) | ||
269 | module_exit(bh1780_exit) | ||
270 | |||
271 | MODULE_DESCRIPTION("BH1780GLI Ambient Light Sensor Driver"); | ||
272 | MODULE_LICENSE("GPL"); | ||
273 | MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>"); | ||
diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c new file mode 100644 index 000000000000..63ee4c1a5315 --- /dev/null +++ b/drivers/misc/bmp085.c | |||
@@ -0,0 +1,482 @@ | |||
1 | /* Copyright (c) 2010 Christoph Mair <christoph.mair@gmail.com> | ||
2 | |||
3 | This driver supports the bmp085 digital barometric pressure | ||
4 | and temperature sensor from Bosch Sensortec. The datasheet | ||
5 | is avaliable from their website: | ||
6 | http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf | ||
7 | |||
8 | A pressure measurement is issued by reading from pressure0_input. | ||
9 | The return value ranges from 30000 to 110000 pascal with a resulution | ||
10 | of 1 pascal (0.01 millibar) which enables measurements from 9000m above | ||
11 | to 500m below sea level. | ||
12 | |||
13 | The temperature can be read from temp0_input. Values range from | ||
14 | -400 to 850 representing the ambient temperature in degree celsius | ||
15 | multiplied by 10.The resolution is 0.1 celsius. | ||
16 | |||
17 | Because ambient pressure is temperature dependent, a temperature | ||
18 | measurement will be executed automatically even if the user is reading | ||
19 | from pressure0_input. This happens if the last temperature measurement | ||
20 | has been executed more then one second ago. | ||
21 | |||
22 | To decrease RMS noise from pressure measurements, the bmp085 can | ||
23 | autonomously calculate the average of up to eight samples. This is | ||
24 | set up by writing to the oversampling sysfs file. Accepted values | ||
25 | are 0, 1, 2 and 3. 2^x when x is the value written to this file | ||
26 | specifies the number of samples used to calculate the ambient pressure. | ||
27 | RMS noise is specified with six pascal (without averaging) and decreases | ||
28 | down to 3 pascal when using an oversampling setting of 3. | ||
29 | |||
30 | This program is free software; you can redistribute it and/or modify | ||
31 | it under the terms of the GNU General Public License as published by | ||
32 | the Free Software Foundation; either version 2 of the License, or | ||
33 | (at your option) any later version. | ||
34 | |||
35 | This program is distributed in the hope that it will be useful, | ||
36 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
37 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
38 | GNU General Public License for more details. | ||
39 | |||
40 | You should have received a copy of the GNU General Public License | ||
41 | along with this program; if not, write to the Free Software | ||
42 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <linux/module.h> | ||
47 | #include <linux/init.h> | ||
48 | #include <linux/i2c.h> | ||
49 | #include <linux/slab.h> | ||
50 | #include <linux/delay.h> | ||
51 | |||
52 | |||
53 | #define BMP085_I2C_ADDRESS 0x77 | ||
54 | #define BMP085_CHIP_ID 0x55 | ||
55 | |||
56 | #define BMP085_CALIBRATION_DATA_START 0xAA | ||
57 | #define BMP085_CALIBRATION_DATA_LENGTH 11 /* 16 bit values */ | ||
58 | #define BMP085_CHIP_ID_REG 0xD0 | ||
59 | #define BMP085_VERSION_REG 0xD1 | ||
60 | #define BMP085_CTRL_REG 0xF4 | ||
61 | #define BMP085_TEMP_MEASUREMENT 0x2E | ||
62 | #define BMP085_PRESSURE_MEASUREMENT 0x34 | ||
63 | #define BMP085_CONVERSION_REGISTER_MSB 0xF6 | ||
64 | #define BMP085_CONVERSION_REGISTER_LSB 0xF7 | ||
65 | #define BMP085_CONVERSION_REGISTER_XLSB 0xF8 | ||
66 | #define BMP085_TEMP_CONVERSION_TIME 5 | ||
67 | |||
68 | #define BMP085_CLIENT_NAME "bmp085" | ||
69 | |||
70 | |||
71 | static const unsigned short normal_i2c[] = { BMP085_I2C_ADDRESS, | ||
72 | I2C_CLIENT_END }; | ||
73 | |||
74 | struct bmp085_calibration_data { | ||
75 | s16 AC1, AC2, AC3; | ||
76 | u16 AC4, AC5, AC6; | ||
77 | s16 B1, B2; | ||
78 | s16 MB, MC, MD; | ||
79 | }; | ||
80 | |||
81 | |||
82 | /* Each client has this additional data */ | ||
83 | struct bmp085_data { | ||
84 | struct i2c_client *client; | ||
85 | struct mutex lock; | ||
86 | struct bmp085_calibration_data calibration; | ||
87 | u32 raw_temperature; | ||
88 | u32 raw_pressure; | ||
89 | unsigned char oversampling_setting; | ||
90 | u32 last_temp_measurement; | ||
91 | s32 b6; /* calculated temperature correction coefficient */ | ||
92 | }; | ||
93 | |||
94 | |||
95 | static s32 bmp085_read_calibration_data(struct i2c_client *client) | ||
96 | { | ||
97 | u16 tmp[BMP085_CALIBRATION_DATA_LENGTH]; | ||
98 | struct bmp085_data *data = i2c_get_clientdata(client); | ||
99 | struct bmp085_calibration_data *cali = &(data->calibration); | ||
100 | s32 status = i2c_smbus_read_i2c_block_data(client, | ||
101 | BMP085_CALIBRATION_DATA_START, | ||
102 | BMP085_CALIBRATION_DATA_LENGTH*sizeof(u16), | ||
103 | (u8 *)tmp); | ||
104 | if (status < 0) | ||
105 | return status; | ||
106 | |||
107 | if (status != BMP085_CALIBRATION_DATA_LENGTH*sizeof(u16)) | ||
108 | return -EIO; | ||
109 | |||
110 | cali->AC1 = be16_to_cpu(tmp[0]); | ||
111 | cali->AC2 = be16_to_cpu(tmp[1]); | ||
112 | cali->AC3 = be16_to_cpu(tmp[2]); | ||
113 | cali->AC4 = be16_to_cpu(tmp[3]); | ||
114 | cali->AC5 = be16_to_cpu(tmp[4]); | ||
115 | cali->AC6 = be16_to_cpu(tmp[5]); | ||
116 | cali->B1 = be16_to_cpu(tmp[6]); | ||
117 | cali->B2 = be16_to_cpu(tmp[7]); | ||
118 | cali->MB = be16_to_cpu(tmp[8]); | ||
119 | cali->MC = be16_to_cpu(tmp[9]); | ||
120 | cali->MD = be16_to_cpu(tmp[10]); | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | |||
125 | static s32 bmp085_update_raw_temperature(struct bmp085_data *data) | ||
126 | { | ||
127 | u16 tmp; | ||
128 | s32 status; | ||
129 | |||
130 | mutex_lock(&data->lock); | ||
131 | status = i2c_smbus_write_byte_data(data->client, BMP085_CTRL_REG, | ||
132 | BMP085_TEMP_MEASUREMENT); | ||
133 | if (status != 0) { | ||
134 | dev_err(&data->client->dev, | ||
135 | "Error while requesting temperature measurement.\n"); | ||
136 | goto exit; | ||
137 | } | ||
138 | msleep(BMP085_TEMP_CONVERSION_TIME); | ||
139 | |||
140 | status = i2c_smbus_read_i2c_block_data(data->client, | ||
141 | BMP085_CONVERSION_REGISTER_MSB, sizeof(tmp), (u8 *)&tmp); | ||
142 | if (status < 0) | ||
143 | goto exit; | ||
144 | if (status != sizeof(tmp)) { | ||
145 | dev_err(&data->client->dev, | ||
146 | "Error while reading temperature measurement result\n"); | ||
147 | status = -EIO; | ||
148 | goto exit; | ||
149 | } | ||
150 | data->raw_temperature = be16_to_cpu(tmp); | ||
151 | data->last_temp_measurement = jiffies; | ||
152 | status = 0; /* everything ok, return 0 */ | ||
153 | |||
154 | exit: | ||
155 | mutex_unlock(&data->lock); | ||
156 | return status; | ||
157 | } | ||
158 | |||
159 | static s32 bmp085_update_raw_pressure(struct bmp085_data *data) | ||
160 | { | ||
161 | u32 tmp = 0; | ||
162 | s32 status; | ||
163 | |||
164 | mutex_lock(&data->lock); | ||
165 | status = i2c_smbus_write_byte_data(data->client, BMP085_CTRL_REG, | ||
166 | BMP085_PRESSURE_MEASUREMENT + (data->oversampling_setting<<6)); | ||
167 | if (status != 0) { | ||
168 | dev_err(&data->client->dev, | ||
169 | "Error while requesting pressure measurement.\n"); | ||
170 | goto exit; | ||
171 | } | ||
172 | |||
173 | /* wait for the end of conversion */ | ||
174 | msleep(2+(3 << data->oversampling_setting)); | ||
175 | |||
176 | /* copy data into a u32 (4 bytes), but skip the first byte. */ | ||
177 | status = i2c_smbus_read_i2c_block_data(data->client, | ||
178 | BMP085_CONVERSION_REGISTER_MSB, 3, ((u8 *)&tmp)+1); | ||
179 | if (status < 0) | ||
180 | goto exit; | ||
181 | if (status != 3) { | ||
182 | dev_err(&data->client->dev, | ||
183 | "Error while reading pressure measurement results\n"); | ||
184 | status = -EIO; | ||
185 | goto exit; | ||
186 | } | ||
187 | data->raw_pressure = be32_to_cpu((tmp)); | ||
188 | data->raw_pressure >>= (8-data->oversampling_setting); | ||
189 | status = 0; /* everything ok, return 0 */ | ||
190 | |||
191 | exit: | ||
192 | mutex_unlock(&data->lock); | ||
193 | return status; | ||
194 | } | ||
195 | |||
196 | |||
197 | /* | ||
198 | * This function starts the temperature measurement and returns the value | ||
199 | * in tenth of a degree celsius. | ||
200 | */ | ||
201 | static s32 bmp085_get_temperature(struct bmp085_data *data, int *temperature) | ||
202 | { | ||
203 | struct bmp085_calibration_data *cali = &data->calibration; | ||
204 | long x1, x2; | ||
205 | int status; | ||
206 | |||
207 | status = bmp085_update_raw_temperature(data); | ||
208 | if (status != 0) | ||
209 | goto exit; | ||
210 | |||
211 | x1 = ((data->raw_temperature - cali->AC6) * cali->AC5) >> 15; | ||
212 | x2 = (cali->MC << 11) / (x1 + cali->MD); | ||
213 | data->b6 = x1 + x2 - 4000; | ||
214 | /* if NULL just update b6. Used for pressure only measurements */ | ||
215 | if (temperature != NULL) | ||
216 | *temperature = (x1+x2+8) >> 4; | ||
217 | |||
218 | exit: | ||
219 | return status;; | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * This function starts the pressure measurement and returns the value | ||
224 | * in millibar. Since the pressure depends on the ambient temperature, | ||
225 | * a temperature measurement is executed if the last known value is older | ||
226 | * than one second. | ||
227 | */ | ||
228 | static s32 bmp085_get_pressure(struct bmp085_data *data, int *pressure) | ||
229 | { | ||
230 | struct bmp085_calibration_data *cali = &data->calibration; | ||
231 | s32 x1, x2, x3, b3; | ||
232 | u32 b4, b7; | ||
233 | s32 p; | ||
234 | int status; | ||
235 | |||
236 | /* alt least every second force an update of the ambient temperature */ | ||
237 | if (data->last_temp_measurement + 1*HZ < jiffies) { | ||
238 | status = bmp085_get_temperature(data, NULL); | ||
239 | if (status != 0) | ||
240 | goto exit; | ||
241 | } | ||
242 | |||
243 | status = bmp085_update_raw_pressure(data); | ||
244 | if (status != 0) | ||
245 | goto exit; | ||
246 | |||
247 | x1 = (data->b6 * data->b6) >> 12; | ||
248 | x1 *= cali->B2; | ||
249 | x1 >>= 11; | ||
250 | |||
251 | x2 = cali->AC2 * data->b6; | ||
252 | x2 >>= 11; | ||
253 | |||
254 | x3 = x1 + x2; | ||
255 | |||
256 | b3 = (((((s32)cali->AC1) * 4 + x3) << data->oversampling_setting) + 2); | ||
257 | b3 >>= 2; | ||
258 | |||
259 | x1 = (cali->AC3 * data->b6) >> 13; | ||
260 | x2 = (cali->B1 * ((data->b6 * data->b6) >> 12)) >> 16; | ||
261 | x3 = (x1 + x2 + 2) >> 2; | ||
262 | b4 = (cali->AC4 * (u32)(x3 + 32768)) >> 15; | ||
263 | |||
264 | b7 = ((u32)data->raw_pressure - b3) * | ||
265 | (50000 >> data->oversampling_setting); | ||
266 | p = ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2)); | ||
267 | |||
268 | x1 = p >> 8; | ||
269 | x1 *= x1; | ||
270 | x1 = (x1 * 3038) >> 16; | ||
271 | x2 = (-7357 * p) >> 16; | ||
272 | p += (x1 + x2 + 3791) >> 4; | ||
273 | |||
274 | *pressure = p; | ||
275 | |||
276 | exit: | ||
277 | return status; | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * This function sets the chip-internal oversampling. Valid values are 0..3. | ||
282 | * The chip will use 2^oversampling samples for internal averaging. | ||
283 | * This influences the measurement time and the accuracy; larger values | ||
284 | * increase both. The datasheet gives on overview on how measurement time, | ||
285 | * accuracy and noise correlate. | ||
286 | */ | ||
287 | static void bmp085_set_oversampling(struct bmp085_data *data, | ||
288 | unsigned char oversampling) | ||
289 | { | ||
290 | if (oversampling > 3) | ||
291 | oversampling = 3; | ||
292 | data->oversampling_setting = oversampling; | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * Returns the currently selected oversampling. Range: 0..3 | ||
297 | */ | ||
298 | static unsigned char bmp085_get_oversampling(struct bmp085_data *data) | ||
299 | { | ||
300 | return data->oversampling_setting; | ||
301 | } | ||
302 | |||
303 | /* sysfs callbacks */ | ||
304 | static ssize_t set_oversampling(struct device *dev, | ||
305 | struct device_attribute *attr, | ||
306 | const char *buf, size_t count) | ||
307 | { | ||
308 | struct i2c_client *client = to_i2c_client(dev); | ||
309 | struct bmp085_data *data = i2c_get_clientdata(client); | ||
310 | unsigned long oversampling; | ||
311 | int success = strict_strtoul(buf, 10, &oversampling); | ||
312 | if (success == 0) { | ||
313 | bmp085_set_oversampling(data, oversampling); | ||
314 | return count; | ||
315 | } | ||
316 | return success; | ||
317 | } | ||
318 | |||
319 | static ssize_t show_oversampling(struct device *dev, | ||
320 | struct device_attribute *attr, char *buf) | ||
321 | { | ||
322 | struct i2c_client *client = to_i2c_client(dev); | ||
323 | struct bmp085_data *data = i2c_get_clientdata(client); | ||
324 | return sprintf(buf, "%u\n", bmp085_get_oversampling(data)); | ||
325 | } | ||
326 | static DEVICE_ATTR(oversampling, S_IWUSR | S_IRUGO, | ||
327 | show_oversampling, set_oversampling); | ||
328 | |||
329 | |||
330 | static ssize_t show_temperature(struct device *dev, | ||
331 | struct device_attribute *attr, char *buf) | ||
332 | { | ||
333 | int temperature; | ||
334 | int status; | ||
335 | struct i2c_client *client = to_i2c_client(dev); | ||
336 | struct bmp085_data *data = i2c_get_clientdata(client); | ||
337 | |||
338 | status = bmp085_get_temperature(data, &temperature); | ||
339 | if (status != 0) | ||
340 | return status; | ||
341 | else | ||
342 | return sprintf(buf, "%d\n", temperature); | ||
343 | } | ||
344 | static DEVICE_ATTR(temp0_input, S_IRUGO, show_temperature, NULL); | ||
345 | |||
346 | |||
347 | static ssize_t show_pressure(struct device *dev, | ||
348 | struct device_attribute *attr, char *buf) | ||
349 | { | ||
350 | int pressure; | ||
351 | int status; | ||
352 | struct i2c_client *client = to_i2c_client(dev); | ||
353 | struct bmp085_data *data = i2c_get_clientdata(client); | ||
354 | |||
355 | status = bmp085_get_pressure(data, &pressure); | ||
356 | if (status != 0) | ||
357 | return status; | ||
358 | else | ||
359 | return sprintf(buf, "%d\n", pressure); | ||
360 | } | ||
361 | static DEVICE_ATTR(pressure0_input, S_IRUGO, show_pressure, NULL); | ||
362 | |||
363 | |||
364 | static struct attribute *bmp085_attributes[] = { | ||
365 | &dev_attr_temp0_input.attr, | ||
366 | &dev_attr_pressure0_input.attr, | ||
367 | &dev_attr_oversampling.attr, | ||
368 | NULL | ||
369 | }; | ||
370 | |||
371 | static const struct attribute_group bmp085_attr_group = { | ||
372 | .attrs = bmp085_attributes, | ||
373 | }; | ||
374 | |||
375 | static int bmp085_detect(struct i2c_client *client, struct i2c_board_info *info) | ||
376 | { | ||
377 | if (client->addr != BMP085_I2C_ADDRESS) | ||
378 | return -ENODEV; | ||
379 | |||
380 | if (i2c_smbus_read_byte_data(client, BMP085_CHIP_ID_REG) != BMP085_CHIP_ID) | ||
381 | return -ENODEV; | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static int bmp085_init_client(struct i2c_client *client) | ||
387 | { | ||
388 | unsigned char version; | ||
389 | int status; | ||
390 | struct bmp085_data *data = i2c_get_clientdata(client); | ||
391 | data->client = client; | ||
392 | status = bmp085_read_calibration_data(client); | ||
393 | if (status != 0) | ||
394 | goto exit; | ||
395 | version = i2c_smbus_read_byte_data(client, BMP085_VERSION_REG); | ||
396 | data->last_temp_measurement = 0; | ||
397 | data->oversampling_setting = 3; | ||
398 | mutex_init(&data->lock); | ||
399 | dev_info(&data->client->dev, "BMP085 ver. %d.%d found.\n", | ||
400 | (version & 0x0F), (version & 0xF0) >> 4); | ||
401 | exit: | ||
402 | return status; | ||
403 | } | ||
404 | |||
405 | static int bmp085_probe(struct i2c_client *client, | ||
406 | const struct i2c_device_id *id) | ||
407 | { | ||
408 | struct bmp085_data *data; | ||
409 | int err = 0; | ||
410 | |||
411 | data = kzalloc(sizeof(struct bmp085_data), GFP_KERNEL); | ||
412 | if (!data) { | ||
413 | err = -ENOMEM; | ||
414 | goto exit; | ||
415 | } | ||
416 | |||
417 | /* default settings after POR */ | ||
418 | data->oversampling_setting = 0x00; | ||
419 | |||
420 | i2c_set_clientdata(client, data); | ||
421 | |||
422 | /* Initialize the BMP085 chip */ | ||
423 | err = bmp085_init_client(client); | ||
424 | if (err != 0) | ||
425 | goto exit_free; | ||
426 | |||
427 | /* Register sysfs hooks */ | ||
428 | err = sysfs_create_group(&client->dev.kobj, &bmp085_attr_group); | ||
429 | if (err) | ||
430 | goto exit_free; | ||
431 | |||
432 | dev_info(&data->client->dev, "Succesfully initialized bmp085!\n"); | ||
433 | goto exit; | ||
434 | |||
435 | exit_free: | ||
436 | kfree(data); | ||
437 | exit: | ||
438 | return err; | ||
439 | } | ||
440 | |||
441 | static int bmp085_remove(struct i2c_client *client) | ||
442 | { | ||
443 | sysfs_remove_group(&client->dev.kobj, &bmp085_attr_group); | ||
444 | kfree(i2c_get_clientdata(client)); | ||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static const struct i2c_device_id bmp085_id[] = { | ||
449 | { "bmp085", 0 }, | ||
450 | { } | ||
451 | }; | ||
452 | |||
453 | static struct i2c_driver bmp085_driver = { | ||
454 | .driver = { | ||
455 | .owner = THIS_MODULE, | ||
456 | .name = "bmp085" | ||
457 | }, | ||
458 | .id_table = bmp085_id, | ||
459 | .probe = bmp085_probe, | ||
460 | .remove = bmp085_remove, | ||
461 | |||
462 | .detect = bmp085_detect, | ||
463 | .address_list = normal_i2c | ||
464 | }; | ||
465 | |||
466 | static int __init bmp085_init(void) | ||
467 | { | ||
468 | return i2c_add_driver(&bmp085_driver); | ||
469 | } | ||
470 | |||
471 | static void __exit bmp085_exit(void) | ||
472 | { | ||
473 | i2c_del_driver(&bmp085_driver); | ||
474 | } | ||
475 | |||
476 | |||
477 | MODULE_AUTHOR("Christoph Mair <christoph.mair@gmail.com"); | ||
478 | MODULE_DESCRIPTION("BMP085 driver"); | ||
479 | MODULE_LICENSE("GPL"); | ||
480 | |||
481 | module_init(bmp085_init); | ||
482 | module_exit(bmp085_exit); | ||
diff --git a/drivers/misc/hmc6352.c b/drivers/misc/hmc6352.c new file mode 100644 index 000000000000..234bfcaf2099 --- /dev/null +++ b/drivers/misc/hmc6352.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /* | ||
2 | * hmc6352.c - Honeywell Compass Driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Intel Corp | ||
5 | * | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
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 as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
20 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/err.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/sysfs.h> | ||
31 | |||
32 | static DEFINE_MUTEX(compass_mutex); | ||
33 | |||
34 | static int compass_command(struct i2c_client *c, u8 cmd) | ||
35 | { | ||
36 | int ret = i2c_master_send(c, &cmd, 1); | ||
37 | if (ret < 0) | ||
38 | dev_warn(&c->dev, "command '%c' failed.\n", cmd); | ||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | static int compass_store(struct device *dev, const char *buf, size_t count, | ||
43 | const char *map) | ||
44 | { | ||
45 | struct i2c_client *c = to_i2c_client(dev); | ||
46 | int ret; | ||
47 | unsigned long val; | ||
48 | |||
49 | if (strict_strtoul(buf, 10, &val)) | ||
50 | return -EINVAL; | ||
51 | if (val >= strlen(map)) | ||
52 | return -EINVAL; | ||
53 | mutex_lock(&compass_mutex); | ||
54 | ret = compass_command(c, map[val]); | ||
55 | mutex_unlock(&compass_mutex); | ||
56 | if (ret < 0) | ||
57 | return ret; | ||
58 | return count; | ||
59 | } | ||
60 | |||
61 | static ssize_t compass_calibration_store(struct device *dev, | ||
62 | struct device_attribute *attr, const char *buf, size_t count) | ||
63 | { | ||
64 | return compass_store(dev, buf, count, "EC"); | ||
65 | } | ||
66 | |||
67 | static ssize_t compass_power_mode_store(struct device *dev, | ||
68 | struct device_attribute *attr, const char *buf, size_t count) | ||
69 | { | ||
70 | return compass_store(dev, buf, count, "SW"); | ||
71 | } | ||
72 | |||
73 | static ssize_t compass_heading_data_show(struct device *dev, | ||
74 | struct device_attribute *attr, char *buf) | ||
75 | { | ||
76 | struct i2c_client *client = to_i2c_client(dev); | ||
77 | unsigned char i2c_data[2]; | ||
78 | unsigned int ret; | ||
79 | |||
80 | mutex_lock(&compass_mutex); | ||
81 | ret = compass_command(client, 'A'); | ||
82 | if (ret != 1) { | ||
83 | mutex_unlock(&compass_mutex); | ||
84 | return ret; | ||
85 | } | ||
86 | msleep(10); /* sending 'A' cmd we need to wait for 7-10 millisecs */ | ||
87 | ret = i2c_master_recv(client, i2c_data, 2); | ||
88 | mutex_unlock(&compass_mutex); | ||
89 | if (ret != 1) { | ||
90 | dev_warn(dev, "i2c read data cmd failed\n"); | ||
91 | return ret; | ||
92 | } | ||
93 | ret = (i2c_data[0] << 8) | i2c_data[1]; | ||
94 | return sprintf(buf, "%d.%d\n", ret/10, ret%10); | ||
95 | } | ||
96 | |||
97 | |||
98 | static DEVICE_ATTR(heading0_input, S_IRUGO, compass_heading_data_show, NULL); | ||
99 | static DEVICE_ATTR(calibration, S_IWUSR, NULL, compass_calibration_store); | ||
100 | static DEVICE_ATTR(power_state, S_IWUSR, NULL, compass_power_mode_store); | ||
101 | |||
102 | static struct attribute *mid_att_compass[] = { | ||
103 | &dev_attr_heading0_input.attr, | ||
104 | &dev_attr_calibration.attr, | ||
105 | &dev_attr_power_state.attr, | ||
106 | NULL | ||
107 | }; | ||
108 | |||
109 | static const struct attribute_group m_compass_gr = { | ||
110 | .name = "hmc6352", | ||
111 | .attrs = mid_att_compass | ||
112 | }; | ||
113 | |||
114 | static int hmc6352_probe(struct i2c_client *client, | ||
115 | const struct i2c_device_id *id) | ||
116 | { | ||
117 | int res; | ||
118 | |||
119 | res = sysfs_create_group(&client->dev.kobj, &m_compass_gr); | ||
120 | if (res) { | ||
121 | dev_err(&client->dev, "device_create_file failed\n"); | ||
122 | return res; | ||
123 | } | ||
124 | dev_info(&client->dev, "%s HMC6352 compass chip found\n", | ||
125 | client->name); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int hmc6352_remove(struct i2c_client *client) | ||
130 | { | ||
131 | sysfs_remove_group(&client->dev.kobj, &m_compass_gr); | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static struct i2c_device_id hmc6352_id[] = { | ||
136 | { "hmc6352", 0 }, | ||
137 | { } | ||
138 | }; | ||
139 | |||
140 | MODULE_DEVICE_TABLE(i2c, hmc6352_id); | ||
141 | |||
142 | static struct i2c_driver hmc6352_driver = { | ||
143 | .driver = { | ||
144 | .name = "hmc6352", | ||
145 | }, | ||
146 | .probe = hmc6352_probe, | ||
147 | .remove = hmc6352_remove, | ||
148 | .id_table = hmc6352_id, | ||
149 | }; | ||
150 | |||
151 | static int __init sensor_hmc6352_init(void) | ||
152 | { | ||
153 | return i2c_add_driver(&hmc6352_driver); | ||
154 | } | ||
155 | |||
156 | static void __exit sensor_hmc6352_exit(void) | ||
157 | { | ||
158 | i2c_del_driver(&hmc6352_driver); | ||
159 | } | ||
160 | |||
161 | module_init(sensor_hmc6352_init); | ||
162 | module_exit(sensor_hmc6352_exit); | ||
163 | |||
164 | MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com"); | ||
165 | MODULE_DESCRIPTION("hmc6352 Compass Driver"); | ||
166 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index 98ad0120aa9b..557a8c2a7336 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c | |||
@@ -256,7 +256,8 @@ static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data) | |||
256 | 256 | ||
257 | static int ilo_ccb_setup(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) | 257 | static int ilo_ccb_setup(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) |
258 | { | 258 | { |
259 | char *dma_va, *dma_pa; | 259 | char *dma_va; |
260 | dma_addr_t dma_pa; | ||
260 | struct ccb *driver_ccb, *ilo_ccb; | 261 | struct ccb *driver_ccb, *ilo_ccb; |
261 | 262 | ||
262 | driver_ccb = &data->driver_ccb; | 263 | driver_ccb = &data->driver_ccb; |
@@ -272,12 +273,12 @@ static int ilo_ccb_setup(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) | |||
272 | return -ENOMEM; | 273 | return -ENOMEM; |
273 | 274 | ||
274 | dma_va = (char *)data->dma_va; | 275 | dma_va = (char *)data->dma_va; |
275 | dma_pa = (char *)data->dma_pa; | 276 | dma_pa = data->dma_pa; |
276 | 277 | ||
277 | memset(dma_va, 0, data->dma_size); | 278 | memset(dma_va, 0, data->dma_size); |
278 | 279 | ||
279 | dma_va = (char *)roundup((unsigned long)dma_va, ILO_START_ALIGN); | 280 | dma_va = (char *)roundup((unsigned long)dma_va, ILO_START_ALIGN); |
280 | dma_pa = (char *)roundup((unsigned long)dma_pa, ILO_START_ALIGN); | 281 | dma_pa = roundup(dma_pa, ILO_START_ALIGN); |
281 | 282 | ||
282 | /* | 283 | /* |
283 | * Create two ccb's, one with virt addrs, one with phys addrs. | 284 | * Create two ccb's, one with virt addrs, one with phys addrs. |
@@ -288,26 +289,26 @@ static int ilo_ccb_setup(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) | |||
288 | 289 | ||
289 | fifo_setup(dma_va, NR_QENTRY); | 290 | fifo_setup(dma_va, NR_QENTRY); |
290 | driver_ccb->ccb_u1.send_fifobar = dma_va + FIFOHANDLESIZE; | 291 | driver_ccb->ccb_u1.send_fifobar = dma_va + FIFOHANDLESIZE; |
291 | ilo_ccb->ccb_u1.send_fifobar = dma_pa + FIFOHANDLESIZE; | 292 | ilo_ccb->ccb_u1.send_fifobar_pa = dma_pa + FIFOHANDLESIZE; |
292 | dma_va += fifo_sz(NR_QENTRY); | 293 | dma_va += fifo_sz(NR_QENTRY); |
293 | dma_pa += fifo_sz(NR_QENTRY); | 294 | dma_pa += fifo_sz(NR_QENTRY); |
294 | 295 | ||
295 | dma_va = (char *)roundup((unsigned long)dma_va, ILO_CACHE_SZ); | 296 | dma_va = (char *)roundup((unsigned long)dma_va, ILO_CACHE_SZ); |
296 | dma_pa = (char *)roundup((unsigned long)dma_pa, ILO_CACHE_SZ); | 297 | dma_pa = roundup(dma_pa, ILO_CACHE_SZ); |
297 | 298 | ||
298 | fifo_setup(dma_va, NR_QENTRY); | 299 | fifo_setup(dma_va, NR_QENTRY); |
299 | driver_ccb->ccb_u3.recv_fifobar = dma_va + FIFOHANDLESIZE; | 300 | driver_ccb->ccb_u3.recv_fifobar = dma_va + FIFOHANDLESIZE; |
300 | ilo_ccb->ccb_u3.recv_fifobar = dma_pa + FIFOHANDLESIZE; | 301 | ilo_ccb->ccb_u3.recv_fifobar_pa = dma_pa + FIFOHANDLESIZE; |
301 | dma_va += fifo_sz(NR_QENTRY); | 302 | dma_va += fifo_sz(NR_QENTRY); |
302 | dma_pa += fifo_sz(NR_QENTRY); | 303 | dma_pa += fifo_sz(NR_QENTRY); |
303 | 304 | ||
304 | driver_ccb->ccb_u2.send_desc = dma_va; | 305 | driver_ccb->ccb_u2.send_desc = dma_va; |
305 | ilo_ccb->ccb_u2.send_desc = dma_pa; | 306 | ilo_ccb->ccb_u2.send_desc_pa = dma_pa; |
306 | dma_pa += desc_mem_sz(NR_QENTRY); | 307 | dma_pa += desc_mem_sz(NR_QENTRY); |
307 | dma_va += desc_mem_sz(NR_QENTRY); | 308 | dma_va += desc_mem_sz(NR_QENTRY); |
308 | 309 | ||
309 | driver_ccb->ccb_u4.recv_desc = dma_va; | 310 | driver_ccb->ccb_u4.recv_desc = dma_va; |
310 | ilo_ccb->ccb_u4.recv_desc = dma_pa; | 311 | ilo_ccb->ccb_u4.recv_desc_pa = dma_pa; |
311 | 312 | ||
312 | driver_ccb->channel = slot; | 313 | driver_ccb->channel = slot; |
313 | ilo_ccb->channel = slot; | 314 | ilo_ccb->channel = slot; |
diff --git a/drivers/misc/hpilo.h b/drivers/misc/hpilo.h index 247eb386a973..54e43adbdea1 100644 --- a/drivers/misc/hpilo.h +++ b/drivers/misc/hpilo.h | |||
@@ -79,21 +79,21 @@ struct ilo_hwinfo { | |||
79 | struct ccb { | 79 | struct ccb { |
80 | union { | 80 | union { |
81 | char *send_fifobar; | 81 | char *send_fifobar; |
82 | u64 padding1; | 82 | u64 send_fifobar_pa; |
83 | } ccb_u1; | 83 | } ccb_u1; |
84 | union { | 84 | union { |
85 | char *send_desc; | 85 | char *send_desc; |
86 | u64 padding2; | 86 | u64 send_desc_pa; |
87 | } ccb_u2; | 87 | } ccb_u2; |
88 | u64 send_ctrl; | 88 | u64 send_ctrl; |
89 | 89 | ||
90 | union { | 90 | union { |
91 | char *recv_fifobar; | 91 | char *recv_fifobar; |
92 | u64 padding3; | 92 | u64 recv_fifobar_pa; |
93 | } ccb_u3; | 93 | } ccb_u3; |
94 | union { | 94 | union { |
95 | char *recv_desc; | 95 | char *recv_desc; |
96 | u64 padding4; | 96 | u64 recv_desc_pa; |
97 | } ccb_u4; | 97 | } ccb_u4; |
98 | u64 recv_ctrl; | 98 | u64 recv_ctrl; |
99 | 99 | ||
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index f8210bf2d241..1e2cbf5d9aa1 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
@@ -311,15 +311,17 @@ config SM_FTL | |||
311 | select MTD_BLKDEVS | 311 | select MTD_BLKDEVS |
312 | select MTD_NAND_ECC | 312 | select MTD_NAND_ECC |
313 | help | 313 | help |
314 | This enables new and very EXPERMENTAL support for SmartMedia/xD | 314 | This enables EXPERIMENTAL R/W support for SmartMedia/xD |
315 | FTL (Flash translation layer). | 315 | FTL (Flash translation layer). |
316 | Write support isn't yet well tested, therefore this code IS likely to | 316 | Write support is only lightly tested, therefore this driver |
317 | eat your card, so please don't use it together with valuable data. | 317 | isn't recommended to use with valuable data (anyway if you have |
318 | Use readonly driver (CONFIG_SSFDC) instead. | 318 | valuable data, do backups regardless of software/hardware you |
319 | use, because you never know what will eat your data...) | ||
320 | If you only need R/O access, you can use older R/O driver | ||
321 | (CONFIG_SSFDC) | ||
319 | 322 | ||
320 | config MTD_OOPS | 323 | config MTD_OOPS |
321 | tristate "Log panic/oops to an MTD buffer" | 324 | tristate "Log panic/oops to an MTD buffer" |
322 | depends on MTD | ||
323 | help | 325 | help |
324 | This enables panic and oops messages to be logged to a circular | 326 | This enables panic and oops messages to be logged to a circular |
325 | buffer in a flash partition where it can be read back at some | 327 | buffer in a flash partition where it can be read back at some |
diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c index cec7ab98b2a9..302372c08b56 100644 --- a/drivers/mtd/afs.c +++ b/drivers/mtd/afs.c | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | drivers/mtd/afs.c: ARM Flash Layout/Partitioning | 3 | drivers/mtd/afs.c: ARM Flash Layout/Partitioning |
4 | 4 | ||
5 | Copyright (C) 2000 ARM Limited | 5 | Copyright © 2000 ARM Limited |
6 | 6 | ||
7 | This program is free software; you can redistribute it and/or modify | 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 | 8 | it under the terms of the GNU General Public License as published by |
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 62f3ea9de848..9e2b7e9e0ad9 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/mtd/xip.h> | 34 | #include <linux/mtd/xip.h> |
35 | #include <linux/mtd/map.h> | 35 | #include <linux/mtd/map.h> |
36 | #include <linux/mtd/mtd.h> | 36 | #include <linux/mtd/mtd.h> |
37 | #include <linux/mtd/compatmac.h> | ||
38 | #include <linux/mtd/cfi.h> | 37 | #include <linux/mtd/cfi.h> |
39 | 38 | ||
40 | /* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */ | 39 | /* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */ |
@@ -63,6 +62,8 @@ static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *); | |||
63 | static void cfi_intelext_sync (struct mtd_info *); | 62 | static void cfi_intelext_sync (struct mtd_info *); |
64 | static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | 63 | static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
65 | static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | 64 | static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
65 | static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs, | ||
66 | uint64_t len); | ||
66 | #ifdef CONFIG_MTD_OTP | 67 | #ifdef CONFIG_MTD_OTP |
67 | static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 68 | static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
68 | static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 69 | static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
@@ -448,6 +449,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) | |||
448 | mtd->sync = cfi_intelext_sync; | 449 | mtd->sync = cfi_intelext_sync; |
449 | mtd->lock = cfi_intelext_lock; | 450 | mtd->lock = cfi_intelext_lock; |
450 | mtd->unlock = cfi_intelext_unlock; | 451 | mtd->unlock = cfi_intelext_unlock; |
452 | mtd->is_locked = cfi_intelext_is_locked; | ||
451 | mtd->suspend = cfi_intelext_suspend; | 453 | mtd->suspend = cfi_intelext_suspend; |
452 | mtd->resume = cfi_intelext_resume; | 454 | mtd->resume = cfi_intelext_resume; |
453 | mtd->flags = MTD_CAP_NORFLASH; | 455 | mtd->flags = MTD_CAP_NORFLASH; |
@@ -717,7 +719,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, | |||
717 | chip = &newcfi->chips[0]; | 719 | chip = &newcfi->chips[0]; |
718 | for (i = 0; i < cfi->numchips; i++) { | 720 | for (i = 0; i < cfi->numchips; i++) { |
719 | shared[i].writing = shared[i].erasing = NULL; | 721 | shared[i].writing = shared[i].erasing = NULL; |
720 | spin_lock_init(&shared[i].lock); | 722 | mutex_init(&shared[i].lock); |
721 | for (j = 0; j < numparts; j++) { | 723 | for (j = 0; j < numparts; j++) { |
722 | *chip = cfi->chips[i]; | 724 | *chip = cfi->chips[i]; |
723 | chip->start += j << partshift; | 725 | chip->start += j << partshift; |
@@ -886,7 +888,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
886 | */ | 888 | */ |
887 | struct flchip_shared *shared = chip->priv; | 889 | struct flchip_shared *shared = chip->priv; |
888 | struct flchip *contender; | 890 | struct flchip *contender; |
889 | spin_lock(&shared->lock); | 891 | mutex_lock(&shared->lock); |
890 | contender = shared->writing; | 892 | contender = shared->writing; |
891 | if (contender && contender != chip) { | 893 | if (contender && contender != chip) { |
892 | /* | 894 | /* |
@@ -899,7 +901,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
899 | * get_chip returns success we're clear to go ahead. | 901 | * get_chip returns success we're clear to go ahead. |
900 | */ | 902 | */ |
901 | ret = mutex_trylock(&contender->mutex); | 903 | ret = mutex_trylock(&contender->mutex); |
902 | spin_unlock(&shared->lock); | 904 | mutex_unlock(&shared->lock); |
903 | if (!ret) | 905 | if (!ret) |
904 | goto retry; | 906 | goto retry; |
905 | mutex_unlock(&chip->mutex); | 907 | mutex_unlock(&chip->mutex); |
@@ -914,7 +916,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
914 | mutex_unlock(&contender->mutex); | 916 | mutex_unlock(&contender->mutex); |
915 | return ret; | 917 | return ret; |
916 | } | 918 | } |
917 | spin_lock(&shared->lock); | 919 | mutex_lock(&shared->lock); |
918 | 920 | ||
919 | /* We should not own chip if it is already | 921 | /* We should not own chip if it is already |
920 | * in FL_SYNCING state. Put contender and retry. */ | 922 | * in FL_SYNCING state. Put contender and retry. */ |
@@ -930,7 +932,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
930 | * on this chip. Sleep. */ | 932 | * on this chip. Sleep. */ |
931 | if (mode == FL_ERASING && shared->erasing | 933 | if (mode == FL_ERASING && shared->erasing |
932 | && shared->erasing->oldstate == FL_ERASING) { | 934 | && shared->erasing->oldstate == FL_ERASING) { |
933 | spin_unlock(&shared->lock); | 935 | mutex_unlock(&shared->lock); |
934 | set_current_state(TASK_UNINTERRUPTIBLE); | 936 | set_current_state(TASK_UNINTERRUPTIBLE); |
935 | add_wait_queue(&chip->wq, &wait); | 937 | add_wait_queue(&chip->wq, &wait); |
936 | mutex_unlock(&chip->mutex); | 938 | mutex_unlock(&chip->mutex); |
@@ -944,7 +946,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
944 | shared->writing = chip; | 946 | shared->writing = chip; |
945 | if (mode == FL_ERASING) | 947 | if (mode == FL_ERASING) |
946 | shared->erasing = chip; | 948 | shared->erasing = chip; |
947 | spin_unlock(&shared->lock); | 949 | mutex_unlock(&shared->lock); |
948 | } | 950 | } |
949 | ret = chip_ready(map, chip, adr, mode); | 951 | ret = chip_ready(map, chip, adr, mode); |
950 | if (ret == -EAGAIN) | 952 | if (ret == -EAGAIN) |
@@ -959,7 +961,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
959 | 961 | ||
960 | if (chip->priv) { | 962 | if (chip->priv) { |
961 | struct flchip_shared *shared = chip->priv; | 963 | struct flchip_shared *shared = chip->priv; |
962 | spin_lock(&shared->lock); | 964 | mutex_lock(&shared->lock); |
963 | if (shared->writing == chip && chip->oldstate == FL_READY) { | 965 | if (shared->writing == chip && chip->oldstate == FL_READY) { |
964 | /* We own the ability to write, but we're done */ | 966 | /* We own the ability to write, but we're done */ |
965 | shared->writing = shared->erasing; | 967 | shared->writing = shared->erasing; |
@@ -967,7 +969,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
967 | /* give back ownership to who we loaned it from */ | 969 | /* give back ownership to who we loaned it from */ |
968 | struct flchip *loaner = shared->writing; | 970 | struct flchip *loaner = shared->writing; |
969 | mutex_lock(&loaner->mutex); | 971 | mutex_lock(&loaner->mutex); |
970 | spin_unlock(&shared->lock); | 972 | mutex_unlock(&shared->lock); |
971 | mutex_unlock(&chip->mutex); | 973 | mutex_unlock(&chip->mutex); |
972 | put_chip(map, loaner, loaner->start); | 974 | put_chip(map, loaner, loaner->start); |
973 | mutex_lock(&chip->mutex); | 975 | mutex_lock(&chip->mutex); |
@@ -985,11 +987,11 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
985 | * Don't let the switch below mess things up since | 987 | * Don't let the switch below mess things up since |
986 | * we don't have ownership to resume anything. | 988 | * we don't have ownership to resume anything. |
987 | */ | 989 | */ |
988 | spin_unlock(&shared->lock); | 990 | mutex_unlock(&shared->lock); |
989 | wake_up(&chip->wq); | 991 | wake_up(&chip->wq); |
990 | return; | 992 | return; |
991 | } | 993 | } |
992 | spin_unlock(&shared->lock); | 994 | mutex_unlock(&shared->lock); |
993 | } | 995 | } |
994 | 996 | ||
995 | switch(chip->oldstate) { | 997 | switch(chip->oldstate) { |
@@ -2139,6 +2141,13 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
2139 | return ret; | 2141 | return ret; |
2140 | } | 2142 | } |
2141 | 2143 | ||
2144 | static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs, | ||
2145 | uint64_t len) | ||
2146 | { | ||
2147 | return cfi_varsize_frob(mtd, do_getlockstatus_oneblock, | ||
2148 | ofs, len, NULL) ? 1 : 0; | ||
2149 | } | ||
2150 | |||
2142 | #ifdef CONFIG_MTD_OTP | 2151 | #ifdef CONFIG_MTD_OTP |
2143 | 2152 | ||
2144 | typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip, | 2153 | typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip, |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index d81079ef91a5..3e6c47bdce53 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
35 | #include <linux/reboot.h> | 35 | #include <linux/reboot.h> |
36 | #include <linux/mtd/compatmac.h> | ||
37 | #include <linux/mtd/map.h> | 36 | #include <linux/mtd/map.h> |
38 | #include <linux/mtd/mtd.h> | 37 | #include <linux/mtd/mtd.h> |
39 | #include <linux/mtd/cfi.h> | 38 | #include <linux/mtd/cfi.h> |
@@ -417,16 +416,26 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | |||
417 | */ | 416 | */ |
418 | cfi_fixup_major_minor(cfi, extp); | 417 | cfi_fixup_major_minor(cfi, extp); |
419 | 418 | ||
419 | /* | ||
420 | * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4 | ||
421 | * see: http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_r20.pdf, page 19 | ||
422 | * http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_100_20011201.pdf | ||
423 | * http://www.spansion.com/Support/Datasheets/s29ws-p_00_a12_e.pdf | ||
424 | */ | ||
420 | if (extp->MajorVersion != '1' || | 425 | if (extp->MajorVersion != '1' || |
421 | (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { | 426 | (extp->MajorVersion == '1' && (extp->MinorVersion < '0' || extp->MinorVersion > '4'))) { |
422 | printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " | 427 | printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " |
423 | "version %c.%c.\n", extp->MajorVersion, | 428 | "version %c.%c (%#02x/%#02x).\n", |
424 | extp->MinorVersion); | 429 | extp->MajorVersion, extp->MinorVersion, |
430 | extp->MajorVersion, extp->MinorVersion); | ||
425 | kfree(extp); | 431 | kfree(extp); |
426 | kfree(mtd); | 432 | kfree(mtd); |
427 | return NULL; | 433 | return NULL; |
428 | } | 434 | } |
429 | 435 | ||
436 | printk(KERN_INFO " Amd/Fujitsu Extended Query version %c.%c.\n", | ||
437 | extp->MajorVersion, extp->MinorVersion); | ||
438 | |||
430 | /* Install our own private info structure */ | 439 | /* Install our own private info structure */ |
431 | cfi->cmdset_priv = extp; | 440 | cfi->cmdset_priv = extp; |
432 | 441 | ||
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index e54e8c169d76..314af1f5a370 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/mtd/map.h> | 33 | #include <linux/mtd/map.h> |
34 | #include <linux/mtd/cfi.h> | 34 | #include <linux/mtd/cfi.h> |
35 | #include <linux/mtd/mtd.h> | 35 | #include <linux/mtd/mtd.h> |
36 | #include <linux/mtd/compatmac.h> | ||
37 | 36 | ||
38 | 37 | ||
39 | static int cfi_staa_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 38 | static int cfi_staa_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index b2acd32f4fbf..8f5b96aa87a0 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c | |||
@@ -235,9 +235,9 @@ static int __xipram cfi_chip_setup(struct map_info *map, | |||
235 | cfi_qry_mode_off(base, map, cfi); | 235 | cfi_qry_mode_off(base, map, cfi); |
236 | xip_allowed(base, map); | 236 | xip_allowed(base, map); |
237 | 237 | ||
238 | printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n", | 238 | printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank. Manufacturer ID %#08x Chip ID %#08x\n", |
239 | map->name, cfi->interleave, cfi->device_type*8, base, | 239 | map->name, cfi->interleave, cfi->device_type*8, base, |
240 | map->bankwidth*8); | 240 | map->bankwidth*8, cfi->mfr, cfi->id); |
241 | 241 | ||
242 | return 1; | 242 | return 1; |
243 | } | 243 | } |
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index d7c2c672757e..e503b2ca894d 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/mtd/mtd.h> | 22 | #include <linux/mtd/mtd.h> |
23 | #include <linux/mtd/map.h> | 23 | #include <linux/mtd/map.h> |
24 | #include <linux/mtd/cfi.h> | 24 | #include <linux/mtd/cfi.h> |
25 | #include <linux/mtd/compatmac.h> | ||
26 | 25 | ||
27 | int __xipram cfi_qry_present(struct map_info *map, __u32 base, | 26 | int __xipram cfi_qry_present(struct map_info *map, __u32 base, |
28 | struct cfi_private *cfi) | 27 | struct cfi_private *cfi) |
diff --git a/drivers/mtd/chips/chipreg.c b/drivers/mtd/chips/chipreg.c index c85760968227..da1f96f385c7 100644 --- a/drivers/mtd/chips/chipreg.c +++ b/drivers/mtd/chips/chipreg.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | #include <linux/mtd/map.h> | 11 | #include <linux/mtd/map.h> |
12 | #include <linux/mtd/mtd.h> | 12 | #include <linux/mtd/mtd.h> |
13 | #include <linux/mtd/compatmac.h> | ||
14 | 13 | ||
15 | static DEFINE_SPINLOCK(chip_drvs_lock); | 14 | static DEFINE_SPINLOCK(chip_drvs_lock); |
16 | static LIST_HEAD(chip_drvs_list); | 15 | static LIST_HEAD(chip_drvs_list); |
diff --git a/drivers/mtd/chips/map_absent.c b/drivers/mtd/chips/map_absent.c index 494d30d0631a..f2b872946871 100644 --- a/drivers/mtd/chips/map_absent.c +++ b/drivers/mtd/chips/map_absent.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/mtd/mtd.h> | 26 | #include <linux/mtd/mtd.h> |
27 | #include <linux/mtd/map.h> | 27 | #include <linux/mtd/map.h> |
28 | #include <linux/mtd/compatmac.h> | ||
29 | 28 | ||
30 | static int map_absent_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 29 | static int map_absent_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
31 | static int map_absent_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); | 30 | static int map_absent_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); |
diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c index 6bdc50c727e7..67640ccb2d41 100644 --- a/drivers/mtd/chips/map_ram.c +++ b/drivers/mtd/chips/map_ram.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/mtd/mtd.h> | 14 | #include <linux/mtd/mtd.h> |
15 | #include <linux/mtd/map.h> | 15 | #include <linux/mtd/map.h> |
16 | #include <linux/mtd/compatmac.h> | ||
17 | 16 | ||
18 | 17 | ||
19 | static int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 18 | static int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c index 076090a67b90..593f73d480d2 100644 --- a/drivers/mtd/chips/map_rom.c +++ b/drivers/mtd/chips/map_rom.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/mtd/mtd.h> | 14 | #include <linux/mtd/mtd.h> |
15 | #include <linux/mtd/map.h> | 15 | #include <linux/mtd/map.h> |
16 | #include <linux/mtd/compatmac.h> | ||
17 | 16 | ||
18 | static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 17 | static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
19 | static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); | 18 | static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); |
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 1479da6d3aa6..e790f38893b0 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c | |||
@@ -1,7 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | * Read flash partition table from command line | 2 | * Read flash partition table from command line |
3 | * | 3 | * |
4 | * Copyright 2002 SYSGO Real-Time Solutions GmbH | 4 | * Copyright © 2002 SYSGO Real-Time Solutions GmbH |
5 | * Copyright © 2002-2010 David Woodhouse <dwmw2@infradead.org> | ||
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
5 | * | 20 | * |
6 | * The format for the command line is as follows: | 21 | * The format for the command line is as follows: |
7 | * | 22 | * |
diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c index a19cda52da5c..a99838bb2dc0 100644 --- a/drivers/mtd/devices/docecc.c +++ b/drivers/mtd/devices/docecc.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | 33 | ||
34 | #include <linux/mtd/compatmac.h> /* for min() in older kernels */ | ||
35 | #include <linux/mtd/mtd.h> | 34 | #include <linux/mtd/mtd.h> |
36 | #include <linux/mtd/doc2000.h> | 35 | #include <linux/mtd/doc2000.h> |
37 | 36 | ||
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index 6e62922942b1..d374603493a7 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c | |||
@@ -49,7 +49,6 @@ | |||
49 | #include <linux/mtd/mtd.h> | 49 | #include <linux/mtd/mtd.h> |
50 | #include <linux/mtd/nand.h> | 50 | #include <linux/mtd/nand.h> |
51 | #include <linux/mtd/doc2000.h> | 51 | #include <linux/mtd/doc2000.h> |
52 | #include <linux/mtd/compatmac.h> | ||
53 | 52 | ||
54 | /* Where to look for the devices? */ | 53 | /* Where to look for the devices? */ |
55 | #ifndef CONFIG_MTD_DOCPROBE_ADDRESS | 54 | #ifndef CONFIG_MTD_DOCPROBE_ADDRESS |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 81e49a9b017e..f90941a785e4 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -16,6 +16,8 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/err.h> | ||
20 | #include <linux/errno.h> | ||
19 | #include <linux/module.h> | 21 | #include <linux/module.h> |
20 | #include <linux/device.h> | 22 | #include <linux/device.h> |
21 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
@@ -639,8 +641,18 @@ static const struct spi_device_id m25p_ids[] = { | |||
639 | { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) }, | 641 | { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) }, |
640 | { "at26df321", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, | 642 | { "at26df321", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, |
641 | 643 | ||
644 | /* EON -- en25pxx */ | ||
645 | { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, | ||
646 | { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, | ||
647 | |||
648 | /* Intel/Numonyx -- xxxs33b */ | ||
649 | { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, | ||
650 | { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, | ||
651 | { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, | ||
652 | |||
642 | /* Macronix */ | 653 | /* Macronix */ |
643 | { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, | 654 | { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, |
655 | { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, | ||
644 | { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, | 656 | { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, |
645 | { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, | 657 | { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, |
646 | { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, | 658 | { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, |
@@ -680,6 +692,16 @@ static const struct spi_device_id m25p_ids[] = { | |||
680 | { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, | 692 | { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, |
681 | { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, | 693 | { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, |
682 | 694 | ||
695 | { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, | ||
696 | { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, | ||
697 | { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) }, | ||
698 | { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) }, | ||
699 | { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) }, | ||
700 | { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) }, | ||
701 | { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) }, | ||
702 | { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) }, | ||
703 | { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) }, | ||
704 | |||
683 | { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) }, | 705 | { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) }, |
684 | { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) }, | 706 | { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) }, |
685 | { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) }, | 707 | { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) }, |
@@ -694,6 +716,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
694 | { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, | 716 | { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, |
695 | { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, | 717 | { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, |
696 | { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, | 718 | { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, |
719 | { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, | ||
697 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, | 720 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, |
698 | 721 | ||
699 | /* Catalyst / On Semiconductor -- non-JEDEC */ | 722 | /* Catalyst / On Semiconductor -- non-JEDEC */ |
@@ -723,7 +746,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) | |||
723 | if (tmp < 0) { | 746 | if (tmp < 0) { |
724 | DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n", | 747 | DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n", |
725 | dev_name(&spi->dev), tmp); | 748 | dev_name(&spi->dev), tmp); |
726 | return NULL; | 749 | return ERR_PTR(tmp); |
727 | } | 750 | } |
728 | jedec = id[0]; | 751 | jedec = id[0]; |
729 | jedec = jedec << 8; | 752 | jedec = jedec << 8; |
@@ -731,14 +754,6 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) | |||
731 | jedec = jedec << 8; | 754 | jedec = jedec << 8; |
732 | jedec |= id[2]; | 755 | jedec |= id[2]; |
733 | 756 | ||
734 | /* | ||
735 | * Some chips (like Numonyx M25P80) have JEDEC and non-JEDEC variants, | ||
736 | * which depend on technology process. Officially RDID command doesn't | ||
737 | * exist for non-JEDEC chips, but for compatibility they return ID 0. | ||
738 | */ | ||
739 | if (jedec == 0) | ||
740 | return NULL; | ||
741 | |||
742 | ext_jedec = id[3] << 8 | id[4]; | 757 | ext_jedec = id[3] << 8 | id[4]; |
743 | 758 | ||
744 | for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) { | 759 | for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) { |
@@ -749,7 +764,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) | |||
749 | return &m25p_ids[tmp]; | 764 | return &m25p_ids[tmp]; |
750 | } | 765 | } |
751 | } | 766 | } |
752 | return NULL; | 767 | return ERR_PTR(-ENODEV); |
753 | } | 768 | } |
754 | 769 | ||
755 | 770 | ||
@@ -794,9 +809,8 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
794 | const struct spi_device_id *jid; | 809 | const struct spi_device_id *jid; |
795 | 810 | ||
796 | jid = jedec_probe(spi); | 811 | jid = jedec_probe(spi); |
797 | if (!jid) { | 812 | if (IS_ERR(jid)) { |
798 | dev_info(&spi->dev, "non-JEDEC variant of %s\n", | 813 | return PTR_ERR(jid); |
799 | id->name); | ||
800 | } else if (jid != id) { | 814 | } else if (jid != id) { |
801 | /* | 815 | /* |
802 | * JEDEC knows better, so overwrite platform ID. We | 816 | * JEDEC knows better, so overwrite platform ID. We |
@@ -826,11 +840,12 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
826 | dev_set_drvdata(&spi->dev, flash); | 840 | dev_set_drvdata(&spi->dev, flash); |
827 | 841 | ||
828 | /* | 842 | /* |
829 | * Atmel and SST serial flash tend to power | 843 | * Atmel, SST and Intel/Numonyx serial flash tend to power |
830 | * up with the software protection bits set | 844 | * up with the software protection bits set |
831 | */ | 845 | */ |
832 | 846 | ||
833 | if (info->jedec_id >> 16 == 0x1f || | 847 | if (info->jedec_id >> 16 == 0x1f || |
848 | info->jedec_id >> 16 == 0x89 || | ||
834 | info->jedec_id >> 16 == 0xbf) { | 849 | info->jedec_id >> 16 == 0xbf) { |
835 | write_enable(flash); | 850 | write_enable(flash); |
836 | write_sr(flash, 0); | 851 | write_sr(flash, 0); |
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 19817404ce7d..c5015cc721d5 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -141,7 +141,7 @@ static int dataflash_waitready(struct spi_device *spi) | |||
141 | */ | 141 | */ |
142 | static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | 142 | static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) |
143 | { | 143 | { |
144 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 144 | struct dataflash *priv = mtd->priv; |
145 | struct spi_device *spi = priv->spi; | 145 | struct spi_device *spi = priv->spi; |
146 | struct spi_transfer x = { .tx_dma = 0, }; | 146 | struct spi_transfer x = { .tx_dma = 0, }; |
147 | struct spi_message msg; | 147 | struct spi_message msg; |
@@ -231,7 +231,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
231 | static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | 231 | static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, |
232 | size_t *retlen, u_char *buf) | 232 | size_t *retlen, u_char *buf) |
233 | { | 233 | { |
234 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 234 | struct dataflash *priv = mtd->priv; |
235 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; | 235 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; |
236 | struct spi_message msg; | 236 | struct spi_message msg; |
237 | unsigned int addr; | 237 | unsigned int addr; |
@@ -304,7 +304,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
304 | static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | 304 | static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, |
305 | size_t * retlen, const u_char * buf) | 305 | size_t * retlen, const u_char * buf) |
306 | { | 306 | { |
307 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 307 | struct dataflash *priv = mtd->priv; |
308 | struct spi_device *spi = priv->spi; | 308 | struct spi_device *spi = priv->spi; |
309 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; | 309 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; |
310 | struct spi_message msg; | 310 | struct spi_message msg; |
@@ -515,7 +515,7 @@ static ssize_t otp_read(struct spi_device *spi, unsigned base, | |||
515 | static int dataflash_read_fact_otp(struct mtd_info *mtd, | 515 | static int dataflash_read_fact_otp(struct mtd_info *mtd, |
516 | loff_t from, size_t len, size_t *retlen, u_char *buf) | 516 | loff_t from, size_t len, size_t *retlen, u_char *buf) |
517 | { | 517 | { |
518 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 518 | struct dataflash *priv = mtd->priv; |
519 | int status; | 519 | int status; |
520 | 520 | ||
521 | /* 64 bytes, from 0..63 ... start at 64 on-chip */ | 521 | /* 64 bytes, from 0..63 ... start at 64 on-chip */ |
@@ -532,7 +532,7 @@ static int dataflash_read_fact_otp(struct mtd_info *mtd, | |||
532 | static int dataflash_read_user_otp(struct mtd_info *mtd, | 532 | static int dataflash_read_user_otp(struct mtd_info *mtd, |
533 | loff_t from, size_t len, size_t *retlen, u_char *buf) | 533 | loff_t from, size_t len, size_t *retlen, u_char *buf) |
534 | { | 534 | { |
535 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 535 | struct dataflash *priv = mtd->priv; |
536 | int status; | 536 | int status; |
537 | 537 | ||
538 | /* 64 bytes, from 0..63 ... start at 0 on-chip */ | 538 | /* 64 bytes, from 0..63 ... start at 0 on-chip */ |
@@ -553,7 +553,7 @@ static int dataflash_write_user_otp(struct mtd_info *mtd, | |||
553 | const size_t l = 4 + 64; | 553 | const size_t l = 4 + 64; |
554 | uint8_t *scratch; | 554 | uint8_t *scratch; |
555 | struct spi_transfer t; | 555 | struct spi_transfer t; |
556 | struct dataflash *priv = (struct dataflash *)mtd->priv; | 556 | struct dataflash *priv = mtd->priv; |
557 | int status; | 557 | int status; |
558 | 558 | ||
559 | if (len > 64) | 559 | if (len > 64) |
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index fce5ff7589aa..26a6e809013d 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/ioport.h> | 14 | #include <linux/ioport.h> |
15 | #include <linux/vmalloc.h> | 15 | #include <linux/vmalloc.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/mtd/compatmac.h> | ||
18 | #include <linux/mtd/mtd.h> | 17 | #include <linux/mtd/mtd.h> |
19 | #include <linux/mtd/mtdram.h> | 18 | #include <linux/mtd/mtdram.h> |
20 | 19 | ||
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index fc8ea0a57ac2..ef0aba0ce58f 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c | |||
@@ -98,7 +98,6 @@ | |||
98 | 98 | ||
99 | #include <linux/mtd/mtd.h> | 99 | #include <linux/mtd/mtd.h> |
100 | #include <linux/mtd/pmc551.h> | 100 | #include <linux/mtd/pmc551.h> |
101 | #include <linux/mtd/compatmac.h> | ||
102 | 101 | ||
103 | static struct mtd_info *pmc551list; | 102 | static struct mtd_info *pmc551list; |
104 | 103 | ||
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index ab5d8cd02a15..684247a8a5ed 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c | |||
@@ -454,7 +454,7 @@ static int __init sst25l_probe(struct spi_device *spi) | |||
454 | parts, nr_parts); | 454 | parts, nr_parts); |
455 | } | 455 | } |
456 | 456 | ||
457 | } else if (data->nr_parts) { | 457 | } else if (data && data->nr_parts) { |
458 | dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", | 458 | dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", |
459 | data->nr_parts, data->name); | 459 | data->nr_parts, data->name); |
460 | } | 460 | } |
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index 62da9eb7032b..4d6a64c387ec 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | The initial developer of the original code is David A. Hinds | 27 | The initial developer of the original code is David A. Hinds |
28 | <dahinds@users.sourceforge.net>. Portions created by David A. Hinds | 28 | <dahinds@users.sourceforge.net>. Portions created by David A. Hinds |
29 | are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | 29 | are Copyright © 1999 David A. Hinds. All Rights Reserved. |
30 | 30 | ||
31 | Alternatively, the contents of this file may be used under the | 31 | Alternatively, the contents of this file may be used under the |
32 | terms of the GNU General Public License version 2 (the "GPL"), in | 32 | terms of the GNU General Public License version 2 (the "GPL"), in |
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 015a7fe1b6ee..d7592e67d048 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c | |||
@@ -1,11 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL) | 2 | * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL) |
3 | * | 3 | * |
4 | * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) | 4 | * Copyright © 2002, Greg Ungerer (gerg@snapgear.com) |
5 | * | 5 | * |
6 | * Based heavily on the nftlcore.c code which is: | 6 | * Based heavily on the nftlcore.c code which is: |
7 | * (c) 1999 Machine Vision Holdings, Inc. | 7 | * Copyright © 1999 Machine Vision Holdings, Inc. |
8 | * Author: David Woodhouse <dwmw2@infradead.org> | 8 | * Copyright © 1999 David Woodhouse <dwmw2@infradead.org> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index 8f988d7d3c5c..104052e774b0 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c | |||
@@ -2,11 +2,11 @@ | |||
2 | * inftlmount.c -- INFTL mount code with extensive checks. | 2 | * inftlmount.c -- INFTL mount code with extensive checks. |
3 | * | 3 | * |
4 | * Author: Greg Ungerer (gerg@snapgear.com) | 4 | * Author: Greg Ungerer (gerg@snapgear.com) |
5 | * (C) Copyright 2002-2003, Greg Ungerer (gerg@snapgear.com) | 5 | * Copyright © 2002-2003, Greg Ungerer (gerg@snapgear.com) |
6 | * | 6 | * |
7 | * Based heavily on the nftlmount.c code which is: | 7 | * Based heavily on the nftlmount.c code which is: |
8 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) | 8 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) |
9 | * Copyright (C) 2000 Netgem S.A. | 9 | * Copyright © 2000 Netgem S.A. |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/mtd/mtd.h> | 34 | #include <linux/mtd/mtd.h> |
35 | #include <linux/mtd/nftl.h> | 35 | #include <linux/mtd/nftl.h> |
36 | #include <linux/mtd/inftl.h> | 36 | #include <linux/mtd/inftl.h> |
37 | #include <linux/mtd/compatmac.h> | ||
38 | 37 | ||
39 | /* | 38 | /* |
40 | * find_boot_record: Find the INFTL Media Header and its Spare copy which | 39 | * find_boot_record: Find the INFTL Media Header and its Spare copy which |
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c index fece5be58715..04fdfcca93f7 100644 --- a/drivers/mtd/lpddr/lpddr_cmds.c +++ b/drivers/mtd/lpddr/lpddr_cmds.c | |||
@@ -98,7 +98,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map) | |||
98 | numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum; | 98 | numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum; |
99 | for (i = 0; i < numchips; i++) { | 99 | for (i = 0; i < numchips; i++) { |
100 | shared[i].writing = shared[i].erasing = NULL; | 100 | shared[i].writing = shared[i].erasing = NULL; |
101 | spin_lock_init(&shared[i].lock); | 101 | mutex_init(&shared[i].lock); |
102 | for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) { | 102 | for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) { |
103 | *chip = lpddr->chips[i]; | 103 | *chip = lpddr->chips[i]; |
104 | chip->start += j << lpddr->chipshift; | 104 | chip->start += j << lpddr->chipshift; |
@@ -217,7 +217,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) | |||
217 | */ | 217 | */ |
218 | struct flchip_shared *shared = chip->priv; | 218 | struct flchip_shared *shared = chip->priv; |
219 | struct flchip *contender; | 219 | struct flchip *contender; |
220 | spin_lock(&shared->lock); | 220 | mutex_lock(&shared->lock); |
221 | contender = shared->writing; | 221 | contender = shared->writing; |
222 | if (contender && contender != chip) { | 222 | if (contender && contender != chip) { |
223 | /* | 223 | /* |
@@ -230,7 +230,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) | |||
230 | * get_chip returns success we're clear to go ahead. | 230 | * get_chip returns success we're clear to go ahead. |
231 | */ | 231 | */ |
232 | ret = mutex_trylock(&contender->mutex); | 232 | ret = mutex_trylock(&contender->mutex); |
233 | spin_unlock(&shared->lock); | 233 | mutex_unlock(&shared->lock); |
234 | if (!ret) | 234 | if (!ret) |
235 | goto retry; | 235 | goto retry; |
236 | mutex_unlock(&chip->mutex); | 236 | mutex_unlock(&chip->mutex); |
@@ -245,7 +245,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) | |||
245 | mutex_unlock(&contender->mutex); | 245 | mutex_unlock(&contender->mutex); |
246 | return ret; | 246 | return ret; |
247 | } | 247 | } |
248 | spin_lock(&shared->lock); | 248 | mutex_lock(&shared->lock); |
249 | 249 | ||
250 | /* We should not own chip if it is already in FL_SYNCING | 250 | /* We should not own chip if it is already in FL_SYNCING |
251 | * state. Put contender and retry. */ | 251 | * state. Put contender and retry. */ |
@@ -261,7 +261,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) | |||
261 | Must sleep in such a case. */ | 261 | Must sleep in such a case. */ |
262 | if (mode == FL_ERASING && shared->erasing | 262 | if (mode == FL_ERASING && shared->erasing |
263 | && shared->erasing->oldstate == FL_ERASING) { | 263 | && shared->erasing->oldstate == FL_ERASING) { |
264 | spin_unlock(&shared->lock); | 264 | mutex_unlock(&shared->lock); |
265 | set_current_state(TASK_UNINTERRUPTIBLE); | 265 | set_current_state(TASK_UNINTERRUPTIBLE); |
266 | add_wait_queue(&chip->wq, &wait); | 266 | add_wait_queue(&chip->wq, &wait); |
267 | mutex_unlock(&chip->mutex); | 267 | mutex_unlock(&chip->mutex); |
@@ -275,7 +275,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode) | |||
275 | shared->writing = chip; | 275 | shared->writing = chip; |
276 | if (mode == FL_ERASING) | 276 | if (mode == FL_ERASING) |
277 | shared->erasing = chip; | 277 | shared->erasing = chip; |
278 | spin_unlock(&shared->lock); | 278 | mutex_unlock(&shared->lock); |
279 | } | 279 | } |
280 | 280 | ||
281 | ret = chip_ready(map, chip, mode); | 281 | ret = chip_ready(map, chip, mode); |
@@ -348,7 +348,7 @@ static void put_chip(struct map_info *map, struct flchip *chip) | |||
348 | { | 348 | { |
349 | if (chip->priv) { | 349 | if (chip->priv) { |
350 | struct flchip_shared *shared = chip->priv; | 350 | struct flchip_shared *shared = chip->priv; |
351 | spin_lock(&shared->lock); | 351 | mutex_lock(&shared->lock); |
352 | if (shared->writing == chip && chip->oldstate == FL_READY) { | 352 | if (shared->writing == chip && chip->oldstate == FL_READY) { |
353 | /* We own the ability to write, but we're done */ | 353 | /* We own the ability to write, but we're done */ |
354 | shared->writing = shared->erasing; | 354 | shared->writing = shared->erasing; |
@@ -356,7 +356,7 @@ static void put_chip(struct map_info *map, struct flchip *chip) | |||
356 | /* give back the ownership */ | 356 | /* give back the ownership */ |
357 | struct flchip *loaner = shared->writing; | 357 | struct flchip *loaner = shared->writing; |
358 | mutex_lock(&loaner->mutex); | 358 | mutex_lock(&loaner->mutex); |
359 | spin_unlock(&shared->lock); | 359 | mutex_unlock(&shared->lock); |
360 | mutex_unlock(&chip->mutex); | 360 | mutex_unlock(&chip->mutex); |
361 | put_chip(map, loaner); | 361 | put_chip(map, loaner); |
362 | mutex_lock(&chip->mutex); | 362 | mutex_lock(&chip->mutex); |
@@ -374,11 +374,11 @@ static void put_chip(struct map_info *map, struct flchip *chip) | |||
374 | * Don't let the switch below mess things up since | 374 | * Don't let the switch below mess things up since |
375 | * we don't have ownership to resume anything. | 375 | * we don't have ownership to resume anything. |
376 | */ | 376 | */ |
377 | spin_unlock(&shared->lock); | 377 | mutex_unlock(&shared->lock); |
378 | wake_up(&chip->wq); | 378 | wake_up(&chip->wq); |
379 | return; | 379 | return; |
380 | } | 380 | } |
381 | spin_unlock(&shared->lock); | 381 | mutex_unlock(&shared->lock); |
382 | } | 382 | } |
383 | 383 | ||
384 | switch (chip->oldstate) { | 384 | switch (chip->oldstate) { |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 6629d09f3b38..701d942c6795 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -319,14 +319,6 @@ config MTD_CFI_FLAGADM | |||
319 | Mapping for the Flaga digital module. If you don't have one, ignore | 319 | Mapping for the Flaga digital module. If you don't have one, ignore |
320 | this setting. | 320 | this setting. |
321 | 321 | ||
322 | config MTD_REDWOOD | ||
323 | tristate "CFI Flash devices mapped on IBM Redwood" | ||
324 | depends on MTD_CFI | ||
325 | help | ||
326 | This enables access routines for the flash chips on the IBM | ||
327 | Redwood board. If you have one of these boards and would like to | ||
328 | use the flash chips on it, say 'Y'. | ||
329 | |||
330 | config MTD_SOLUTIONENGINE | 322 | config MTD_SOLUTIONENGINE |
331 | tristate "CFI Flash device mapped on Hitachi SolutionEngine" | 323 | tristate "CFI Flash device mapped on Hitachi SolutionEngine" |
332 | depends on SUPERH && SOLUTION_ENGINE && MTD_CFI && MTD_REDBOOT_PARTS | 324 | depends on SUPERH && SOLUTION_ENGINE && MTD_CFI && MTD_REDBOOT_PARTS |
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index bb035cd54c72..f216bb573713 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile | |||
@@ -44,7 +44,6 @@ obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o | |||
44 | obj-$(CONFIG_MTD_EDB7312) += edb7312.o | 44 | obj-$(CONFIG_MTD_EDB7312) += edb7312.o |
45 | obj-$(CONFIG_MTD_IMPA7) += impa7.o | 45 | obj-$(CONFIG_MTD_IMPA7) += impa7.o |
46 | obj-$(CONFIG_MTD_FORTUNET) += fortunet.o | 46 | obj-$(CONFIG_MTD_FORTUNET) += fortunet.o |
47 | obj-$(CONFIG_MTD_REDWOOD) += redwood.o | ||
48 | obj-$(CONFIG_MTD_UCLINUX) += uclinux.o | 47 | obj-$(CONFIG_MTD_UCLINUX) += uclinux.o |
49 | obj-$(CONFIG_MTD_NETtel) += nettel.o | 48 | obj-$(CONFIG_MTD_NETtel) += nettel.o |
50 | obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o | 49 | obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o |
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index e0a5e0426ead..1f9fde0dad35 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c | |||
@@ -118,7 +118,7 @@ static void ixp4xx_copy_from(struct map_info *map, void *to, | |||
118 | *dest++ = BYTE1(data); | 118 | *dest++ = BYTE1(data); |
119 | src += 2; | 119 | src += 2; |
120 | len -= 2; | 120 | len -= 2; |
121 | } | 121 | } |
122 | 122 | ||
123 | if (len > 0) | 123 | if (len > 0) |
124 | *dest++ = BYTE0(flash_read16(src)); | 124 | *dest++ = BYTE0(flash_read16(src)); |
@@ -185,6 +185,8 @@ static int ixp4xx_flash_probe(struct platform_device *dev) | |||
185 | { | 185 | { |
186 | struct flash_platform_data *plat = dev->dev.platform_data; | 186 | struct flash_platform_data *plat = dev->dev.platform_data; |
187 | struct ixp4xx_flash_info *info; | 187 | struct ixp4xx_flash_info *info; |
188 | const char *part_type = NULL; | ||
189 | int nr_parts = 0; | ||
188 | int err = -1; | 190 | int err = -1; |
189 | 191 | ||
190 | if (!plat) | 192 | if (!plat) |
@@ -218,9 +220,9 @@ static int ixp4xx_flash_probe(struct platform_device *dev) | |||
218 | */ | 220 | */ |
219 | info->map.bankwidth = 2; | 221 | info->map.bankwidth = 2; |
220 | info->map.name = dev_name(&dev->dev); | 222 | info->map.name = dev_name(&dev->dev); |
221 | info->map.read = ixp4xx_read16, | 223 | info->map.read = ixp4xx_read16; |
222 | info->map.write = ixp4xx_probe_write16, | 224 | info->map.write = ixp4xx_probe_write16; |
223 | info->map.copy_from = ixp4xx_copy_from, | 225 | info->map.copy_from = ixp4xx_copy_from; |
224 | 226 | ||
225 | info->res = request_mem_region(dev->resource->start, | 227 | info->res = request_mem_region(dev->resource->start, |
226 | resource_size(dev->resource), | 228 | resource_size(dev->resource), |
@@ -248,11 +250,28 @@ static int ixp4xx_flash_probe(struct platform_device *dev) | |||
248 | info->mtd->owner = THIS_MODULE; | 250 | info->mtd->owner = THIS_MODULE; |
249 | 251 | ||
250 | /* Use the fast version */ | 252 | /* Use the fast version */ |
251 | info->map.write = ixp4xx_write16, | 253 | info->map.write = ixp4xx_write16; |
254 | |||
255 | #ifdef CONFIG_MTD_PARTITIONS | ||
256 | nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions, | ||
257 | dev->resource->start); | ||
258 | #endif | ||
259 | if (nr_parts > 0) { | ||
260 | part_type = "dynamic"; | ||
261 | } else { | ||
262 | info->partitions = plat->parts; | ||
263 | nr_parts = plat->nr_parts; | ||
264 | part_type = "static"; | ||
265 | } | ||
266 | if (nr_parts == 0) { | ||
267 | printk(KERN_NOTICE "IXP4xx flash: no partition info " | ||
268 | "available, registering whole flash\n"); | ||
269 | err = add_mtd_device(info->mtd); | ||
270 | } else { | ||
271 | printk(KERN_NOTICE "IXP4xx flash: using %s partition " | ||
272 | "definition\n", part_type); | ||
273 | err = add_mtd_partitions(info->mtd, info->partitions, nr_parts); | ||
252 | 274 | ||
253 | err = parse_mtd_partitions(info->mtd, probes, &info->partitions, dev->resource->start); | ||
254 | if (err > 0) { | ||
255 | err = add_mtd_partitions(info->mtd, info->partitions, err); | ||
256 | if(err) | 275 | if(err) |
257 | printk(KERN_ERR "Could not parse partitions\n"); | 276 | printk(KERN_ERR "Could not parse partitions\n"); |
258 | } | 277 | } |
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 426461a5f0d4..4c18b98a3110 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c | |||
@@ -106,12 +106,12 @@ static int physmap_flash_probe(struct platform_device *dev) | |||
106 | 106 | ||
107 | for (i = 0; i < dev->num_resources; i++) { | 107 | for (i = 0; i < dev->num_resources; i++) { |
108 | printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n", | 108 | printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n", |
109 | (unsigned long long)(dev->resource[i].end - dev->resource[i].start + 1), | 109 | (unsigned long long)resource_size(&dev->resource[i]), |
110 | (unsigned long long)dev->resource[i].start); | 110 | (unsigned long long)dev->resource[i].start); |
111 | 111 | ||
112 | if (!devm_request_mem_region(&dev->dev, | 112 | if (!devm_request_mem_region(&dev->dev, |
113 | dev->resource[i].start, | 113 | dev->resource[i].start, |
114 | dev->resource[i].end - dev->resource[i].start + 1, | 114 | resource_size(&dev->resource[i]), |
115 | dev_name(&dev->dev))) { | 115 | dev_name(&dev->dev))) { |
116 | dev_err(&dev->dev, "Could not reserve memory region\n"); | 116 | dev_err(&dev->dev, "Could not reserve memory region\n"); |
117 | err = -ENOMEM; | 117 | err = -ENOMEM; |
@@ -120,7 +120,7 @@ static int physmap_flash_probe(struct platform_device *dev) | |||
120 | 120 | ||
121 | info->map[i].name = dev_name(&dev->dev); | 121 | info->map[i].name = dev_name(&dev->dev); |
122 | info->map[i].phys = dev->resource[i].start; | 122 | info->map[i].phys = dev->resource[i].start; |
123 | info->map[i].size = dev->resource[i].end - dev->resource[i].start + 1; | 123 | info->map[i].size = resource_size(&dev->resource[i]); |
124 | info->map[i].bankwidth = physmap_data->width; | 124 | info->map[i].bankwidth = physmap_data->width; |
125 | info->map[i].set_vpp = physmap_data->set_vpp; | 125 | info->map[i].set_vpp = physmap_data->set_vpp; |
126 | info->map[i].pfow_base = physmap_data->pfow_base; | 126 | info->map[i].pfow_base = physmap_data->pfow_base; |
@@ -136,8 +136,12 @@ static int physmap_flash_probe(struct platform_device *dev) | |||
136 | simple_map_init(&info->map[i]); | 136 | simple_map_init(&info->map[i]); |
137 | 137 | ||
138 | probe_type = rom_probe_types; | 138 | probe_type = rom_probe_types; |
139 | for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++) | 139 | if (physmap_data->probe_type == NULL) { |
140 | info->mtd[i] = do_map_probe(*probe_type, &info->map[i]); | 140 | for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++) |
141 | info->mtd[i] = do_map_probe(*probe_type, &info->map[i]); | ||
142 | } else | ||
143 | info->mtd[i] = do_map_probe(physmap_data->probe_type, &info->map[i]); | ||
144 | |||
141 | if (info->mtd[i] == NULL) { | 145 | if (info->mtd[i] == NULL) { |
142 | dev_err(&dev->dev, "map_probe failed\n"); | 146 | dev_err(&dev->dev, "map_probe failed\n"); |
143 | err = -ENXIO; | 147 | err = -ENXIO; |
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index ba124baa646d..6ac5f9f28ac3 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -353,7 +353,7 @@ static int __devinit of_flash_probe(struct of_device *dev, | |||
353 | &info->parts, 0); | 353 | &info->parts, 0); |
354 | if (err < 0) { | 354 | if (err < 0) { |
355 | of_free_probes(part_probe_types); | 355 | of_free_probes(part_probe_types); |
356 | return err; | 356 | goto err_out; |
357 | } | 357 | } |
358 | of_free_probes(part_probe_types); | 358 | of_free_probes(part_probe_types); |
359 | 359 | ||
@@ -361,14 +361,14 @@ static int __devinit of_flash_probe(struct of_device *dev, | |||
361 | if (err == 0) { | 361 | if (err == 0) { |
362 | err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts); | 362 | err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts); |
363 | if (err < 0) | 363 | if (err < 0) |
364 | return err; | 364 | goto err_out; |
365 | } | 365 | } |
366 | #endif | 366 | #endif |
367 | 367 | ||
368 | if (err == 0) { | 368 | if (err == 0) { |
369 | err = parse_obsolete_partitions(dev, info, dp); | 369 | err = parse_obsolete_partitions(dev, info, dp); |
370 | if (err < 0) | 370 | if (err < 0) |
371 | return err; | 371 | goto err_out; |
372 | } | 372 | } |
373 | 373 | ||
374 | if (err > 0) | 374 | if (err > 0) |
diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c deleted file mode 100644 index d2c9db00db0c..000000000000 --- a/drivers/mtd/maps/redwood.c +++ /dev/null | |||
@@ -1,131 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/mtd/maps/redwood.c | ||
3 | * | ||
4 | * FLASH map for the IBM Redwood 4/5/6 boards. | ||
5 | * | ||
6 | * Author: MontaVista Software, Inc. <source@mvista.com> | ||
7 | * | ||
8 | * 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | |||
19 | #include <linux/mtd/mtd.h> | ||
20 | #include <linux/mtd/map.h> | ||
21 | #include <linux/mtd/partitions.h> | ||
22 | |||
23 | #include <asm/io.h> | ||
24 | |||
25 | #define WINDOW_ADDR 0xffc00000 | ||
26 | #define WINDOW_SIZE 0x00400000 | ||
27 | |||
28 | #define RW_PART0_OF 0 | ||
29 | #define RW_PART0_SZ 0x10000 | ||
30 | #define RW_PART1_OF RW_PART0_SZ | ||
31 | #define RW_PART1_SZ 0x200000 - 0x10000 | ||
32 | #define RW_PART2_OF 0x200000 | ||
33 | #define RW_PART2_SZ 0x10000 | ||
34 | #define RW_PART3_OF 0x210000 | ||
35 | #define RW_PART3_SZ 0x200000 - (0x10000 + 0x20000) | ||
36 | #define RW_PART4_OF 0x3e0000 | ||
37 | #define RW_PART4_SZ 0x20000 | ||
38 | |||
39 | static struct mtd_partition redwood_flash_partitions[] = { | ||
40 | { | ||
41 | .name = "Redwood OpenBIOS Vital Product Data", | ||
42 | .offset = RW_PART0_OF, | ||
43 | .size = RW_PART0_SZ, | ||
44 | .mask_flags = MTD_WRITEABLE /* force read-only */ | ||
45 | }, | ||
46 | { | ||
47 | .name = "Redwood kernel", | ||
48 | .offset = RW_PART1_OF, | ||
49 | .size = RW_PART1_SZ | ||
50 | }, | ||
51 | { | ||
52 | .name = "Redwood OpenBIOS non-volatile storage", | ||
53 | .offset = RW_PART2_OF, | ||
54 | .size = RW_PART2_SZ, | ||
55 | .mask_flags = MTD_WRITEABLE /* force read-only */ | ||
56 | }, | ||
57 | { | ||
58 | .name = "Redwood filesystem", | ||
59 | .offset = RW_PART3_OF, | ||
60 | .size = RW_PART3_SZ | ||
61 | }, | ||
62 | { | ||
63 | .name = "Redwood OpenBIOS", | ||
64 | .offset = RW_PART4_OF, | ||
65 | .size = RW_PART4_SZ, | ||
66 | .mask_flags = MTD_WRITEABLE /* force read-only */ | ||
67 | } | ||
68 | }; | ||
69 | |||
70 | struct map_info redwood_flash_map = { | ||
71 | .name = "IBM Redwood", | ||
72 | .size = WINDOW_SIZE, | ||
73 | .bankwidth = 2, | ||
74 | .phys = WINDOW_ADDR, | ||
75 | }; | ||
76 | |||
77 | |||
78 | #define NUM_REDWOOD_FLASH_PARTITIONS ARRAY_SIZE(redwood_flash_partitions) | ||
79 | |||
80 | static struct mtd_info *redwood_mtd; | ||
81 | |||
82 | static int __init init_redwood_flash(void) | ||
83 | { | ||
84 | int err; | ||
85 | |||
86 | printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n", | ||
87 | WINDOW_SIZE, WINDOW_ADDR); | ||
88 | |||
89 | redwood_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); | ||
90 | |||
91 | if (!redwood_flash_map.virt) { | ||
92 | printk("init_redwood_flash: failed to ioremap\n"); | ||
93 | return -EIO; | ||
94 | } | ||
95 | simple_map_init(&redwood_flash_map); | ||
96 | |||
97 | redwood_mtd = do_map_probe("cfi_probe",&redwood_flash_map); | ||
98 | |||
99 | if (redwood_mtd) { | ||
100 | redwood_mtd->owner = THIS_MODULE; | ||
101 | err = add_mtd_partitions(redwood_mtd, | ||
102 | redwood_flash_partitions, | ||
103 | NUM_REDWOOD_FLASH_PARTITIONS); | ||
104 | if (err) { | ||
105 | printk("init_redwood_flash: add_mtd_partitions failed\n"); | ||
106 | iounmap(redwood_flash_map.virt); | ||
107 | } | ||
108 | return err; | ||
109 | |||
110 | } | ||
111 | |||
112 | iounmap(redwood_flash_map.virt); | ||
113 | return -ENXIO; | ||
114 | } | ||
115 | |||
116 | static void __exit cleanup_redwood_flash(void) | ||
117 | { | ||
118 | if (redwood_mtd) { | ||
119 | del_mtd_partitions(redwood_mtd); | ||
120 | /* moved iounmap after map_destroy - armin */ | ||
121 | map_destroy(redwood_mtd); | ||
122 | iounmap((void *)redwood_flash_map.virt); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | module_init(init_redwood_flash); | ||
127 | module_exit(cleanup_redwood_flash); | ||
128 | |||
129 | MODULE_LICENSE("GPL"); | ||
130 | MODULE_AUTHOR("MontaVista Software <source@mvista.com>"); | ||
131 | MODULE_DESCRIPTION("MTD map driver for the IBM Redwood reference boards"); | ||
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 03e19c1965cc..1d2144d77470 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -1,7 +1,21 @@ | |||
1 | /* | 1 | /* |
2 | * (C) 2003 David Woodhouse <dwmw2@infradead.org> | 2 | * Interface to Linux block layer for MTD 'translation layers'. |
3 | * | 3 | * |
4 | * Interface to Linux 2.5 block layer for MTD 'translation layers'. | 4 | * Copyright © 2003-2010 David Woodhouse <dwmw2@infradead.org> |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
5 | * | 19 | * |
6 | */ | 20 | */ |
7 | 21 | ||
@@ -245,6 +259,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, | |||
245 | switch (cmd) { | 259 | switch (cmd) { |
246 | case BLKFLSBUF: | 260 | case BLKFLSBUF: |
247 | ret = dev->tr->flush ? dev->tr->flush(dev) : 0; | 261 | ret = dev->tr->flush ? dev->tr->flush(dev) : 0; |
262 | break; | ||
248 | default: | 263 | default: |
249 | ret = -ENOTTY; | 264 | ret = -ENOTTY; |
250 | } | 265 | } |
@@ -409,13 +424,14 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) | |||
409 | BUG(); | 424 | BUG(); |
410 | } | 425 | } |
411 | 426 | ||
412 | /* Stop new requests to arrive */ | ||
413 | del_gendisk(old->disk); | ||
414 | |||
415 | if (old->disk_attributes) | 427 | if (old->disk_attributes) |
416 | sysfs_remove_group(&disk_to_dev(old->disk)->kobj, | 428 | sysfs_remove_group(&disk_to_dev(old->disk)->kobj, |
417 | old->disk_attributes); | 429 | old->disk_attributes); |
418 | 430 | ||
431 | /* Stop new requests to arrive */ | ||
432 | del_gendisk(old->disk); | ||
433 | |||
434 | |||
419 | /* Stop the thread */ | 435 | /* Stop the thread */ |
420 | kthread_stop(old->thread); | 436 | kthread_stop(old->thread); |
421 | 437 | ||
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index e6edbec609fd..1e74ad961040 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c | |||
@@ -1,8 +1,23 @@ | |||
1 | /* | 1 | /* |
2 | * Direct MTD block device access | 2 | * Direct MTD block device access |
3 | * | 3 | * |
4 | * (C) 2000-2003 Nicolas Pitre <nico@fluxnic.net> | 4 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> |
5 | * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> | 5 | * Copyright © 2000-2003 Nicolas Pitre <nico@fluxnic.net> |
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | * | ||
6 | */ | 21 | */ |
7 | 22 | ||
8 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c index d0d3f79f9d03..795a8c0a05b8 100644 --- a/drivers/mtd/mtdblock_ro.c +++ b/drivers/mtd/mtdblock_ro.c | |||
@@ -1,7 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | * (C) 2003 David Woodhouse <dwmw2@infradead.org> | ||
3 | * | ||
4 | * Simple read-only (writable only for RAM) mtdblock driver | 2 | * Simple read-only (writable only for RAM) mtdblock driver |
3 | * | ||
4 | * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | * | ||
5 | */ | 20 | */ |
6 | 21 | ||
7 | #include <linux/init.h> | 22 | #include <linux/init.h> |
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 91c8013cf0d9..a825002123c8 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -1,5 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * Character-device access to raw MTD devices. | 2 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> |
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
3 | * | 17 | * |
4 | */ | 18 | */ |
5 | 19 | ||
@@ -18,7 +32,7 @@ | |||
18 | #include <linux/mount.h> | 32 | #include <linux/mount.h> |
19 | 33 | ||
20 | #include <linux/mtd/mtd.h> | 34 | #include <linux/mtd/mtd.h> |
21 | #include <linux/mtd/compatmac.h> | 35 | #include <linux/mtd/map.h> |
22 | 36 | ||
23 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
24 | 38 | ||
@@ -675,6 +689,20 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
675 | break; | 689 | break; |
676 | } | 690 | } |
677 | 691 | ||
692 | case MEMISLOCKED: | ||
693 | { | ||
694 | struct erase_info_user einfo; | ||
695 | |||
696 | if (copy_from_user(&einfo, argp, sizeof(einfo))) | ||
697 | return -EFAULT; | ||
698 | |||
699 | if (!mtd->is_locked) | ||
700 | ret = -EOPNOTSUPP; | ||
701 | else | ||
702 | ret = mtd->is_locked(mtd, einfo.start, einfo.length); | ||
703 | break; | ||
704 | } | ||
705 | |||
678 | /* Legacy interface */ | 706 | /* Legacy interface */ |
679 | case MEMGETOOBSEL: | 707 | case MEMGETOOBSEL: |
680 | { | 708 | { |
@@ -950,9 +978,34 @@ static int mtd_mmap(struct file *file, struct vm_area_struct *vma) | |||
950 | #ifdef CONFIG_MMU | 978 | #ifdef CONFIG_MMU |
951 | struct mtd_file_info *mfi = file->private_data; | 979 | struct mtd_file_info *mfi = file->private_data; |
952 | struct mtd_info *mtd = mfi->mtd; | 980 | struct mtd_info *mtd = mfi->mtd; |
981 | struct map_info *map = mtd->priv; | ||
982 | unsigned long start; | ||
983 | unsigned long off; | ||
984 | u32 len; | ||
985 | |||
986 | if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) { | ||
987 | off = vma->vm_pgoff << PAGE_SHIFT; | ||
988 | start = map->phys; | ||
989 | len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size); | ||
990 | start &= PAGE_MASK; | ||
991 | if ((vma->vm_end - vma->vm_start + off) > len) | ||
992 | return -EINVAL; | ||
993 | |||
994 | off += start; | ||
995 | vma->vm_pgoff = off >> PAGE_SHIFT; | ||
996 | vma->vm_flags |= VM_IO | VM_RESERVED; | ||
997 | |||
998 | #ifdef pgprot_noncached | ||
999 | if (file->f_flags & O_DSYNC || off >= __pa(high_memory)) | ||
1000 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
1001 | #endif | ||
1002 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, | ||
1003 | vma->vm_end - vma->vm_start, | ||
1004 | vma->vm_page_prot)) | ||
1005 | return -EAGAIN; | ||
953 | 1006 | ||
954 | if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) | ||
955 | return 0; | 1007 | return 0; |
1008 | } | ||
956 | return -ENOSYS; | 1009 | return -ENOSYS; |
957 | #else | 1010 | #else |
958 | return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS; | 1011 | return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS; |
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 7e075621bbf4..bf8de0943103 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c | |||
@@ -1,11 +1,25 @@ | |||
1 | /* | 1 | /* |
2 | * MTD device concatenation layer | 2 | * MTD device concatenation layer |
3 | * | 3 | * |
4 | * (C) 2002 Robert Kaiser <rkaiser@sysgo.de> | 4 | * Copyright © 2002 Robert Kaiser <rkaiser@sysgo.de> |
5 | * Copyright © 2002-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 6 | * |
6 | * NAND support by Christian Gan <cgan@iders.ca> | 7 | * NAND support by Christian Gan <cgan@iders.ca> |
7 | * | 8 | * |
8 | * This code is GPL | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
22 | * | ||
9 | */ | 23 | */ |
10 | 24 | ||
11 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
@@ -540,10 +554,12 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
540 | else | 554 | else |
541 | size = len; | 555 | size = len; |
542 | 556 | ||
543 | err = subdev->lock(subdev, ofs, size); | 557 | if (subdev->lock) { |
544 | 558 | err = subdev->lock(subdev, ofs, size); | |
545 | if (err) | 559 | if (err) |
546 | break; | 560 | break; |
561 | } else | ||
562 | err = -EOPNOTSUPP; | ||
547 | 563 | ||
548 | len -= size; | 564 | len -= size; |
549 | if (len == 0) | 565 | if (len == 0) |
@@ -578,10 +594,12 @@ static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
578 | else | 594 | else |
579 | size = len; | 595 | size = len; |
580 | 596 | ||
581 | err = subdev->unlock(subdev, ofs, size); | 597 | if (subdev->unlock) { |
582 | 598 | err = subdev->unlock(subdev, ofs, size); | |
583 | if (err) | 599 | if (err) |
584 | break; | 600 | break; |
601 | } else | ||
602 | err = -EOPNOTSUPP; | ||
585 | 603 | ||
586 | len -= size; | 604 | len -= size; |
587 | if (len == 0) | 605 | if (len == 0) |
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index a1b8b70d2d0a..527cebf58da4 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -2,9 +2,23 @@ | |||
2 | * Core registration and callback routines for MTD | 2 | * Core registration and callback routines for MTD |
3 | * drivers and users. | 3 | * drivers and users. |
4 | * | 4 | * |
5 | * bdi bits are: | 5 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> |
6 | * Copyright © 2006 Red Hat, Inc. All Rights Reserved. | 6 | * Copyright © 2006 Red Hat UK Limited |
7 | * Written by David Howells (dhowells@redhat.com) | 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 as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | * | ||
8 | */ | 22 | */ |
9 | 23 | ||
10 | #include <linux/module.h> | 24 | #include <linux/module.h> |
@@ -17,7 +31,6 @@ | |||
17 | #include <linux/err.h> | 31 | #include <linux/err.h> |
18 | #include <linux/ioctl.h> | 32 | #include <linux/ioctl.h> |
19 | #include <linux/init.h> | 33 | #include <linux/init.h> |
20 | #include <linux/mtd/compatmac.h> | ||
21 | #include <linux/proc_fs.h> | 34 | #include <linux/proc_fs.h> |
22 | #include <linux/idr.h> | 35 | #include <linux/idr.h> |
23 | #include <linux/backing-dev.h> | 36 | #include <linux/backing-dev.h> |
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index 328313c3dccb..1ee72f3f0512 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * MTD Oops/Panic logger | 2 | * MTD Oops/Panic logger |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Nokia Corporation. All rights reserved. | 4 | * Copyright © 2007 Nokia Corporation. All rights reserved. |
5 | * | 5 | * |
6 | * Author: Richard Purdie <rpurdie@openedhand.com> | 6 | * Author: Richard Purdie <rpurdie@openedhand.com> |
7 | * | 7 | * |
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index b8043a9ba32d..dc6558568876 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
@@ -1,12 +1,24 @@ | |||
1 | /* | 1 | /* |
2 | * Simple MTD partitioning layer | 2 | * Simple MTD partitioning layer |
3 | * | 3 | * |
4 | * (C) 2000 Nicolas Pitre <nico@fluxnic.net> | 4 | * Copyright © 2000 Nicolas Pitre <nico@fluxnic.net> |
5 | * Copyright © 2002 Thomas Gleixner <gleixner@linutronix.de> | ||
6 | * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | 7 | * |
6 | * This code is GPL | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
7 | * | 21 | * |
8 | * 02-21-2002 Thomas Gleixner <gleixner@autronix.de> | ||
9 | * added support for read_oob, write_oob | ||
10 | */ | 22 | */ |
11 | 23 | ||
12 | #include <linux/module.h> | 24 | #include <linux/module.h> |
@@ -17,7 +29,6 @@ | |||
17 | #include <linux/kmod.h> | 29 | #include <linux/kmod.h> |
18 | #include <linux/mtd/mtd.h> | 30 | #include <linux/mtd/mtd.h> |
19 | #include <linux/mtd/partitions.h> | 31 | #include <linux/mtd/partitions.h> |
20 | #include <linux/mtd/compatmac.h> | ||
21 | 32 | ||
22 | /* Our partition linked list */ | 33 | /* Our partition linked list */ |
23 | static LIST_HEAD(mtd_partitions); | 34 | static LIST_HEAD(mtd_partitions); |
@@ -264,6 +275,14 @@ static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
264 | return part->master->unlock(part->master, ofs + part->offset, len); | 275 | return part->master->unlock(part->master, ofs + part->offset, len); |
265 | } | 276 | } |
266 | 277 | ||
278 | static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) | ||
279 | { | ||
280 | struct mtd_part *part = PART(mtd); | ||
281 | if ((len + ofs) > mtd->size) | ||
282 | return -EINVAL; | ||
283 | return part->master->is_locked(part->master, ofs + part->offset, len); | ||
284 | } | ||
285 | |||
267 | static void part_sync(struct mtd_info *mtd) | 286 | static void part_sync(struct mtd_info *mtd) |
268 | { | 287 | { |
269 | struct mtd_part *part = PART(mtd); | 288 | struct mtd_part *part = PART(mtd); |
@@ -402,6 +421,8 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, | |||
402 | slave->mtd.lock = part_lock; | 421 | slave->mtd.lock = part_lock; |
403 | if (master->unlock) | 422 | if (master->unlock) |
404 | slave->mtd.unlock = part_unlock; | 423 | slave->mtd.unlock = part_unlock; |
424 | if (master->is_locked) | ||
425 | slave->mtd.is_locked = part_is_locked; | ||
405 | if (master->block_isbad) | 426 | if (master->block_isbad) |
406 | slave->mtd.block_isbad = part_block_isbad; | 427 | slave->mtd.block_isbad = part_block_isbad; |
407 | if (master->block_markbad) | 428 | if (master->block_markbad) |
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index bd9a443ccf69..38e2ab07e7a3 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c | |||
@@ -1,6 +1,8 @@ | |||
1 | /* MTD-based superblock management | 1 | /* MTD-based superblock management |
2 | * | 2 | * |
3 | * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved. |
4 | * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org> | ||
5 | * | ||
4 | * Written by: David Howells <dhowells@redhat.com> | 6 | * Written by: David Howells <dhowells@redhat.com> |
5 | * David Woodhouse <dwmw2@infradead.org> | 7 | * David Woodhouse <dwmw2@infradead.org> |
6 | * | 8 | * |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 362d177efe1b..8b4b67c8a391 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -37,7 +37,6 @@ config MTD_SM_COMMON | |||
37 | 37 | ||
38 | config MTD_NAND_MUSEUM_IDS | 38 | config MTD_NAND_MUSEUM_IDS |
39 | bool "Enable chip ids for obsolete ancient NAND devices" | 39 | bool "Enable chip ids for obsolete ancient NAND devices" |
40 | depends on MTD_NAND | ||
41 | default n | 40 | default n |
42 | help | 41 | help |
43 | Enable this option only when your board has first generation | 42 | Enable this option only when your board has first generation |
@@ -61,6 +60,7 @@ config MTD_NAND_DENALI | |||
61 | config MTD_NAND_DENALI_SCRATCH_REG_ADDR | 60 | config MTD_NAND_DENALI_SCRATCH_REG_ADDR |
62 | hex "Denali NAND size scratch register address" | 61 | hex "Denali NAND size scratch register address" |
63 | default "0xFF108018" | 62 | default "0xFF108018" |
63 | depends on MTD_NAND_DENALI | ||
64 | help | 64 | help |
65 | Some platforms place the NAND chip size in a scratch register | 65 | Some platforms place the NAND chip size in a scratch register |
66 | because (some versions of) the driver aren't able to automatically | 66 | because (some versions of) the driver aren't able to automatically |
@@ -101,13 +101,13 @@ config MTD_NAND_AMS_DELTA | |||
101 | 101 | ||
102 | config MTD_NAND_OMAP2 | 102 | config MTD_NAND_OMAP2 |
103 | tristate "NAND Flash device on OMAP2 and OMAP3" | 103 | tristate "NAND Flash device on OMAP2 and OMAP3" |
104 | depends on ARM && MTD_NAND && (ARCH_OMAP2 || ARCH_OMAP3) | 104 | depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3) |
105 | help | 105 | help |
106 | Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms. | 106 | Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms. |
107 | 107 | ||
108 | config MTD_NAND_OMAP_PREFETCH | 108 | config MTD_NAND_OMAP_PREFETCH |
109 | bool "GPMC prefetch support for NAND Flash device" | 109 | bool "GPMC prefetch support for NAND Flash device" |
110 | depends on MTD_NAND && MTD_NAND_OMAP2 | 110 | depends on MTD_NAND_OMAP2 |
111 | default y | 111 | default y |
112 | help | 112 | help |
113 | The NAND device can be accessed for Read/Write using GPMC PREFETCH engine | 113 | The NAND device can be accessed for Read/Write using GPMC PREFETCH engine |
@@ -146,7 +146,7 @@ config MTD_NAND_AU1550 | |||
146 | 146 | ||
147 | config MTD_NAND_BF5XX | 147 | config MTD_NAND_BF5XX |
148 | tristate "Blackfin on-chip NAND Flash Controller driver" | 148 | tristate "Blackfin on-chip NAND Flash Controller driver" |
149 | depends on (BF54x || BF52x) && MTD_NAND | 149 | depends on BF54x || BF52x |
150 | help | 150 | help |
151 | This enables the Blackfin on-chip NAND flash controller | 151 | This enables the Blackfin on-chip NAND flash controller |
152 | 152 | ||
@@ -236,7 +236,7 @@ config MTD_NAND_S3C2410_CLKSTOP | |||
236 | 236 | ||
237 | config MTD_NAND_BCM_UMI | 237 | config MTD_NAND_BCM_UMI |
238 | tristate "NAND Flash support for BCM Reference Boards" | 238 | tristate "NAND Flash support for BCM Reference Boards" |
239 | depends on ARCH_BCMRING && MTD_NAND | 239 | depends on ARCH_BCMRING |
240 | help | 240 | help |
241 | This enables the NAND flash controller on the BCM UMI block. | 241 | This enables the NAND flash controller on the BCM UMI block. |
242 | 242 | ||
@@ -395,7 +395,7 @@ endchoice | |||
395 | 395 | ||
396 | config MTD_NAND_PXA3xx | 396 | config MTD_NAND_PXA3xx |
397 | tristate "Support for NAND flash devices on PXA3xx" | 397 | tristate "Support for NAND flash devices on PXA3xx" |
398 | depends on MTD_NAND && (PXA3xx || ARCH_MMP) | 398 | depends on PXA3xx || ARCH_MMP |
399 | help | 399 | help |
400 | This enables the driver for the NAND flash device found on | 400 | This enables the driver for the NAND flash device found on |
401 | PXA3xx processors | 401 | PXA3xx processors |
@@ -409,18 +409,18 @@ config MTD_NAND_PXA3xx_BUILTIN | |||
409 | 409 | ||
410 | config MTD_NAND_CM_X270 | 410 | config MTD_NAND_CM_X270 |
411 | tristate "Support for NAND Flash on CM-X270 modules" | 411 | tristate "Support for NAND Flash on CM-X270 modules" |
412 | depends on MTD_NAND && MACH_ARMCORE | 412 | depends on MACH_ARMCORE |
413 | 413 | ||
414 | config MTD_NAND_PASEMI | 414 | config MTD_NAND_PASEMI |
415 | tristate "NAND support for PA Semi PWRficient" | 415 | tristate "NAND support for PA Semi PWRficient" |
416 | depends on MTD_NAND && PPC_PASEMI | 416 | depends on PPC_PASEMI |
417 | help | 417 | help |
418 | Enables support for NAND Flash interface on PA Semi PWRficient | 418 | Enables support for NAND Flash interface on PA Semi PWRficient |
419 | based boards | 419 | based boards |
420 | 420 | ||
421 | config MTD_NAND_TMIO | 421 | config MTD_NAND_TMIO |
422 | tristate "NAND Flash device on Toshiba Mobile IO Controller" | 422 | tristate "NAND Flash device on Toshiba Mobile IO Controller" |
423 | depends on MTD_NAND && MFD_TMIO | 423 | depends on MFD_TMIO |
424 | help | 424 | help |
425 | Support for NAND flash connected to a Toshiba Mobile IO | 425 | Support for NAND flash connected to a Toshiba Mobile IO |
426 | Controller in some PDAs, including the Sharp SL6000x. | 426 | Controller in some PDAs, including the Sharp SL6000x. |
@@ -434,7 +434,6 @@ config MTD_NAND_NANDSIM | |||
434 | 434 | ||
435 | config MTD_NAND_PLATFORM | 435 | config MTD_NAND_PLATFORM |
436 | tristate "Support for generic platform NAND driver" | 436 | tristate "Support for generic platform NAND driver" |
437 | depends on MTD_NAND | ||
438 | help | 437 | help |
439 | This implements a generic NAND driver for on-SOC platform | 438 | This implements a generic NAND driver for on-SOC platform |
440 | devices. You will need to provide platform-specific functions | 439 | devices. You will need to provide platform-specific functions |
@@ -442,14 +441,14 @@ config MTD_NAND_PLATFORM | |||
442 | 441 | ||
443 | config MTD_ALAUDA | 442 | config MTD_ALAUDA |
444 | tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1" | 443 | tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1" |
445 | depends on MTD_NAND && USB | 444 | depends on USB |
446 | help | 445 | help |
447 | These two (and possibly other) Alauda-based cardreaders for | 446 | These two (and possibly other) Alauda-based cardreaders for |
448 | SmartMedia and xD allow raw flash access. | 447 | SmartMedia and xD allow raw flash access. |
449 | 448 | ||
450 | config MTD_NAND_ORION | 449 | config MTD_NAND_ORION |
451 | tristate "NAND Flash support for Marvell Orion SoC" | 450 | tristate "NAND Flash support for Marvell Orion SoC" |
452 | depends on PLAT_ORION && MTD_NAND | 451 | depends on PLAT_ORION |
453 | help | 452 | help |
454 | This enables the NAND flash controller on Orion machines. | 453 | This enables the NAND flash controller on Orion machines. |
455 | 454 | ||
@@ -458,7 +457,7 @@ config MTD_NAND_ORION | |||
458 | 457 | ||
459 | config MTD_NAND_FSL_ELBC | 458 | config MTD_NAND_FSL_ELBC |
460 | tristate "NAND support for Freescale eLBC controllers" | 459 | tristate "NAND support for Freescale eLBC controllers" |
461 | depends on MTD_NAND && PPC_OF | 460 | depends on PPC_OF |
462 | help | 461 | help |
463 | Various Freescale chips, including the 8313, include a NAND Flash | 462 | Various Freescale chips, including the 8313, include a NAND Flash |
464 | Controller Module with built-in hardware ECC capabilities. | 463 | Controller Module with built-in hardware ECC capabilities. |
@@ -467,7 +466,7 @@ config MTD_NAND_FSL_ELBC | |||
467 | 466 | ||
468 | config MTD_NAND_FSL_UPM | 467 | config MTD_NAND_FSL_UPM |
469 | tristate "Support for NAND on Freescale UPM" | 468 | tristate "Support for NAND on Freescale UPM" |
470 | depends on MTD_NAND && (PPC_83xx || PPC_85xx) | 469 | depends on PPC_83xx || PPC_85xx |
471 | select FSL_LBC | 470 | select FSL_LBC |
472 | help | 471 | help |
473 | Enables support for NAND Flash chips wired onto Freescale PowerPC | 472 | Enables support for NAND Flash chips wired onto Freescale PowerPC |
@@ -482,7 +481,7 @@ config MTD_NAND_MPC5121_NFC | |||
482 | 481 | ||
483 | config MTD_NAND_MXC | 482 | config MTD_NAND_MXC |
484 | tristate "MXC NAND support" | 483 | tristate "MXC NAND support" |
485 | depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 | 484 | depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 || ARCH_MX51 |
486 | help | 485 | help |
487 | This enables the driver for the NAND flash controller on the | 486 | This enables the driver for the NAND flash controller on the |
488 | MXC processors. | 487 | MXC processors. |
@@ -495,7 +494,7 @@ config MTD_NAND_NOMADIK | |||
495 | 494 | ||
496 | config MTD_NAND_SH_FLCTL | 495 | config MTD_NAND_SH_FLCTL |
497 | tristate "Support for NAND on Renesas SuperH FLCTL" | 496 | tristate "Support for NAND on Renesas SuperH FLCTL" |
498 | depends on MTD_NAND && (SUPERH || ARCH_SHMOBILE) | 497 | depends on SUPERH || ARCH_SHMOBILE |
499 | help | 498 | help |
500 | Several Renesas SuperH CPU has FLCTL. This option enables support | 499 | Several Renesas SuperH CPU has FLCTL. This option enables support |
501 | for NAND Flash using FLCTL. | 500 | for NAND Flash using FLCTL. |
@@ -515,7 +514,7 @@ config MTD_NAND_TXX9NDFMC | |||
515 | 514 | ||
516 | config MTD_NAND_SOCRATES | 515 | config MTD_NAND_SOCRATES |
517 | tristate "Support for NAND on Socrates board" | 516 | tristate "Support for NAND on Socrates board" |
518 | depends on MTD_NAND && SOCRATES | 517 | depends on SOCRATES |
519 | help | 518 | help |
520 | Enables support for NAND Flash chips wired onto Socrates board. | 519 | Enables support for NAND Flash chips wired onto Socrates board. |
521 | 520 | ||
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 04d30887ca7f..ccce0f03b5dc 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -364,7 +364,7 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) | |||
364 | } | 364 | } |
365 | } | 365 | } |
366 | 366 | ||
367 | #ifdef CONFIG_MTD_PARTITIONS | 367 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
368 | static const char *part_probes[] = { "cmdlinepart", NULL }; | 368 | static const char *part_probes[] = { "cmdlinepart", NULL }; |
369 | #endif | 369 | #endif |
370 | 370 | ||
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 2974995e194d..a382e3dd0a5d 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -20,9 +20,6 @@ | |||
20 | * - DMA supported in ECC_HW | 20 | * - DMA supported in ECC_HW |
21 | * - YAFFS tested as rootfs in both ECC_HW and ECC_SW | 21 | * - YAFFS tested as rootfs in both ECC_HW and ECC_SW |
22 | * | 22 | * |
23 | * TODO: | ||
24 | * Enable JFFS2 over NAND as rootfs | ||
25 | * | ||
26 | * This program is free software; you can redistribute it and/or modify | 23 | * This program is free software; you can redistribute it and/or modify |
27 | * it under the terms of the GNU General Public License as published by | 24 | * it under the terms of the GNU General Public License as published by |
28 | * the Free Software Foundation; either version 2 of the License, or | 25 | * the Free Software Foundation; either version 2 of the License, or |
@@ -206,7 +203,7 @@ static void bf5xx_nand_hwcontrol(struct mtd_info *mtd, int cmd, | |||
206 | 203 | ||
207 | if (ctrl & NAND_CLE) | 204 | if (ctrl & NAND_CLE) |
208 | bfin_write_NFC_CMD(cmd); | 205 | bfin_write_NFC_CMD(cmd); |
209 | else | 206 | else if (ctrl & NAND_ALE) |
210 | bfin_write_NFC_ADDR(cmd); | 207 | bfin_write_NFC_ADDR(cmd); |
211 | SSYNC(); | 208 | SSYNC(); |
212 | } | 209 | } |
@@ -218,9 +215,9 @@ static void bf5xx_nand_hwcontrol(struct mtd_info *mtd, int cmd, | |||
218 | */ | 215 | */ |
219 | static int bf5xx_nand_devready(struct mtd_info *mtd) | 216 | static int bf5xx_nand_devready(struct mtd_info *mtd) |
220 | { | 217 | { |
221 | unsigned short val = bfin_read_NFC_IRQSTAT(); | 218 | unsigned short val = bfin_read_NFC_STAT(); |
222 | 219 | ||
223 | if ((val & NBUSYIRQ) == NBUSYIRQ) | 220 | if ((val & NBUSY) == NBUSY) |
224 | return 1; | 221 | return 1; |
225 | else | 222 | else |
226 | return 0; | 223 | return 0; |
@@ -317,18 +314,16 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat, | |||
317 | static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat, | 314 | static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat, |
318 | u_char *read_ecc, u_char *calc_ecc) | 315 | u_char *read_ecc, u_char *calc_ecc) |
319 | { | 316 | { |
320 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); | 317 | struct nand_chip *chip = mtd->priv; |
321 | struct bf5xx_nand_platform *plat = info->platform; | ||
322 | unsigned short page_size = (plat->page_size ? 512 : 256); | ||
323 | int ret; | 318 | int ret; |
324 | 319 | ||
325 | ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); | 320 | ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); |
326 | 321 | ||
327 | /* If page size is 512, correct second 256 bytes */ | 322 | /* If ecc size is 512, correct second 256 bytes */ |
328 | if (page_size == 512) { | 323 | if (chip->ecc.size == 512) { |
329 | dat += 256; | 324 | dat += 256; |
330 | read_ecc += 8; | 325 | read_ecc += 3; |
331 | calc_ecc += 8; | 326 | calc_ecc += 3; |
332 | ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); | 327 | ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); |
333 | } | 328 | } |
334 | 329 | ||
@@ -344,13 +339,12 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd, | |||
344 | const u_char *dat, u_char *ecc_code) | 339 | const u_char *dat, u_char *ecc_code) |
345 | { | 340 | { |
346 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); | 341 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); |
347 | struct bf5xx_nand_platform *plat = info->platform; | 342 | struct nand_chip *chip = mtd->priv; |
348 | u16 page_size = (plat->page_size ? 512 : 256); | ||
349 | u16 ecc0, ecc1; | 343 | u16 ecc0, ecc1; |
350 | u32 code[2]; | 344 | u32 code[2]; |
351 | u8 *p; | 345 | u8 *p; |
352 | 346 | ||
353 | /* first 4 bytes ECC code for 256 page size */ | 347 | /* first 3 bytes ECC code for 256 page size */ |
354 | ecc0 = bfin_read_NFC_ECC0(); | 348 | ecc0 = bfin_read_NFC_ECC0(); |
355 | ecc1 = bfin_read_NFC_ECC1(); | 349 | ecc1 = bfin_read_NFC_ECC1(); |
356 | 350 | ||
@@ -358,12 +352,11 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd, | |||
358 | 352 | ||
359 | dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]); | 353 | dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]); |
360 | 354 | ||
361 | /* first 3 bytes in ecc_code for 256 page size */ | ||
362 | p = (u8 *) code; | 355 | p = (u8 *) code; |
363 | memcpy(ecc_code, p, 3); | 356 | memcpy(ecc_code, p, 3); |
364 | 357 | ||
365 | /* second 4 bytes ECC code for 512 page size */ | 358 | /* second 3 bytes ECC code for 512 ecc size */ |
366 | if (page_size == 512) { | 359 | if (chip->ecc.size == 512) { |
367 | ecc0 = bfin_read_NFC_ECC2(); | 360 | ecc0 = bfin_read_NFC_ECC2(); |
368 | ecc1 = bfin_read_NFC_ECC3(); | 361 | ecc1 = bfin_read_NFC_ECC3(); |
369 | code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11); | 362 | code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11); |
@@ -483,8 +476,7 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd, | |||
483 | uint8_t *buf, int is_read) | 476 | uint8_t *buf, int is_read) |
484 | { | 477 | { |
485 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); | 478 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); |
486 | struct bf5xx_nand_platform *plat = info->platform; | 479 | struct nand_chip *chip = mtd->priv; |
487 | unsigned short page_size = (plat->page_size ? 512 : 256); | ||
488 | unsigned short val; | 480 | unsigned short val; |
489 | 481 | ||
490 | dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n", | 482 | dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n", |
@@ -498,10 +490,10 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd, | |||
498 | */ | 490 | */ |
499 | if (is_read) | 491 | if (is_read) |
500 | invalidate_dcache_range((unsigned int)buf, | 492 | invalidate_dcache_range((unsigned int)buf, |
501 | (unsigned int)(buf + page_size)); | 493 | (unsigned int)(buf + chip->ecc.size)); |
502 | else | 494 | else |
503 | flush_dcache_range((unsigned int)buf, | 495 | flush_dcache_range((unsigned int)buf, |
504 | (unsigned int)(buf + page_size)); | 496 | (unsigned int)(buf + chip->ecc.size)); |
505 | 497 | ||
506 | /* | 498 | /* |
507 | * This register must be written before each page is | 499 | * This register must be written before each page is |
@@ -510,6 +502,8 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd, | |||
510 | */ | 502 | */ |
511 | bfin_write_NFC_RST(ECC_RST); | 503 | bfin_write_NFC_RST(ECC_RST); |
512 | SSYNC(); | 504 | SSYNC(); |
505 | while (bfin_read_NFC_RST() & ECC_RST) | ||
506 | cpu_relax(); | ||
513 | 507 | ||
514 | disable_dma(CH_NFC); | 508 | disable_dma(CH_NFC); |
515 | clear_dma_irqstat(CH_NFC); | 509 | clear_dma_irqstat(CH_NFC); |
@@ -520,13 +514,13 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd, | |||
520 | 514 | ||
521 | /* The DMAs have different size on BF52x and BF54x */ | 515 | /* The DMAs have different size on BF52x and BF54x */ |
522 | #ifdef CONFIG_BF52x | 516 | #ifdef CONFIG_BF52x |
523 | set_dma_x_count(CH_NFC, (page_size >> 1)); | 517 | set_dma_x_count(CH_NFC, (chip->ecc.size >> 1)); |
524 | set_dma_x_modify(CH_NFC, 2); | 518 | set_dma_x_modify(CH_NFC, 2); |
525 | val = DI_EN | WDSIZE_16; | 519 | val = DI_EN | WDSIZE_16; |
526 | #endif | 520 | #endif |
527 | 521 | ||
528 | #ifdef CONFIG_BF54x | 522 | #ifdef CONFIG_BF54x |
529 | set_dma_x_count(CH_NFC, (page_size >> 2)); | 523 | set_dma_x_count(CH_NFC, (chip->ecc.size >> 2)); |
530 | set_dma_x_modify(CH_NFC, 4); | 524 | set_dma_x_modify(CH_NFC, 4); |
531 | val = DI_EN | WDSIZE_32; | 525 | val = DI_EN | WDSIZE_32; |
532 | #endif | 526 | #endif |
@@ -548,12 +542,11 @@ static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd, | |||
548 | uint8_t *buf, int len) | 542 | uint8_t *buf, int len) |
549 | { | 543 | { |
550 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); | 544 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); |
551 | struct bf5xx_nand_platform *plat = info->platform; | 545 | struct nand_chip *chip = mtd->priv; |
552 | unsigned short page_size = (plat->page_size ? 512 : 256); | ||
553 | 546 | ||
554 | dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len); | 547 | dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len); |
555 | 548 | ||
556 | if (len == page_size) | 549 | if (len == chip->ecc.size) |
557 | bf5xx_nand_dma_rw(mtd, buf, 1); | 550 | bf5xx_nand_dma_rw(mtd, buf, 1); |
558 | else | 551 | else |
559 | bf5xx_nand_read_buf(mtd, buf, len); | 552 | bf5xx_nand_read_buf(mtd, buf, len); |
@@ -563,17 +556,32 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd, | |||
563 | const uint8_t *buf, int len) | 556 | const uint8_t *buf, int len) |
564 | { | 557 | { |
565 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); | 558 | struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); |
566 | struct bf5xx_nand_platform *plat = info->platform; | 559 | struct nand_chip *chip = mtd->priv; |
567 | unsigned short page_size = (plat->page_size ? 512 : 256); | ||
568 | 560 | ||
569 | dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len); | 561 | dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len); |
570 | 562 | ||
571 | if (len == page_size) | 563 | if (len == chip->ecc.size) |
572 | bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0); | 564 | bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0); |
573 | else | 565 | else |
574 | bf5xx_nand_write_buf(mtd, buf, len); | 566 | bf5xx_nand_write_buf(mtd, buf, len); |
575 | } | 567 | } |
576 | 568 | ||
569 | static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | ||
570 | uint8_t *buf, int page) | ||
571 | { | ||
572 | bf5xx_nand_read_buf(mtd, buf, mtd->writesize); | ||
573 | bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
574 | |||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | ||
579 | const uint8_t *buf) | ||
580 | { | ||
581 | bf5xx_nand_write_buf(mtd, buf, mtd->writesize); | ||
582 | bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
583 | } | ||
584 | |||
577 | /* | 585 | /* |
578 | * System initialization functions | 586 | * System initialization functions |
579 | */ | 587 | */ |
@@ -627,15 +635,14 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info) | |||
627 | 635 | ||
628 | /* setup NFC_CTL register */ | 636 | /* setup NFC_CTL register */ |
629 | dev_info(info->device, | 637 | dev_info(info->device, |
630 | "page_size=%d, data_width=%d, wr_dly=%d, rd_dly=%d\n", | 638 | "data_width=%d, wr_dly=%d, rd_dly=%d\n", |
631 | (plat->page_size ? 512 : 256), | ||
632 | (plat->data_width ? 16 : 8), | 639 | (plat->data_width ? 16 : 8), |
633 | plat->wr_dly, plat->rd_dly); | 640 | plat->wr_dly, plat->rd_dly); |
634 | 641 | ||
635 | val = (plat->page_size << NFC_PG_SIZE_OFFSET) | | 642 | val = (1 << NFC_PG_SIZE_OFFSET) | |
636 | (plat->data_width << NFC_NWIDTH_OFFSET) | | 643 | (plat->data_width << NFC_NWIDTH_OFFSET) | |
637 | (plat->rd_dly << NFC_RDDLY_OFFSET) | | 644 | (plat->rd_dly << NFC_RDDLY_OFFSET) | |
638 | (plat->rd_dly << NFC_WRDLY_OFFSET); | 645 | (plat->wr_dly << NFC_WRDLY_OFFSET); |
639 | dev_dbg(info->device, "NFC_CTL is 0x%04x\n", val); | 646 | dev_dbg(info->device, "NFC_CTL is 0x%04x\n", val); |
640 | 647 | ||
641 | bfin_write_NFC_CTL(val); | 648 | bfin_write_NFC_CTL(val); |
@@ -698,6 +705,33 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev) | |||
698 | return 0; | 705 | return 0; |
699 | } | 706 | } |
700 | 707 | ||
708 | static int bf5xx_nand_scan(struct mtd_info *mtd) | ||
709 | { | ||
710 | struct nand_chip *chip = mtd->priv; | ||
711 | int ret; | ||
712 | |||
713 | ret = nand_scan_ident(mtd, 1); | ||
714 | if (ret) | ||
715 | return ret; | ||
716 | |||
717 | if (hardware_ecc) { | ||
718 | /* | ||
719 | * for nand with page size > 512B, think it as several sections with 512B | ||
720 | */ | ||
721 | if (likely(mtd->writesize >= 512)) { | ||
722 | chip->ecc.size = 512; | ||
723 | chip->ecc.bytes = 6; | ||
724 | } else { | ||
725 | chip->ecc.size = 256; | ||
726 | chip->ecc.bytes = 3; | ||
727 | bfin_write_NFC_CTL(bfin_read_NFC_CTL() & ~(1 << NFC_PG_SIZE_OFFSET)); | ||
728 | SSYNC(); | ||
729 | } | ||
730 | } | ||
731 | |||
732 | return nand_scan_tail(mtd); | ||
733 | } | ||
734 | |||
701 | /* | 735 | /* |
702 | * bf5xx_nand_probe | 736 | * bf5xx_nand_probe |
703 | * | 737 | * |
@@ -783,27 +817,20 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) | |||
783 | chip->badblock_pattern = &bootrom_bbt; | 817 | chip->badblock_pattern = &bootrom_bbt; |
784 | chip->ecc.layout = &bootrom_ecclayout; | 818 | chip->ecc.layout = &bootrom_ecclayout; |
785 | #endif | 819 | #endif |
786 | |||
787 | if (plat->page_size == NFC_PG_SIZE_256) { | ||
788 | chip->ecc.bytes = 3; | ||
789 | chip->ecc.size = 256; | ||
790 | } else if (plat->page_size == NFC_PG_SIZE_512) { | ||
791 | chip->ecc.bytes = 6; | ||
792 | chip->ecc.size = 512; | ||
793 | } | ||
794 | |||
795 | chip->read_buf = bf5xx_nand_dma_read_buf; | 820 | chip->read_buf = bf5xx_nand_dma_read_buf; |
796 | chip->write_buf = bf5xx_nand_dma_write_buf; | 821 | chip->write_buf = bf5xx_nand_dma_write_buf; |
797 | chip->ecc.calculate = bf5xx_nand_calculate_ecc; | 822 | chip->ecc.calculate = bf5xx_nand_calculate_ecc; |
798 | chip->ecc.correct = bf5xx_nand_correct_data; | 823 | chip->ecc.correct = bf5xx_nand_correct_data; |
799 | chip->ecc.mode = NAND_ECC_HW; | 824 | chip->ecc.mode = NAND_ECC_HW; |
800 | chip->ecc.hwctl = bf5xx_nand_enable_hwecc; | 825 | chip->ecc.hwctl = bf5xx_nand_enable_hwecc; |
826 | chip->ecc.read_page_raw = bf5xx_nand_read_page_raw; | ||
827 | chip->ecc.write_page_raw = bf5xx_nand_write_page_raw; | ||
801 | } else { | 828 | } else { |
802 | chip->ecc.mode = NAND_ECC_SOFT; | 829 | chip->ecc.mode = NAND_ECC_SOFT; |
803 | } | 830 | } |
804 | 831 | ||
805 | /* scan hardware nand chip and setup mtd info data struct */ | 832 | /* scan hardware nand chip and setup mtd info data struct */ |
806 | if (nand_scan(mtd, 1)) { | 833 | if (bf5xx_nand_scan(mtd)) { |
807 | err = -ENXIO; | 834 | err = -ENXIO; |
808 | goto out_err_nand_scan; | 835 | goto out_err_nand_scan; |
809 | } | 836 | } |
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 9c9d893affeb..2ac7367afe77 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -311,7 +311,9 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd, | |||
311 | unsigned short ecc10[8]; | 311 | unsigned short ecc10[8]; |
312 | unsigned short *ecc16; | 312 | unsigned short *ecc16; |
313 | u32 syndrome[4]; | 313 | u32 syndrome[4]; |
314 | u32 ecc_state; | ||
314 | unsigned num_errors, corrected; | 315 | unsigned num_errors, corrected; |
316 | unsigned long timeo = jiffies + msecs_to_jiffies(100); | ||
315 | 317 | ||
316 | /* All bytes 0xff? It's an erased page; ignore its ECC. */ | 318 | /* All bytes 0xff? It's an erased page; ignore its ECC. */ |
317 | for (i = 0; i < 10; i++) { | 319 | for (i = 0; i < 10; i++) { |
@@ -361,6 +363,21 @@ compare: | |||
361 | */ | 363 | */ |
362 | davinci_nand_writel(info, NANDFCR_OFFSET, | 364 | davinci_nand_writel(info, NANDFCR_OFFSET, |
363 | davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13)); | 365 | davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13)); |
366 | |||
367 | /* | ||
368 | * ECC_STATE field reads 0x3 (Error correction complete) immediately | ||
369 | * after setting the 4BITECC_ADD_CALC_START bit. So if you immediately | ||
370 | * begin trying to poll for the state, you may fall right out of your | ||
371 | * loop without any of the correction calculations having taken place. | ||
372 | * The recommendation from the hardware team is to wait till ECC_STATE | ||
373 | * reads less than 4, which means ECC HW has entered correction state. | ||
374 | */ | ||
375 | do { | ||
376 | ecc_state = (davinci_nand_readl(info, | ||
377 | NANDFSR_OFFSET) >> 8) & 0x0f; | ||
378 | cpu_relax(); | ||
379 | } while ((ecc_state < 4) && time_before(jiffies, timeo)); | ||
380 | |||
364 | for (;;) { | 381 | for (;;) { |
365 | u32 fsr = davinci_nand_readl(info, NANDFSR_OFFSET); | 382 | u32 fsr = davinci_nand_readl(info, NANDFSR_OFFSET); |
366 | 383 | ||
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 3dfda9cc677d..618fb42b86b0 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/slab.h> | ||
24 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
25 | #include <linux/mtd/mtd.h> | 26 | #include <linux/mtd/mtd.h> |
26 | #include <linux/module.h> | 27 | #include <linux/module.h> |
@@ -29,15 +30,15 @@ | |||
29 | 30 | ||
30 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
31 | 32 | ||
32 | /* We define a module parameter that allows the user to override | 33 | /* We define a module parameter that allows the user to override |
33 | * the hardware and decide what timing mode should be used. | 34 | * the hardware and decide what timing mode should be used. |
34 | */ | 35 | */ |
35 | #define NAND_DEFAULT_TIMINGS -1 | 36 | #define NAND_DEFAULT_TIMINGS -1 |
36 | 37 | ||
37 | static int onfi_timing_mode = NAND_DEFAULT_TIMINGS; | 38 | static int onfi_timing_mode = NAND_DEFAULT_TIMINGS; |
38 | module_param(onfi_timing_mode, int, S_IRUGO); | 39 | module_param(onfi_timing_mode, int, S_IRUGO); |
39 | MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting. -1 indicates" | 40 | MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting." |
40 | " use default timings"); | 41 | " -1 indicates use default timings"); |
41 | 42 | ||
42 | #define DENALI_NAND_NAME "denali-nand" | 43 | #define DENALI_NAND_NAME "denali-nand" |
43 | 44 | ||
@@ -54,13 +55,13 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting. -1 indicates | |||
54 | INTR_STATUS0__RST_COMP | \ | 55 | INTR_STATUS0__RST_COMP | \ |
55 | INTR_STATUS0__ERASE_COMP) | 56 | INTR_STATUS0__ERASE_COMP) |
56 | 57 | ||
57 | /* indicates whether or not the internal value for the flash bank is | 58 | /* indicates whether or not the internal value for the flash bank is |
58 | valid or not */ | 59 | valid or not */ |
59 | #define CHIP_SELECT_INVALID -1 | 60 | #define CHIP_SELECT_INVALID -1 |
60 | 61 | ||
61 | #define SUPPORT_8BITECC 1 | 62 | #define SUPPORT_8BITECC 1 |
62 | 63 | ||
63 | /* This macro divides two integers and rounds fractional values up | 64 | /* This macro divides two integers and rounds fractional values up |
64 | * to the nearest integer value. */ | 65 | * to the nearest integer value. */ |
65 | #define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y))) | 66 | #define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y))) |
66 | 67 | ||
@@ -83,7 +84,7 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting. -1 indicates | |||
83 | #define ADDR_CYCLE 1 | 84 | #define ADDR_CYCLE 1 |
84 | #define STATUS_CYCLE 2 | 85 | #define STATUS_CYCLE 2 |
85 | 86 | ||
86 | /* this is a helper macro that allows us to | 87 | /* this is a helper macro that allows us to |
87 | * format the bank into the proper bits for the controller */ | 88 | * format the bank into the proper bits for the controller */ |
88 | #define BANK(x) ((x) << 24) | 89 | #define BANK(x) ((x) << 24) |
89 | 90 | ||
@@ -95,59 +96,64 @@ static const struct pci_device_id denali_pci_ids[] = { | |||
95 | }; | 96 | }; |
96 | 97 | ||
97 | 98 | ||
98 | /* these are static lookup tables that give us easy access to | 99 | /* these are static lookup tables that give us easy access to |
99 | registers in the NAND controller. | 100 | registers in the NAND controller. |
100 | */ | 101 | */ |
101 | static const uint32_t intr_status_addresses[4] = {INTR_STATUS0, | 102 | static const uint32_t intr_status_addresses[4] = {INTR_STATUS0, |
102 | INTR_STATUS1, | 103 | INTR_STATUS1, |
103 | INTR_STATUS2, | 104 | INTR_STATUS2, |
104 | INTR_STATUS3}; | 105 | INTR_STATUS3}; |
105 | 106 | ||
106 | static const uint32_t device_reset_banks[4] = {DEVICE_RESET__BANK0, | 107 | static const uint32_t device_reset_banks[4] = {DEVICE_RESET__BANK0, |
107 | DEVICE_RESET__BANK1, | 108 | DEVICE_RESET__BANK1, |
108 | DEVICE_RESET__BANK2, | 109 | DEVICE_RESET__BANK2, |
109 | DEVICE_RESET__BANK3}; | 110 | DEVICE_RESET__BANK3}; |
110 | 111 | ||
111 | static const uint32_t operation_timeout[4] = {INTR_STATUS0__TIME_OUT, | 112 | static const uint32_t operation_timeout[4] = {INTR_STATUS0__TIME_OUT, |
112 | INTR_STATUS1__TIME_OUT, | 113 | INTR_STATUS1__TIME_OUT, |
113 | INTR_STATUS2__TIME_OUT, | 114 | INTR_STATUS2__TIME_OUT, |
114 | INTR_STATUS3__TIME_OUT}; | 115 | INTR_STATUS3__TIME_OUT}; |
115 | 116 | ||
116 | static const uint32_t reset_complete[4] = {INTR_STATUS0__RST_COMP, | 117 | static const uint32_t reset_complete[4] = {INTR_STATUS0__RST_COMP, |
117 | INTR_STATUS1__RST_COMP, | 118 | INTR_STATUS1__RST_COMP, |
118 | INTR_STATUS2__RST_COMP, | 119 | INTR_STATUS2__RST_COMP, |
119 | INTR_STATUS3__RST_COMP}; | 120 | INTR_STATUS3__RST_COMP}; |
120 | 121 | ||
121 | /* specifies the debug level of the driver */ | 122 | /* specifies the debug level of the driver */ |
122 | static int nand_debug_level = 0; | 123 | static int nand_debug_level; |
123 | 124 | ||
124 | /* forward declarations */ | 125 | /* forward declarations */ |
125 | static void clear_interrupts(struct denali_nand_info *denali); | 126 | static void clear_interrupts(struct denali_nand_info *denali); |
126 | static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask); | 127 | static uint32_t wait_for_irq(struct denali_nand_info *denali, |
127 | static void denali_irq_enable(struct denali_nand_info *denali, uint32_t int_mask); | 128 | uint32_t irq_mask); |
129 | static void denali_irq_enable(struct denali_nand_info *denali, | ||
130 | uint32_t int_mask); | ||
128 | static uint32_t read_interrupt_status(struct denali_nand_info *denali); | 131 | static uint32_t read_interrupt_status(struct denali_nand_info *denali); |
129 | 132 | ||
130 | #define DEBUG_DENALI 0 | 133 | #define DEBUG_DENALI 0 |
131 | 134 | ||
132 | /* This is a wrapper for writing to the denali registers. | 135 | /* This is a wrapper for writing to the denali registers. |
133 | * this allows us to create debug information so we can | 136 | * this allows us to create debug information so we can |
134 | * observe how the driver is programming the device. | 137 | * observe how the driver is programming the device. |
135 | * it uses standard linux convention for (val, addr) */ | 138 | * it uses standard linux convention for (val, addr) */ |
136 | static void denali_write32(uint32_t value, void *addr) | 139 | static void denali_write32(uint32_t value, void *addr) |
137 | { | 140 | { |
138 | iowrite32(value, addr); | 141 | iowrite32(value, addr); |
139 | 142 | ||
140 | #if DEBUG_DENALI | 143 | #if DEBUG_DENALI |
141 | printk(KERN_ERR "wrote: 0x%x -> 0x%x\n", value, (uint32_t)((uint32_t)addr & 0x1fff)); | 144 | printk(KERN_INFO "wrote: 0x%x -> 0x%x\n", value, |
145 | (uint32_t)((uint32_t)addr & 0x1fff)); | ||
142 | #endif | 146 | #endif |
143 | } | 147 | } |
144 | 148 | ||
145 | /* Certain operations for the denali NAND controller use an indexed mode to read/write | 149 | /* Certain operations for the denali NAND controller use |
146 | data. The operation is performed by writing the address value of the command to | 150 | * an indexed mode to read/write data. The operation is |
147 | the device memory followed by the data. This function abstracts this common | 151 | * performed by writing the address value of the command |
148 | operation. | 152 | * to the device memory followed by the data. This function |
153 | * abstracts this common operation. | ||
149 | */ | 154 | */ |
150 | static void index_addr(struct denali_nand_info *denali, uint32_t address, uint32_t data) | 155 | static void index_addr(struct denali_nand_info *denali, |
156 | uint32_t address, uint32_t data) | ||
151 | { | 157 | { |
152 | denali_write32(address, denali->flash_mem); | 158 | denali_write32(address, denali->flash_mem); |
153 | denali_write32(data, denali->flash_mem + 0x10); | 159 | denali_write32(data, denali->flash_mem + 0x10); |
@@ -161,7 +167,7 @@ static void index_addr_read_data(struct denali_nand_info *denali, | |||
161 | *pdata = ioread32(denali->flash_mem + 0x10); | 167 | *pdata = ioread32(denali->flash_mem + 0x10); |
162 | } | 168 | } |
163 | 169 | ||
164 | /* We need to buffer some data for some of the NAND core routines. | 170 | /* We need to buffer some data for some of the NAND core routines. |
165 | * The operations manage buffering that data. */ | 171 | * The operations manage buffering that data. */ |
166 | static void reset_buf(struct denali_nand_info *denali) | 172 | static void reset_buf(struct denali_nand_info *denali) |
167 | { | 173 | { |
@@ -183,7 +189,7 @@ static void read_status(struct denali_nand_info *denali) | |||
183 | reset_buf(denali); | 189 | reset_buf(denali); |
184 | 190 | ||
185 | /* initiate a device status read */ | 191 | /* initiate a device status read */ |
186 | cmd = MODE_11 | BANK(denali->flash_bank); | 192 | cmd = MODE_11 | BANK(denali->flash_bank); |
187 | index_addr(denali, cmd | COMMAND_CYCLE, 0x70); | 193 | index_addr(denali, cmd | COMMAND_CYCLE, 0x70); |
188 | denali_write32(cmd | STATUS_CYCLE, denali->flash_mem); | 194 | denali_write32(cmd | STATUS_CYCLE, denali->flash_mem); |
189 | 195 | ||
@@ -191,7 +197,8 @@ static void read_status(struct denali_nand_info *denali) | |||
191 | write_byte_to_buf(denali, ioread32(denali->flash_mem + 0x10)); | 197 | write_byte_to_buf(denali, ioread32(denali->flash_mem + 0x10)); |
192 | 198 | ||
193 | #if DEBUG_DENALI | 199 | #if DEBUG_DENALI |
194 | printk("device reporting status value of 0x%2x\n", denali->buf.buf[0]); | 200 | printk(KERN_INFO "device reporting status value of 0x%2x\n", |
201 | denali->buf.buf[0]); | ||
195 | #endif | 202 | #endif |
196 | } | 203 | } |
197 | 204 | ||
@@ -199,7 +206,7 @@ static void read_status(struct denali_nand_info *denali) | |||
199 | static void reset_bank(struct denali_nand_info *denali) | 206 | static void reset_bank(struct denali_nand_info *denali) |
200 | { | 207 | { |
201 | uint32_t irq_status = 0; | 208 | uint32_t irq_status = 0; |
202 | uint32_t irq_mask = reset_complete[denali->flash_bank] | | 209 | uint32_t irq_mask = reset_complete[denali->flash_bank] | |
203 | operation_timeout[denali->flash_bank]; | 210 | operation_timeout[denali->flash_bank]; |
204 | int bank = 0; | 211 | int bank = 0; |
205 | 212 | ||
@@ -209,15 +216,13 @@ static void reset_bank(struct denali_nand_info *denali) | |||
209 | denali_write32(bank, denali->flash_reg + DEVICE_RESET); | 216 | denali_write32(bank, denali->flash_reg + DEVICE_RESET); |
210 | 217 | ||
211 | irq_status = wait_for_irq(denali, irq_mask); | 218 | irq_status = wait_for_irq(denali, irq_mask); |
212 | 219 | ||
213 | if (irq_status & operation_timeout[denali->flash_bank]) | 220 | if (irq_status & operation_timeout[denali->flash_bank]) |
214 | { | ||
215 | printk(KERN_ERR "reset bank failed.\n"); | 221 | printk(KERN_ERR "reset bank failed.\n"); |
216 | } | ||
217 | } | 222 | } |
218 | 223 | ||
219 | /* Reset the flash controller */ | 224 | /* Reset the flash controller */ |
220 | static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali) | 225 | static uint16_t denali_nand_reset(struct denali_nand_info *denali) |
221 | { | 226 | { |
222 | uint32_t i; | 227 | uint32_t i; |
223 | 228 | ||
@@ -229,8 +234,10 @@ static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali) | |||
229 | denali->flash_reg + intr_status_addresses[i]); | 234 | denali->flash_reg + intr_status_addresses[i]); |
230 | 235 | ||
231 | for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) { | 236 | for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) { |
232 | denali_write32(device_reset_banks[i], denali->flash_reg + DEVICE_RESET); | 237 | denali_write32(device_reset_banks[i], |
233 | while (!(ioread32(denali->flash_reg + intr_status_addresses[i]) & | 238 | denali->flash_reg + DEVICE_RESET); |
239 | while (!(ioread32(denali->flash_reg + | ||
240 | intr_status_addresses[i]) & | ||
234 | (reset_complete[i] | operation_timeout[i]))) | 241 | (reset_complete[i] | operation_timeout[i]))) |
235 | ; | 242 | ; |
236 | if (ioread32(denali->flash_reg + intr_status_addresses[i]) & | 243 | if (ioread32(denali->flash_reg + intr_status_addresses[i]) & |
@@ -246,11 +253,12 @@ static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali) | |||
246 | return PASS; | 253 | return PASS; |
247 | } | 254 | } |
248 | 255 | ||
249 | /* this routine calculates the ONFI timing values for a given mode and programs | 256 | /* this routine calculates the ONFI timing values for a given mode and |
250 | * the clocking register accordingly. The mode is determined by the get_onfi_nand_para | 257 | * programs the clocking register accordingly. The mode is determined by |
251 | routine. | 258 | * the get_onfi_nand_para routine. |
252 | */ | 259 | */ |
253 | static void NAND_ONFi_Timing_Mode(struct denali_nand_info *denali, uint16_t mode) | 260 | static void nand_onfi_timing_set(struct denali_nand_info *denali, |
261 | uint16_t mode) | ||
254 | { | 262 | { |
255 | uint16_t Trea[6] = {40, 30, 25, 20, 20, 16}; | 263 | uint16_t Trea[6] = {40, 30, 25, 20, 20, 16}; |
256 | uint16_t Trp[6] = {50, 25, 17, 15, 12, 10}; | 264 | uint16_t Trp[6] = {50, 25, 17, 15, 12, 10}; |
@@ -347,136 +355,24 @@ static void NAND_ONFi_Timing_Mode(struct denali_nand_info *denali, uint16_t mode | |||
347 | denali_write32(cs_cnt, denali->flash_reg + CS_SETUP_CNT); | 355 | denali_write32(cs_cnt, denali->flash_reg + CS_SETUP_CNT); |
348 | } | 356 | } |
349 | 357 | ||
350 | /* configures the initial ECC settings for the controller */ | ||
351 | static void set_ecc_config(struct denali_nand_info *denali) | ||
352 | { | ||
353 | #if SUPPORT_8BITECC | ||
354 | if ((ioread32(denali->flash_reg + DEVICE_MAIN_AREA_SIZE) < 4096) || | ||
355 | (ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE) <= 128)) | ||
356 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); | ||
357 | #endif | ||
358 | |||
359 | if ((ioread32(denali->flash_reg + ECC_CORRECTION) & ECC_CORRECTION__VALUE) | ||
360 | == 1) { | ||
361 | denali->dev_info.wECCBytesPerSector = 4; | ||
362 | denali->dev_info.wECCBytesPerSector *= denali->dev_info.wDevicesConnected; | ||
363 | denali->dev_info.wNumPageSpareFlag = | ||
364 | denali->dev_info.wPageSpareSize - | ||
365 | denali->dev_info.wPageDataSize / | ||
366 | (ECC_SECTOR_SIZE * denali->dev_info.wDevicesConnected) * | ||
367 | denali->dev_info.wECCBytesPerSector | ||
368 | - denali->dev_info.wSpareSkipBytes; | ||
369 | } else { | ||
370 | denali->dev_info.wECCBytesPerSector = | ||
371 | (ioread32(denali->flash_reg + ECC_CORRECTION) & | ||
372 | ECC_CORRECTION__VALUE) * 13 / 8; | ||
373 | if ((denali->dev_info.wECCBytesPerSector) % 2 == 0) | ||
374 | denali->dev_info.wECCBytesPerSector += 2; | ||
375 | else | ||
376 | denali->dev_info.wECCBytesPerSector += 1; | ||
377 | |||
378 | denali->dev_info.wECCBytesPerSector *= denali->dev_info.wDevicesConnected; | ||
379 | denali->dev_info.wNumPageSpareFlag = denali->dev_info.wPageSpareSize - | ||
380 | denali->dev_info.wPageDataSize / | ||
381 | (ECC_SECTOR_SIZE * denali->dev_info.wDevicesConnected) * | ||
382 | denali->dev_info.wECCBytesPerSector | ||
383 | - denali->dev_info.wSpareSkipBytes; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | /* queries the NAND device to see what ONFI modes it supports. */ | 358 | /* queries the NAND device to see what ONFI modes it supports. */ |
388 | static uint16_t get_onfi_nand_para(struct denali_nand_info *denali) | 359 | static uint16_t get_onfi_nand_para(struct denali_nand_info *denali) |
389 | { | 360 | { |
390 | int i; | 361 | int i; |
391 | uint16_t blks_lun_l, blks_lun_h, n_of_luns; | 362 | /* we needn't to do a reset here because driver has already |
392 | uint32_t blockperlun, id; | 363 | * reset all the banks before |
393 | 364 | * */ | |
394 | denali_write32(DEVICE_RESET__BANK0, denali->flash_reg + DEVICE_RESET); | ||
395 | |||
396 | while (!((ioread32(denali->flash_reg + INTR_STATUS0) & | ||
397 | INTR_STATUS0__RST_COMP) | | ||
398 | (ioread32(denali->flash_reg + INTR_STATUS0) & | ||
399 | INTR_STATUS0__TIME_OUT))) | ||
400 | ; | ||
401 | |||
402 | if (ioread32(denali->flash_reg + INTR_STATUS0) & INTR_STATUS0__RST_COMP) { | ||
403 | denali_write32(DEVICE_RESET__BANK1, denali->flash_reg + DEVICE_RESET); | ||
404 | while (!((ioread32(denali->flash_reg + INTR_STATUS1) & | ||
405 | INTR_STATUS1__RST_COMP) | | ||
406 | (ioread32(denali->flash_reg + INTR_STATUS1) & | ||
407 | INTR_STATUS1__TIME_OUT))) | ||
408 | ; | ||
409 | |||
410 | if (ioread32(denali->flash_reg + INTR_STATUS1) & | ||
411 | INTR_STATUS1__RST_COMP) { | ||
412 | denali_write32(DEVICE_RESET__BANK2, | ||
413 | denali->flash_reg + DEVICE_RESET); | ||
414 | while (!((ioread32(denali->flash_reg + INTR_STATUS2) & | ||
415 | INTR_STATUS2__RST_COMP) | | ||
416 | (ioread32(denali->flash_reg + INTR_STATUS2) & | ||
417 | INTR_STATUS2__TIME_OUT))) | ||
418 | ; | ||
419 | |||
420 | if (ioread32(denali->flash_reg + INTR_STATUS2) & | ||
421 | INTR_STATUS2__RST_COMP) { | ||
422 | denali_write32(DEVICE_RESET__BANK3, | ||
423 | denali->flash_reg + DEVICE_RESET); | ||
424 | while (!((ioread32(denali->flash_reg + INTR_STATUS3) & | ||
425 | INTR_STATUS3__RST_COMP) | | ||
426 | (ioread32(denali->flash_reg + INTR_STATUS3) & | ||
427 | INTR_STATUS3__TIME_OUT))) | ||
428 | ; | ||
429 | } else { | ||
430 | printk(KERN_ERR "Getting a time out for bank 2!\n"); | ||
431 | } | ||
432 | } else { | ||
433 | printk(KERN_ERR "Getting a time out for bank 1!\n"); | ||
434 | } | ||
435 | } | ||
436 | |||
437 | denali_write32(INTR_STATUS0__TIME_OUT, denali->flash_reg + INTR_STATUS0); | ||
438 | denali_write32(INTR_STATUS1__TIME_OUT, denali->flash_reg + INTR_STATUS1); | ||
439 | denali_write32(INTR_STATUS2__TIME_OUT, denali->flash_reg + INTR_STATUS2); | ||
440 | denali_write32(INTR_STATUS3__TIME_OUT, denali->flash_reg + INTR_STATUS3); | ||
441 | |||
442 | denali->dev_info.wONFIDevFeatures = | ||
443 | ioread32(denali->flash_reg + ONFI_DEVICE_FEATURES); | ||
444 | denali->dev_info.wONFIOptCommands = | ||
445 | ioread32(denali->flash_reg + ONFI_OPTIONAL_COMMANDS); | ||
446 | denali->dev_info.wONFITimingMode = | ||
447 | ioread32(denali->flash_reg + ONFI_TIMING_MODE); | ||
448 | denali->dev_info.wONFIPgmCacheTimingMode = | ||
449 | ioread32(denali->flash_reg + ONFI_PGM_CACHE_TIMING_MODE); | ||
450 | |||
451 | n_of_luns = ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) & | ||
452 | ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS; | ||
453 | blks_lun_l = ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L); | ||
454 | blks_lun_h = ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U); | ||
455 | |||
456 | blockperlun = (blks_lun_h << 16) | blks_lun_l; | ||
457 | |||
458 | denali->dev_info.wTotalBlocks = n_of_luns * blockperlun; | ||
459 | |||
460 | if (!(ioread32(denali->flash_reg + ONFI_TIMING_MODE) & | 365 | if (!(ioread32(denali->flash_reg + ONFI_TIMING_MODE) & |
461 | ONFI_TIMING_MODE__VALUE)) | 366 | ONFI_TIMING_MODE__VALUE)) |
462 | return FAIL; | 367 | return FAIL; |
463 | 368 | ||
464 | for (i = 5; i > 0; i--) { | 369 | for (i = 5; i > 0; i--) { |
465 | if (ioread32(denali->flash_reg + ONFI_TIMING_MODE) & (0x01 << i)) | 370 | if (ioread32(denali->flash_reg + ONFI_TIMING_MODE) & |
371 | (0x01 << i)) | ||
466 | break; | 372 | break; |
467 | } | 373 | } |
468 | 374 | ||
469 | NAND_ONFi_Timing_Mode(denali, i); | 375 | nand_onfi_timing_set(denali, i); |
470 | |||
471 | index_addr(denali, MODE_11 | 0, 0x90); | ||
472 | index_addr(denali, MODE_11 | 1, 0); | ||
473 | |||
474 | for (i = 0; i < 3; i++) | ||
475 | index_addr_read_data(denali, MODE_11 | 2, &id); | ||
476 | |||
477 | nand_dbg_print(NAND_DBG_DEBUG, "3rd ID: 0x%x\n", id); | ||
478 | |||
479 | denali->dev_info.MLCDevice = id & 0x0C; | ||
480 | 376 | ||
481 | /* By now, all the ONFI devices we know support the page cache */ | 377 | /* By now, all the ONFI devices we know support the page cache */ |
482 | /* rw feature. So here we enable the pipeline_rw_ahead feature */ | 378 | /* rw feature. So here we enable the pipeline_rw_ahead feature */ |
@@ -486,25 +382,10 @@ static uint16_t get_onfi_nand_para(struct denali_nand_info *denali) | |||
486 | return PASS; | 382 | return PASS; |
487 | } | 383 | } |
488 | 384 | ||
489 | static void get_samsung_nand_para(struct denali_nand_info *denali) | 385 | static void get_samsung_nand_para(struct denali_nand_info *denali, |
386 | uint8_t device_id) | ||
490 | { | 387 | { |
491 | uint8_t no_of_planes; | 388 | if (device_id == 0xd3) { /* Samsung K9WAG08U1A */ |
492 | uint32_t blk_size; | ||
493 | uint64_t plane_size, capacity; | ||
494 | uint32_t id_bytes[5]; | ||
495 | int i; | ||
496 | |||
497 | index_addr(denali, (uint32_t)(MODE_11 | 0), 0x90); | ||
498 | index_addr(denali, (uint32_t)(MODE_11 | 1), 0); | ||
499 | for (i = 0; i < 5; i++) | ||
500 | index_addr_read_data(denali, (uint32_t)(MODE_11 | 2), &id_bytes[i]); | ||
501 | |||
502 | nand_dbg_print(NAND_DBG_DEBUG, | ||
503 | "ID bytes: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", | ||
504 | id_bytes[0], id_bytes[1], id_bytes[2], | ||
505 | id_bytes[3], id_bytes[4]); | ||
506 | |||
507 | if ((id_bytes[1] & 0xff) == 0xd3) { /* Samsung K9WAG08U1A */ | ||
508 | /* Set timing register values according to datasheet */ | 389 | /* Set timing register values according to datasheet */ |
509 | denali_write32(5, denali->flash_reg + ACC_CLKS); | 390 | denali_write32(5, denali->flash_reg + ACC_CLKS); |
510 | denali_write32(20, denali->flash_reg + RE_2_WE); | 391 | denali_write32(20, denali->flash_reg + RE_2_WE); |
@@ -514,19 +395,10 @@ static void get_samsung_nand_para(struct denali_nand_info *denali) | |||
514 | denali_write32(2, denali->flash_reg + RDWR_EN_HI_CNT); | 395 | denali_write32(2, denali->flash_reg + RDWR_EN_HI_CNT); |
515 | denali_write32(2, denali->flash_reg + CS_SETUP_CNT); | 396 | denali_write32(2, denali->flash_reg + CS_SETUP_CNT); |
516 | } | 397 | } |
517 | |||
518 | no_of_planes = 1 << ((id_bytes[4] & 0x0c) >> 2); | ||
519 | plane_size = (uint64_t)64 << ((id_bytes[4] & 0x70) >> 4); | ||
520 | blk_size = 64 << ((ioread32(denali->flash_reg + DEVICE_PARAM_1) & 0x30) >> 4); | ||
521 | capacity = (uint64_t)128 * plane_size * no_of_planes; | ||
522 | |||
523 | do_div(capacity, blk_size); | ||
524 | denali->dev_info.wTotalBlocks = capacity; | ||
525 | } | 398 | } |
526 | 399 | ||
527 | static void get_toshiba_nand_para(struct denali_nand_info *denali) | 400 | static void get_toshiba_nand_para(struct denali_nand_info *denali) |
528 | { | 401 | { |
529 | void __iomem *scratch_reg; | ||
530 | uint32_t tmp; | 402 | uint32_t tmp; |
531 | 403 | ||
532 | /* Workaround to fix a controller bug which reports a wrong */ | 404 | /* Workaround to fix a controller bug which reports a wrong */ |
@@ -536,81 +408,52 @@ static void get_toshiba_nand_para(struct denali_nand_info *denali) | |||
536 | denali_write32(216, denali->flash_reg + DEVICE_SPARE_AREA_SIZE); | 408 | denali_write32(216, denali->flash_reg + DEVICE_SPARE_AREA_SIZE); |
537 | tmp = ioread32(denali->flash_reg + DEVICES_CONNECTED) * | 409 | tmp = ioread32(denali->flash_reg + DEVICES_CONNECTED) * |
538 | ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE); | 410 | ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE); |
539 | denali_write32(tmp, denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); | 411 | denali_write32(tmp, |
412 | denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); | ||
540 | #if SUPPORT_15BITECC | 413 | #if SUPPORT_15BITECC |
541 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); | 414 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); |
542 | #elif SUPPORT_8BITECC | 415 | #elif SUPPORT_8BITECC |
543 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); | 416 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); |
544 | #endif | 417 | #endif |
545 | } | 418 | } |
546 | |||
547 | /* As Toshiba NAND can not provide it's block number, */ | ||
548 | /* so here we need user to provide the correct block */ | ||
549 | /* number in a scratch register before the Linux NAND */ | ||
550 | /* driver is loaded. If no valid value found in the scratch */ | ||
551 | /* register, then we use default block number value */ | ||
552 | scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); | ||
553 | if (!scratch_reg) { | ||
554 | printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", | ||
555 | __FILE__, __LINE__); | ||
556 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
557 | } else { | ||
558 | nand_dbg_print(NAND_DBG_WARN, | ||
559 | "Spectra: ioremap reg address: 0x%p\n", scratch_reg); | ||
560 | denali->dev_info.wTotalBlocks = 1 << ioread8(scratch_reg); | ||
561 | if (denali->dev_info.wTotalBlocks < 512) | ||
562 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
563 | iounmap(scratch_reg); | ||
564 | } | ||
565 | } | 419 | } |
566 | 420 | ||
567 | static void get_hynix_nand_para(struct denali_nand_info *denali) | 421 | static void get_hynix_nand_para(struct denali_nand_info *denali, |
422 | uint8_t device_id) | ||
568 | { | 423 | { |
569 | void __iomem *scratch_reg; | ||
570 | uint32_t main_size, spare_size; | 424 | uint32_t main_size, spare_size; |
571 | 425 | ||
572 | switch (denali->dev_info.wDeviceID) { | 426 | switch (device_id) { |
573 | case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ | 427 | case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ |
574 | case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ | 428 | case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ |
575 | denali_write32(128, denali->flash_reg + PAGES_PER_BLOCK); | 429 | denali_write32(128, denali->flash_reg + PAGES_PER_BLOCK); |
576 | denali_write32(4096, denali->flash_reg + DEVICE_MAIN_AREA_SIZE); | 430 | denali_write32(4096, denali->flash_reg + DEVICE_MAIN_AREA_SIZE); |
577 | denali_write32(224, denali->flash_reg + DEVICE_SPARE_AREA_SIZE); | 431 | denali_write32(224, denali->flash_reg + DEVICE_SPARE_AREA_SIZE); |
578 | main_size = 4096 * ioread32(denali->flash_reg + DEVICES_CONNECTED); | 432 | main_size = 4096 * |
579 | spare_size = 224 * ioread32(denali->flash_reg + DEVICES_CONNECTED); | 433 | ioread32(denali->flash_reg + DEVICES_CONNECTED); |
580 | denali_write32(main_size, denali->flash_reg + LOGICAL_PAGE_DATA_SIZE); | 434 | spare_size = 224 * |
581 | denali_write32(spare_size, denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); | 435 | ioread32(denali->flash_reg + DEVICES_CONNECTED); |
436 | denali_write32(main_size, | ||
437 | denali->flash_reg + LOGICAL_PAGE_DATA_SIZE); | ||
438 | denali_write32(spare_size, | ||
439 | denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); | ||
582 | denali_write32(0, denali->flash_reg + DEVICE_WIDTH); | 440 | denali_write32(0, denali->flash_reg + DEVICE_WIDTH); |
583 | #if SUPPORT_15BITECC | 441 | #if SUPPORT_15BITECC |
584 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); | 442 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); |
585 | #elif SUPPORT_8BITECC | 443 | #elif SUPPORT_8BITECC |
586 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); | 444 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); |
587 | #endif | 445 | #endif |
588 | denali->dev_info.MLCDevice = 1; | ||
589 | break; | 446 | break; |
590 | default: | 447 | default: |
591 | nand_dbg_print(NAND_DBG_WARN, | 448 | nand_dbg_print(NAND_DBG_WARN, |
592 | "Spectra: Unknown Hynix NAND (Device ID: 0x%x)." | 449 | "Spectra: Unknown Hynix NAND (Device ID: 0x%x)." |
593 | "Will use default parameter values instead.\n", | 450 | "Will use default parameter values instead.\n", |
594 | denali->dev_info.wDeviceID); | 451 | device_id); |
595 | } | ||
596 | |||
597 | scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); | ||
598 | if (!scratch_reg) { | ||
599 | printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", | ||
600 | __FILE__, __LINE__); | ||
601 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
602 | } else { | ||
603 | nand_dbg_print(NAND_DBG_WARN, | ||
604 | "Spectra: ioremap reg address: 0x%p\n", scratch_reg); | ||
605 | denali->dev_info.wTotalBlocks = 1 << ioread8(scratch_reg); | ||
606 | if (denali->dev_info.wTotalBlocks < 512) | ||
607 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
608 | iounmap(scratch_reg); | ||
609 | } | 452 | } |
610 | } | 453 | } |
611 | 454 | ||
612 | /* determines how many NAND chips are connected to the controller. Note for | 455 | /* determines how many NAND chips are connected to the controller. Note for |
613 | Intel CE4100 devices we don't support more than one device. | 456 | Intel CE4100 devices we don't support more than one device. |
614 | */ | 457 | */ |
615 | static void find_valid_banks(struct denali_nand_info *denali) | 458 | static void find_valid_banks(struct denali_nand_info *denali) |
616 | { | 459 | { |
@@ -621,7 +464,8 @@ static void find_valid_banks(struct denali_nand_info *denali) | |||
621 | for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) { | 464 | for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) { |
622 | index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 0), 0x90); | 465 | index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 0), 0x90); |
623 | index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 1), 0); | 466 | index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 1), 0); |
624 | index_addr_read_data(denali, (uint32_t)(MODE_11 | (i << 24) | 2), &id[i]); | 467 | index_addr_read_data(denali, |
468 | (uint32_t)(MODE_11 | (i << 24) | 2), &id[i]); | ||
625 | 469 | ||
626 | nand_dbg_print(NAND_DBG_DEBUG, | 470 | nand_dbg_print(NAND_DBG_DEBUG, |
627 | "Return 1st ID for bank[%d]: %x\n", i, id[i]); | 471 | "Return 1st ID for bank[%d]: %x\n", i, id[i]); |
@@ -637,14 +481,12 @@ static void find_valid_banks(struct denali_nand_info *denali) | |||
637 | } | 481 | } |
638 | } | 482 | } |
639 | 483 | ||
640 | if (denali->platform == INTEL_CE4100) | 484 | if (denali->platform == INTEL_CE4100) { |
641 | { | ||
642 | /* Platform limitations of the CE4100 device limit | 485 | /* Platform limitations of the CE4100 device limit |
643 | * users to a single chip solution for NAND. | 486 | * users to a single chip solution for NAND. |
644 | * Multichip support is not enabled. | 487 | * Multichip support is not enabled. |
645 | */ | 488 | */ |
646 | if (denali->total_used_banks != 1) | 489 | if (denali->total_used_banks != 1) { |
647 | { | ||
648 | printk(KERN_ERR "Sorry, Intel CE4100 only supports " | 490 | printk(KERN_ERR "Sorry, Intel CE4100 only supports " |
649 | "a single NAND device.\n"); | 491 | "a single NAND device.\n"); |
650 | BUG(); | 492 | BUG(); |
@@ -656,150 +498,60 @@ static void find_valid_banks(struct denali_nand_info *denali) | |||
656 | 498 | ||
657 | static void detect_partition_feature(struct denali_nand_info *denali) | 499 | static void detect_partition_feature(struct denali_nand_info *denali) |
658 | { | 500 | { |
501 | /* For MRST platform, denali->fwblks represent the | ||
502 | * number of blocks firmware is taken, | ||
503 | * FW is in protect partition and MTD driver has no | ||
504 | * permission to access it. So let driver know how many | ||
505 | * blocks it can't touch. | ||
506 | * */ | ||
659 | if (ioread32(denali->flash_reg + FEATURES) & FEATURES__PARTITION) { | 507 | if (ioread32(denali->flash_reg + FEATURES) & FEATURES__PARTITION) { |
660 | if ((ioread32(denali->flash_reg + PERM_SRC_ID_1) & | 508 | if ((ioread32(denali->flash_reg + PERM_SRC_ID_1) & |
661 | PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) { | 509 | PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) { |
662 | denali->dev_info.wSpectraStartBlock = | 510 | denali->fwblks = |
663 | ((ioread32(denali->flash_reg + MIN_MAX_BANK_1) & | 511 | ((ioread32(denali->flash_reg + MIN_MAX_BANK_1) & |
664 | MIN_MAX_BANK_1__MIN_VALUE) * | 512 | MIN_MAX_BANK_1__MIN_VALUE) * |
665 | denali->dev_info.wTotalBlocks) | 513 | denali->blksperchip) |
666 | + | 514 | + |
667 | (ioread32(denali->flash_reg + MIN_BLK_ADDR_1) & | 515 | (ioread32(denali->flash_reg + MIN_BLK_ADDR_1) & |
668 | MIN_BLK_ADDR_1__VALUE); | 516 | MIN_BLK_ADDR_1__VALUE); |
669 | 517 | } else | |
670 | denali->dev_info.wSpectraEndBlock = | 518 | denali->fwblks = SPECTRA_START_BLOCK; |
671 | (((ioread32(denali->flash_reg + MIN_MAX_BANK_1) & | 519 | } else |
672 | MIN_MAX_BANK_1__MAX_VALUE) >> 2) * | 520 | denali->fwblks = SPECTRA_START_BLOCK; |
673 | denali->dev_info.wTotalBlocks) | ||
674 | + | ||
675 | (ioread32(denali->flash_reg + MAX_BLK_ADDR_1) & | ||
676 | MAX_BLK_ADDR_1__VALUE); | ||
677 | |||
678 | denali->dev_info.wTotalBlocks *= denali->total_used_banks; | ||
679 | |||
680 | if (denali->dev_info.wSpectraEndBlock >= | ||
681 | denali->dev_info.wTotalBlocks) { | ||
682 | denali->dev_info.wSpectraEndBlock = | ||
683 | denali->dev_info.wTotalBlocks - 1; | ||
684 | } | ||
685 | |||
686 | denali->dev_info.wDataBlockNum = | ||
687 | denali->dev_info.wSpectraEndBlock - | ||
688 | denali->dev_info.wSpectraStartBlock + 1; | ||
689 | } else { | ||
690 | denali->dev_info.wTotalBlocks *= denali->total_used_banks; | ||
691 | denali->dev_info.wSpectraStartBlock = SPECTRA_START_BLOCK; | ||
692 | denali->dev_info.wSpectraEndBlock = | ||
693 | denali->dev_info.wTotalBlocks - 1; | ||
694 | denali->dev_info.wDataBlockNum = | ||
695 | denali->dev_info.wSpectraEndBlock - | ||
696 | denali->dev_info.wSpectraStartBlock + 1; | ||
697 | } | ||
698 | } else { | ||
699 | denali->dev_info.wTotalBlocks *= denali->total_used_banks; | ||
700 | denali->dev_info.wSpectraStartBlock = SPECTRA_START_BLOCK; | ||
701 | denali->dev_info.wSpectraEndBlock = denali->dev_info.wTotalBlocks - 1; | ||
702 | denali->dev_info.wDataBlockNum = | ||
703 | denali->dev_info.wSpectraEndBlock - | ||
704 | denali->dev_info.wSpectraStartBlock + 1; | ||
705 | } | ||
706 | } | 521 | } |
707 | 522 | ||
708 | static void dump_device_info(struct denali_nand_info *denali) | 523 | static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) |
709 | { | ||
710 | nand_dbg_print(NAND_DBG_DEBUG, "denali->dev_info:\n"); | ||
711 | nand_dbg_print(NAND_DBG_DEBUG, "DeviceMaker: 0x%x\n", | ||
712 | denali->dev_info.wDeviceMaker); | ||
713 | nand_dbg_print(NAND_DBG_DEBUG, "DeviceID: 0x%x\n", | ||
714 | denali->dev_info.wDeviceID); | ||
715 | nand_dbg_print(NAND_DBG_DEBUG, "DeviceType: 0x%x\n", | ||
716 | denali->dev_info.wDeviceType); | ||
717 | nand_dbg_print(NAND_DBG_DEBUG, "SpectraStartBlock: %d\n", | ||
718 | denali->dev_info.wSpectraStartBlock); | ||
719 | nand_dbg_print(NAND_DBG_DEBUG, "SpectraEndBlock: %d\n", | ||
720 | denali->dev_info.wSpectraEndBlock); | ||
721 | nand_dbg_print(NAND_DBG_DEBUG, "TotalBlocks: %d\n", | ||
722 | denali->dev_info.wTotalBlocks); | ||
723 | nand_dbg_print(NAND_DBG_DEBUG, "PagesPerBlock: %d\n", | ||
724 | denali->dev_info.wPagesPerBlock); | ||
725 | nand_dbg_print(NAND_DBG_DEBUG, "PageSize: %d\n", | ||
726 | denali->dev_info.wPageSize); | ||
727 | nand_dbg_print(NAND_DBG_DEBUG, "PageDataSize: %d\n", | ||
728 | denali->dev_info.wPageDataSize); | ||
729 | nand_dbg_print(NAND_DBG_DEBUG, "PageSpareSize: %d\n", | ||
730 | denali->dev_info.wPageSpareSize); | ||
731 | nand_dbg_print(NAND_DBG_DEBUG, "NumPageSpareFlag: %d\n", | ||
732 | denali->dev_info.wNumPageSpareFlag); | ||
733 | nand_dbg_print(NAND_DBG_DEBUG, "ECCBytesPerSector: %d\n", | ||
734 | denali->dev_info.wECCBytesPerSector); | ||
735 | nand_dbg_print(NAND_DBG_DEBUG, "BlockSize: %d\n", | ||
736 | denali->dev_info.wBlockSize); | ||
737 | nand_dbg_print(NAND_DBG_DEBUG, "BlockDataSize: %d\n", | ||
738 | denali->dev_info.wBlockDataSize); | ||
739 | nand_dbg_print(NAND_DBG_DEBUG, "DataBlockNum: %d\n", | ||
740 | denali->dev_info.wDataBlockNum); | ||
741 | nand_dbg_print(NAND_DBG_DEBUG, "PlaneNum: %d\n", | ||
742 | denali->dev_info.bPlaneNum); | ||
743 | nand_dbg_print(NAND_DBG_DEBUG, "DeviceMainAreaSize: %d\n", | ||
744 | denali->dev_info.wDeviceMainAreaSize); | ||
745 | nand_dbg_print(NAND_DBG_DEBUG, "DeviceSpareAreaSize: %d\n", | ||
746 | denali->dev_info.wDeviceSpareAreaSize); | ||
747 | nand_dbg_print(NAND_DBG_DEBUG, "DevicesConnected: %d\n", | ||
748 | denali->dev_info.wDevicesConnected); | ||
749 | nand_dbg_print(NAND_DBG_DEBUG, "DeviceWidth: %d\n", | ||
750 | denali->dev_info.wDeviceWidth); | ||
751 | nand_dbg_print(NAND_DBG_DEBUG, "HWRevision: 0x%x\n", | ||
752 | denali->dev_info.wHWRevision); | ||
753 | nand_dbg_print(NAND_DBG_DEBUG, "HWFeatures: 0x%x\n", | ||
754 | denali->dev_info.wHWFeatures); | ||
755 | nand_dbg_print(NAND_DBG_DEBUG, "ONFIDevFeatures: 0x%x\n", | ||
756 | denali->dev_info.wONFIDevFeatures); | ||
757 | nand_dbg_print(NAND_DBG_DEBUG, "ONFIOptCommands: 0x%x\n", | ||
758 | denali->dev_info.wONFIOptCommands); | ||
759 | nand_dbg_print(NAND_DBG_DEBUG, "ONFITimingMode: 0x%x\n", | ||
760 | denali->dev_info.wONFITimingMode); | ||
761 | nand_dbg_print(NAND_DBG_DEBUG, "ONFIPgmCacheTimingMode: 0x%x\n", | ||
762 | denali->dev_info.wONFIPgmCacheTimingMode); | ||
763 | nand_dbg_print(NAND_DBG_DEBUG, "MLCDevice: %s\n", | ||
764 | denali->dev_info.MLCDevice ? "Yes" : "No"); | ||
765 | nand_dbg_print(NAND_DBG_DEBUG, "SpareSkipBytes: %d\n", | ||
766 | denali->dev_info.wSpareSkipBytes); | ||
767 | nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageNumber: %d\n", | ||
768 | denali->dev_info.nBitsInPageNumber); | ||
769 | nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageDataSize: %d\n", | ||
770 | denali->dev_info.nBitsInPageDataSize); | ||
771 | nand_dbg_print(NAND_DBG_DEBUG, "BitsInBlockDataSize: %d\n", | ||
772 | denali->dev_info.nBitsInBlockDataSize); | ||
773 | } | ||
774 | |||
775 | static uint16_t NAND_Read_Device_ID(struct denali_nand_info *denali) | ||
776 | { | 524 | { |
777 | uint16_t status = PASS; | 525 | uint16_t status = PASS; |
778 | uint8_t no_of_planes; | 526 | uint32_t id_bytes[5], addr; |
527 | uint8_t i, maf_id, device_id; | ||
779 | 528 | ||
780 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", | 529 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", |
781 | __FILE__, __LINE__, __func__); | 530 | __FILE__, __LINE__, __func__); |
782 | 531 | ||
783 | denali->dev_info.wDeviceMaker = ioread32(denali->flash_reg + MANUFACTURER_ID); | 532 | /* Use read id method to get device ID and other |
784 | denali->dev_info.wDeviceID = ioread32(denali->flash_reg + DEVICE_ID); | 533 | * params. For some NAND chips, controller can't |
785 | denali->dev_info.bDeviceParam0 = ioread32(denali->flash_reg + DEVICE_PARAM_0); | 534 | * report the correct device ID by reading from |
786 | denali->dev_info.bDeviceParam1 = ioread32(denali->flash_reg + DEVICE_PARAM_1); | 535 | * DEVICE_ID register |
787 | denali->dev_info.bDeviceParam2 = ioread32(denali->flash_reg + DEVICE_PARAM_2); | 536 | * */ |
788 | 537 | addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); | |
789 | denali->dev_info.MLCDevice = ioread32(denali->flash_reg + DEVICE_PARAM_0) & 0x0c; | 538 | index_addr(denali, (uint32_t)addr | 0, 0x90); |
539 | index_addr(denali, (uint32_t)addr | 1, 0); | ||
540 | for (i = 0; i < 5; i++) | ||
541 | index_addr_read_data(denali, addr | 2, &id_bytes[i]); | ||
542 | maf_id = id_bytes[0]; | ||
543 | device_id = id_bytes[1]; | ||
790 | 544 | ||
791 | if (ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) & | 545 | if (ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) & |
792 | ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */ | 546 | ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */ |
793 | if (FAIL == get_onfi_nand_para(denali)) | 547 | if (FAIL == get_onfi_nand_para(denali)) |
794 | return FAIL; | 548 | return FAIL; |
795 | } else if (denali->dev_info.wDeviceMaker == 0xEC) { /* Samsung NAND */ | 549 | } else if (maf_id == 0xEC) { /* Samsung NAND */ |
796 | get_samsung_nand_para(denali); | 550 | get_samsung_nand_para(denali, device_id); |
797 | } else if (denali->dev_info.wDeviceMaker == 0x98) { /* Toshiba NAND */ | 551 | } else if (maf_id == 0x98) { /* Toshiba NAND */ |
798 | get_toshiba_nand_para(denali); | 552 | get_toshiba_nand_para(denali); |
799 | } else if (denali->dev_info.wDeviceMaker == 0xAD) { /* Hynix NAND */ | 553 | } else if (maf_id == 0xAD) { /* Hynix NAND */ |
800 | get_hynix_nand_para(denali); | 554 | get_hynix_nand_para(denali, device_id); |
801 | } else { | ||
802 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
803 | } | 555 | } |
804 | 556 | ||
805 | nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" | 557 | nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" |
@@ -814,88 +566,20 @@ static uint16_t NAND_Read_Device_ID(struct denali_nand_info *denali) | |||
814 | ioread32(denali->flash_reg + RDWR_EN_HI_CNT), | 566 | ioread32(denali->flash_reg + RDWR_EN_HI_CNT), |
815 | ioread32(denali->flash_reg + CS_SETUP_CNT)); | 567 | ioread32(denali->flash_reg + CS_SETUP_CNT)); |
816 | 568 | ||
817 | denali->dev_info.wHWRevision = ioread32(denali->flash_reg + REVISION); | ||
818 | denali->dev_info.wHWFeatures = ioread32(denali->flash_reg + FEATURES); | ||
819 | |||
820 | denali->dev_info.wDeviceMainAreaSize = | ||
821 | ioread32(denali->flash_reg + DEVICE_MAIN_AREA_SIZE); | ||
822 | denali->dev_info.wDeviceSpareAreaSize = | ||
823 | ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE); | ||
824 | |||
825 | denali->dev_info.wPageDataSize = | ||
826 | ioread32(denali->flash_reg + LOGICAL_PAGE_DATA_SIZE); | ||
827 | |||
828 | /* Note: When using the Micon 4K NAND device, the controller will report | ||
829 | * Page Spare Size as 216 bytes. But Micron's Spec say it's 218 bytes. | ||
830 | * And if force set it to 218 bytes, the controller can not work | ||
831 | * correctly. So just let it be. But keep in mind that this bug may | ||
832 | * cause | ||
833 | * other problems in future. - Yunpeng 2008-10-10 | ||
834 | */ | ||
835 | denali->dev_info.wPageSpareSize = | ||
836 | ioread32(denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE); | ||
837 | |||
838 | denali->dev_info.wPagesPerBlock = ioread32(denali->flash_reg + PAGES_PER_BLOCK); | ||
839 | |||
840 | denali->dev_info.wPageSize = | ||
841 | denali->dev_info.wPageDataSize + denali->dev_info.wPageSpareSize; | ||
842 | denali->dev_info.wBlockSize = | ||
843 | denali->dev_info.wPageSize * denali->dev_info.wPagesPerBlock; | ||
844 | denali->dev_info.wBlockDataSize = | ||
845 | denali->dev_info.wPagesPerBlock * denali->dev_info.wPageDataSize; | ||
846 | |||
847 | denali->dev_info.wDeviceWidth = ioread32(denali->flash_reg + DEVICE_WIDTH); | ||
848 | denali->dev_info.wDeviceType = | ||
849 | ((ioread32(denali->flash_reg + DEVICE_WIDTH) > 0) ? 16 : 8); | ||
850 | |||
851 | denali->dev_info.wDevicesConnected = ioread32(denali->flash_reg + DEVICES_CONNECTED); | ||
852 | |||
853 | denali->dev_info.wSpareSkipBytes = | ||
854 | ioread32(denali->flash_reg + SPARE_AREA_SKIP_BYTES) * | ||
855 | denali->dev_info.wDevicesConnected; | ||
856 | |||
857 | denali->dev_info.nBitsInPageNumber = | ||
858 | ilog2(denali->dev_info.wPagesPerBlock); | ||
859 | denali->dev_info.nBitsInPageDataSize = | ||
860 | ilog2(denali->dev_info.wPageDataSize); | ||
861 | denali->dev_info.nBitsInBlockDataSize = | ||
862 | ilog2(denali->dev_info.wBlockDataSize); | ||
863 | |||
864 | set_ecc_config(denali); | ||
865 | |||
866 | no_of_planes = ioread32(denali->flash_reg + NUMBER_OF_PLANES) & | ||
867 | NUMBER_OF_PLANES__VALUE; | ||
868 | |||
869 | switch (no_of_planes) { | ||
870 | case 0: | ||
871 | case 1: | ||
872 | case 3: | ||
873 | case 7: | ||
874 | denali->dev_info.bPlaneNum = no_of_planes + 1; | ||
875 | break; | ||
876 | default: | ||
877 | status = FAIL; | ||
878 | break; | ||
879 | } | ||
880 | |||
881 | find_valid_banks(denali); | 569 | find_valid_banks(denali); |
882 | 570 | ||
883 | detect_partition_feature(denali); | 571 | detect_partition_feature(denali); |
884 | 572 | ||
885 | dump_device_info(denali); | ||
886 | |||
887 | /* If the user specified to override the default timings | 573 | /* If the user specified to override the default timings |
888 | * with a specific ONFI mode, we apply those changes here. | 574 | * with a specific ONFI mode, we apply those changes here. |
889 | */ | 575 | */ |
890 | if (onfi_timing_mode != NAND_DEFAULT_TIMINGS) | 576 | if (onfi_timing_mode != NAND_DEFAULT_TIMINGS) |
891 | { | 577 | nand_onfi_timing_set(denali, onfi_timing_mode); |
892 | NAND_ONFi_Timing_Mode(denali, onfi_timing_mode); | ||
893 | } | ||
894 | 578 | ||
895 | return status; | 579 | return status; |
896 | } | 580 | } |
897 | 581 | ||
898 | static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *denali, | 582 | static void denali_set_intr_modes(struct denali_nand_info *denali, |
899 | uint16_t INT_ENABLE) | 583 | uint16_t INT_ENABLE) |
900 | { | 584 | { |
901 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", | 585 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", |
@@ -912,7 +596,7 @@ static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *denali, | |||
912 | */ | 596 | */ |
913 | static inline bool is_flash_bank_valid(int flash_bank) | 597 | static inline bool is_flash_bank_valid(int flash_bank) |
914 | { | 598 | { |
915 | return (flash_bank >= 0 && flash_bank < 4); | 599 | return (flash_bank >= 0 && flash_bank < 4); |
916 | } | 600 | } |
917 | 601 | ||
918 | static void denali_irq_init(struct denali_nand_info *denali) | 602 | static void denali_irq_init(struct denali_nand_info *denali) |
@@ -920,7 +604,7 @@ static void denali_irq_init(struct denali_nand_info *denali) | |||
920 | uint32_t int_mask = 0; | 604 | uint32_t int_mask = 0; |
921 | 605 | ||
922 | /* Disable global interrupts */ | 606 | /* Disable global interrupts */ |
923 | NAND_LLD_Enable_Disable_Interrupts(denali, false); | 607 | denali_set_intr_modes(denali, false); |
924 | 608 | ||
925 | int_mask = DENALI_IRQ_ALL; | 609 | int_mask = DENALI_IRQ_ALL; |
926 | 610 | ||
@@ -935,11 +619,12 @@ static void denali_irq_init(struct denali_nand_info *denali) | |||
935 | 619 | ||
936 | static void denali_irq_cleanup(int irqnum, struct denali_nand_info *denali) | 620 | static void denali_irq_cleanup(int irqnum, struct denali_nand_info *denali) |
937 | { | 621 | { |
938 | NAND_LLD_Enable_Disable_Interrupts(denali, false); | 622 | denali_set_intr_modes(denali, false); |
939 | free_irq(irqnum, denali); | 623 | free_irq(irqnum, denali); |
940 | } | 624 | } |
941 | 625 | ||
942 | static void denali_irq_enable(struct denali_nand_info *denali, uint32_t int_mask) | 626 | static void denali_irq_enable(struct denali_nand_info *denali, |
627 | uint32_t int_mask) | ||
943 | { | 628 | { |
944 | denali_write32(int_mask, denali->flash_reg + INTR_EN0); | 629 | denali_write32(int_mask, denali->flash_reg + INTR_EN0); |
945 | denali_write32(int_mask, denali->flash_reg + INTR_EN1); | 630 | denali_write32(int_mask, denali->flash_reg + INTR_EN1); |
@@ -948,15 +633,16 @@ static void denali_irq_enable(struct denali_nand_info *denali, uint32_t int_mask | |||
948 | } | 633 | } |
949 | 634 | ||
950 | /* This function only returns when an interrupt that this driver cares about | 635 | /* This function only returns when an interrupt that this driver cares about |
951 | * occurs. This is to reduce the overhead of servicing interrupts | 636 | * occurs. This is to reduce the overhead of servicing interrupts |
952 | */ | 637 | */ |
953 | static inline uint32_t denali_irq_detected(struct denali_nand_info *denali) | 638 | static inline uint32_t denali_irq_detected(struct denali_nand_info *denali) |
954 | { | 639 | { |
955 | return (read_interrupt_status(denali) & DENALI_IRQ_ALL); | 640 | return read_interrupt_status(denali) & DENALI_IRQ_ALL; |
956 | } | 641 | } |
957 | 642 | ||
958 | /* Interrupts are cleared by writing a 1 to the appropriate status bit */ | 643 | /* Interrupts are cleared by writing a 1 to the appropriate status bit */ |
959 | static inline void clear_interrupt(struct denali_nand_info *denali, uint32_t irq_mask) | 644 | static inline void clear_interrupt(struct denali_nand_info *denali, |
645 | uint32_t irq_mask) | ||
960 | { | 646 | { |
961 | uint32_t intr_status_reg = 0; | 647 | uint32_t intr_status_reg = 0; |
962 | 648 | ||
@@ -995,17 +681,15 @@ static void print_irq_log(struct denali_nand_info *denali) | |||
995 | { | 681 | { |
996 | int i = 0; | 682 | int i = 0; |
997 | 683 | ||
998 | printk("ISR debug log index = %X\n", denali->idx); | 684 | printk(KERN_INFO "ISR debug log index = %X\n", denali->idx); |
999 | for (i = 0; i < 32; i++) | 685 | for (i = 0; i < 32; i++) |
1000 | { | 686 | printk(KERN_INFO "%08X: %08X\n", i, denali->irq_debug_array[i]); |
1001 | printk("%08X: %08X\n", i, denali->irq_debug_array[i]); | ||
1002 | } | ||
1003 | } | 687 | } |
1004 | #endif | 688 | #endif |
1005 | 689 | ||
1006 | /* This is the interrupt service routine. It handles all interrupts | 690 | /* This is the interrupt service routine. It handles all interrupts |
1007 | * sent to this device. Note that on CE4100, this is a shared | 691 | * sent to this device. Note that on CE4100, this is a shared |
1008 | * interrupt. | 692 | * interrupt. |
1009 | */ | 693 | */ |
1010 | static irqreturn_t denali_isr(int irq, void *dev_id) | 694 | static irqreturn_t denali_isr(int irq, void *dev_id) |
1011 | { | 695 | { |
@@ -1015,20 +699,20 @@ static irqreturn_t denali_isr(int irq, void *dev_id) | |||
1015 | 699 | ||
1016 | spin_lock(&denali->irq_lock); | 700 | spin_lock(&denali->irq_lock); |
1017 | 701 | ||
1018 | /* check to see if a valid NAND chip has | 702 | /* check to see if a valid NAND chip has |
1019 | * been selected. | 703 | * been selected. |
1020 | */ | 704 | */ |
1021 | if (is_flash_bank_valid(denali->flash_bank)) | 705 | if (is_flash_bank_valid(denali->flash_bank)) { |
1022 | { | 706 | /* check to see if controller generated |
1023 | /* check to see if controller generated | ||
1024 | * the interrupt, since this is a shared interrupt */ | 707 | * the interrupt, since this is a shared interrupt */ |
1025 | if ((irq_status = denali_irq_detected(denali)) != 0) | 708 | irq_status = denali_irq_detected(denali); |
1026 | { | 709 | if (irq_status != 0) { |
1027 | #if DEBUG_DENALI | 710 | #if DEBUG_DENALI |
1028 | denali->irq_debug_array[denali->idx++] = 0x10000000 | irq_status; | 711 | denali->irq_debug_array[denali->idx++] = |
712 | 0x10000000 | irq_status; | ||
1029 | denali->idx %= 32; | 713 | denali->idx %= 32; |
1030 | 714 | ||
1031 | printk("IRQ status = 0x%04x\n", irq_status); | 715 | printk(KERN_INFO "IRQ status = 0x%04x\n", irq_status); |
1032 | #endif | 716 | #endif |
1033 | /* handle interrupt */ | 717 | /* handle interrupt */ |
1034 | /* first acknowledge it */ | 718 | /* first acknowledge it */ |
@@ -1054,61 +738,62 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask) | |||
1054 | bool retry = false; | 738 | bool retry = false; |
1055 | unsigned long timeout = msecs_to_jiffies(1000); | 739 | unsigned long timeout = msecs_to_jiffies(1000); |
1056 | 740 | ||
1057 | do | 741 | do { |
1058 | { | ||
1059 | #if DEBUG_DENALI | 742 | #if DEBUG_DENALI |
1060 | printk("waiting for 0x%x\n", irq_mask); | 743 | printk(KERN_INFO "waiting for 0x%x\n", irq_mask); |
1061 | #endif | 744 | #endif |
1062 | comp_res = wait_for_completion_timeout(&denali->complete, timeout); | 745 | comp_res = |
746 | wait_for_completion_timeout(&denali->complete, timeout); | ||
1063 | spin_lock_irq(&denali->irq_lock); | 747 | spin_lock_irq(&denali->irq_lock); |
1064 | intr_status = denali->irq_status; | 748 | intr_status = denali->irq_status; |
1065 | 749 | ||
1066 | #if DEBUG_DENALI | 750 | #if DEBUG_DENALI |
1067 | denali->irq_debug_array[denali->idx++] = 0x20000000 | (irq_mask << 16) | intr_status; | 751 | denali->irq_debug_array[denali->idx++] = |
752 | 0x20000000 | (irq_mask << 16) | intr_status; | ||
1068 | denali->idx %= 32; | 753 | denali->idx %= 32; |
1069 | #endif | 754 | #endif |
1070 | 755 | ||
1071 | if (intr_status & irq_mask) | 756 | if (intr_status & irq_mask) { |
1072 | { | ||
1073 | denali->irq_status &= ~irq_mask; | 757 | denali->irq_status &= ~irq_mask; |
1074 | spin_unlock_irq(&denali->irq_lock); | 758 | spin_unlock_irq(&denali->irq_lock); |
1075 | #if DEBUG_DENALI | 759 | #if DEBUG_DENALI |
1076 | if (retry) printk("status on retry = 0x%x\n", intr_status); | 760 | if (retry) |
761 | printk(KERN_INFO "status on retry = 0x%x\n", | ||
762 | intr_status); | ||
1077 | #endif | 763 | #endif |
1078 | /* our interrupt was detected */ | 764 | /* our interrupt was detected */ |
1079 | break; | 765 | break; |
1080 | } | 766 | } else { |
1081 | else | 767 | /* these are not the interrupts you are looking for - |
1082 | { | 768 | * need to wait again */ |
1083 | /* these are not the interrupts you are looking for - | ||
1084 | need to wait again */ | ||
1085 | spin_unlock_irq(&denali->irq_lock); | 769 | spin_unlock_irq(&denali->irq_lock); |
1086 | #if DEBUG_DENALI | 770 | #if DEBUG_DENALI |
1087 | print_irq_log(denali); | 771 | print_irq_log(denali); |
1088 | printk("received irq nobody cared: irq_status = 0x%x," | 772 | printk(KERN_INFO "received irq nobody cared:" |
1089 | " irq_mask = 0x%x, timeout = %ld\n", intr_status, irq_mask, comp_res); | 773 | " irq_status = 0x%x, irq_mask = 0x%x," |
774 | " timeout = %ld\n", intr_status, | ||
775 | irq_mask, comp_res); | ||
1090 | #endif | 776 | #endif |
1091 | retry = true; | 777 | retry = true; |
1092 | } | 778 | } |
1093 | } while (comp_res != 0); | 779 | } while (comp_res != 0); |
1094 | 780 | ||
1095 | if (comp_res == 0) | 781 | if (comp_res == 0) { |
1096 | { | ||
1097 | /* timeout */ | 782 | /* timeout */ |
1098 | printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n", | 783 | printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n", |
1099 | intr_status, irq_mask); | 784 | intr_status, irq_mask); |
1100 | 785 | ||
1101 | intr_status = 0; | 786 | intr_status = 0; |
1102 | } | 787 | } |
1103 | return intr_status; | 788 | return intr_status; |
1104 | } | 789 | } |
1105 | 790 | ||
1106 | /* This helper function setups the registers for ECC and whether or not | 791 | /* This helper function setups the registers for ECC and whether or not |
1107 | the spare area will be transfered. */ | 792 | the spare area will be transfered. */ |
1108 | static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, | 793 | static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, |
1109 | bool transfer_spare) | 794 | bool transfer_spare) |
1110 | { | 795 | { |
1111 | int ecc_en_flag = 0, transfer_spare_flag = 0; | 796 | int ecc_en_flag = 0, transfer_spare_flag = 0; |
1112 | 797 | ||
1113 | /* set ECC, transfer spare bits if needed */ | 798 | /* set ECC, transfer spare bits if needed */ |
1114 | ecc_en_flag = ecc_en ? ECC_ENABLE__FLAG : 0; | 799 | ecc_en_flag = ecc_en ? ECC_ENABLE__FLAG : 0; |
@@ -1116,85 +801,85 @@ static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, | |||
1116 | 801 | ||
1117 | /* Enable spare area/ECC per user's request. */ | 802 | /* Enable spare area/ECC per user's request. */ |
1118 | denali_write32(ecc_en_flag, denali->flash_reg + ECC_ENABLE); | 803 | denali_write32(ecc_en_flag, denali->flash_reg + ECC_ENABLE); |
1119 | denali_write32(transfer_spare_flag, denali->flash_reg + TRANSFER_SPARE_REG); | 804 | denali_write32(transfer_spare_flag, |
805 | denali->flash_reg + TRANSFER_SPARE_REG); | ||
1120 | } | 806 | } |
1121 | 807 | ||
1122 | /* sends a pipeline command operation to the controller. See the Denali NAND | 808 | /* sends a pipeline command operation to the controller. See the Denali NAND |
1123 | controller's user guide for more information (section 4.2.3.6). | 809 | controller's user guide for more information (section 4.2.3.6). |
1124 | */ | 810 | */ |
1125 | static int denali_send_pipeline_cmd(struct denali_nand_info *denali, bool ecc_en, | 811 | static int denali_send_pipeline_cmd(struct denali_nand_info *denali, |
1126 | bool transfer_spare, int access_type, | 812 | bool ecc_en, |
1127 | int op) | 813 | bool transfer_spare, |
814 | int access_type, | ||
815 | int op) | ||
1128 | { | 816 | { |
1129 | int status = PASS; | 817 | int status = PASS; |
1130 | uint32_t addr = 0x0, cmd = 0x0, page_count = 1, irq_status = 0, | 818 | uint32_t addr = 0x0, cmd = 0x0, page_count = 1, irq_status = 0, |
1131 | irq_mask = 0; | 819 | irq_mask = 0; |
1132 | 820 | ||
1133 | if (op == DENALI_READ) irq_mask = INTR_STATUS0__LOAD_COMP; | 821 | if (op == DENALI_READ) |
1134 | else if (op == DENALI_WRITE) irq_mask = 0; | 822 | irq_mask = INTR_STATUS0__LOAD_COMP; |
1135 | else BUG(); | 823 | else if (op == DENALI_WRITE) |
824 | irq_mask = 0; | ||
825 | else | ||
826 | BUG(); | ||
1136 | 827 | ||
1137 | setup_ecc_for_xfer(denali, ecc_en, transfer_spare); | 828 | setup_ecc_for_xfer(denali, ecc_en, transfer_spare); |
1138 | 829 | ||
1139 | #if DEBUG_DENALI | 830 | #if DEBUG_DENALI |
1140 | spin_lock_irq(&denali->irq_lock); | 831 | spin_lock_irq(&denali->irq_lock); |
1141 | denali->irq_debug_array[denali->idx++] = 0x40000000 | ioread32(denali->flash_reg + ECC_ENABLE) | (access_type << 4); | 832 | denali->irq_debug_array[denali->idx++] = |
833 | 0x40000000 | ioread32(denali->flash_reg + ECC_ENABLE) | | ||
834 | (access_type << 4); | ||
1142 | denali->idx %= 32; | 835 | denali->idx %= 32; |
1143 | spin_unlock_irq(&denali->irq_lock); | 836 | spin_unlock_irq(&denali->irq_lock); |
1144 | #endif | 837 | #endif |
1145 | 838 | ||
1146 | 839 | ||
1147 | /* clear interrupts */ | 840 | /* clear interrupts */ |
1148 | clear_interrupts(denali); | 841 | clear_interrupts(denali); |
1149 | 842 | ||
1150 | addr = BANK(denali->flash_bank) | denali->page; | 843 | addr = BANK(denali->flash_bank) | denali->page; |
1151 | 844 | ||
1152 | if (op == DENALI_WRITE && access_type != SPARE_ACCESS) | 845 | if (op == DENALI_WRITE && access_type != SPARE_ACCESS) { |
1153 | { | 846 | cmd = MODE_01 | addr; |
1154 | cmd = MODE_01 | addr; | ||
1155 | denali_write32(cmd, denali->flash_mem); | 847 | denali_write32(cmd, denali->flash_mem); |
1156 | } | 848 | } else if (op == DENALI_WRITE && access_type == SPARE_ACCESS) { |
1157 | else if (op == DENALI_WRITE && access_type == SPARE_ACCESS) | ||
1158 | { | ||
1159 | /* read spare area */ | 849 | /* read spare area */ |
1160 | cmd = MODE_10 | addr; | 850 | cmd = MODE_10 | addr; |
1161 | index_addr(denali, (uint32_t)cmd, access_type); | 851 | index_addr(denali, (uint32_t)cmd, access_type); |
1162 | 852 | ||
1163 | cmd = MODE_01 | addr; | 853 | cmd = MODE_01 | addr; |
1164 | denali_write32(cmd, denali->flash_mem); | 854 | denali_write32(cmd, denali->flash_mem); |
1165 | } | 855 | } else if (op == DENALI_READ) { |
1166 | else if (op == DENALI_READ) | ||
1167 | { | ||
1168 | /* setup page read request for access type */ | 856 | /* setup page read request for access type */ |
1169 | cmd = MODE_10 | addr; | 857 | cmd = MODE_10 | addr; |
1170 | index_addr(denali, (uint32_t)cmd, access_type); | 858 | index_addr(denali, (uint32_t)cmd, access_type); |
1171 | 859 | ||
1172 | /* page 33 of the NAND controller spec indicates we should not | 860 | /* page 33 of the NAND controller spec indicates we should not |
1173 | use the pipeline commands in Spare area only mode. So we | 861 | use the pipeline commands in Spare area only mode. So we |
1174 | don't. | 862 | don't. |
1175 | */ | 863 | */ |
1176 | if (access_type == SPARE_ACCESS) | 864 | if (access_type == SPARE_ACCESS) { |
1177 | { | ||
1178 | cmd = MODE_01 | addr; | 865 | cmd = MODE_01 | addr; |
1179 | denali_write32(cmd, denali->flash_mem); | 866 | denali_write32(cmd, denali->flash_mem); |
1180 | } | 867 | } else { |
1181 | else | 868 | index_addr(denali, (uint32_t)cmd, |
1182 | { | 869 | 0x2000 | op | page_count); |
1183 | index_addr(denali, (uint32_t)cmd, 0x2000 | op | page_count); | 870 | |
1184 | 871 | /* wait for command to be accepted | |
1185 | /* wait for command to be accepted | 872 | * can always use status0 bit as the |
1186 | * can always use status0 bit as the mask is identical for each | 873 | * mask is identical for each |
1187 | * bank. */ | 874 | * bank. */ |
1188 | irq_status = wait_for_irq(denali, irq_mask); | 875 | irq_status = wait_for_irq(denali, irq_mask); |
1189 | 876 | ||
1190 | if (irq_status == 0) | 877 | if (irq_status == 0) { |
1191 | { | ||
1192 | printk(KERN_ERR "cmd, page, addr on timeout " | 878 | printk(KERN_ERR "cmd, page, addr on timeout " |
1193 | "(0x%x, 0x%x, 0x%x)\n", cmd, denali->page, addr); | 879 | "(0x%x, 0x%x, 0x%x)\n", cmd, |
880 | denali->page, addr); | ||
1194 | status = FAIL; | 881 | status = FAIL; |
1195 | } | 882 | } else { |
1196 | else | ||
1197 | { | ||
1198 | cmd = MODE_01 | addr; | 883 | cmd = MODE_01 | addr; |
1199 | denali_write32(cmd, denali->flash_mem); | 884 | denali_write32(cmd, denali->flash_mem); |
1200 | } | 885 | } |
@@ -1204,36 +889,35 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, bool ecc_en | |||
1204 | } | 889 | } |
1205 | 890 | ||
1206 | /* helper function that simply writes a buffer to the flash */ | 891 | /* helper function that simply writes a buffer to the flash */ |
1207 | static int write_data_to_flash_mem(struct denali_nand_info *denali, const uint8_t *buf, | 892 | static int write_data_to_flash_mem(struct denali_nand_info *denali, |
1208 | int len) | 893 | const uint8_t *buf, |
894 | int len) | ||
1209 | { | 895 | { |
1210 | uint32_t i = 0, *buf32; | 896 | uint32_t i = 0, *buf32; |
1211 | 897 | ||
1212 | /* verify that the len is a multiple of 4. see comment in | 898 | /* verify that the len is a multiple of 4. see comment in |
1213 | * read_data_from_flash_mem() */ | 899 | * read_data_from_flash_mem() */ |
1214 | BUG_ON((len % 4) != 0); | 900 | BUG_ON((len % 4) != 0); |
1215 | 901 | ||
1216 | /* write the data to the flash memory */ | 902 | /* write the data to the flash memory */ |
1217 | buf32 = (uint32_t *)buf; | 903 | buf32 = (uint32_t *)buf; |
1218 | for (i = 0; i < len / 4; i++) | 904 | for (i = 0; i < len / 4; i++) |
1219 | { | ||
1220 | denali_write32(*buf32++, denali->flash_mem + 0x10); | 905 | denali_write32(*buf32++, denali->flash_mem + 0x10); |
1221 | } | 906 | return i*4; /* intent is to return the number of bytes read */ |
1222 | return i*4; /* intent is to return the number of bytes read */ | ||
1223 | } | 907 | } |
1224 | 908 | ||
1225 | /* helper function that simply reads a buffer from the flash */ | 909 | /* helper function that simply reads a buffer from the flash */ |
1226 | static int read_data_from_flash_mem(struct denali_nand_info *denali, uint8_t *buf, | 910 | static int read_data_from_flash_mem(struct denali_nand_info *denali, |
1227 | int len) | 911 | uint8_t *buf, |
912 | int len) | ||
1228 | { | 913 | { |
1229 | uint32_t i = 0, *buf32; | 914 | uint32_t i = 0, *buf32; |
1230 | 915 | ||
1231 | /* we assume that len will be a multiple of 4, if not | 916 | /* we assume that len will be a multiple of 4, if not |
1232 | * it would be nice to know about it ASAP rather than | 917 | * it would be nice to know about it ASAP rather than |
1233 | * have random failures... | 918 | * have random failures... |
1234 | * | 919 | * This assumption is based on the fact that this |
1235 | * This assumption is based on the fact that this | 920 | * function is designed to be used to read flash pages, |
1236 | * function is designed to be used to read flash pages, | ||
1237 | * which are typically multiples of 4... | 921 | * which are typically multiples of 4... |
1238 | */ | 922 | */ |
1239 | 923 | ||
@@ -1242,10 +926,8 @@ static int read_data_from_flash_mem(struct denali_nand_info *denali, uint8_t *bu | |||
1242 | /* transfer the data from the flash */ | 926 | /* transfer the data from the flash */ |
1243 | buf32 = (uint32_t *)buf; | 927 | buf32 = (uint32_t *)buf; |
1244 | for (i = 0; i < len / 4; i++) | 928 | for (i = 0; i < len / 4; i++) |
1245 | { | ||
1246 | *buf32++ = ioread32(denali->flash_mem + 0x10); | 929 | *buf32++ = ioread32(denali->flash_mem + 0x10); |
1247 | } | 930 | return i*4; /* intent is to return the number of bytes read */ |
1248 | return i*4; /* intent is to return the number of bytes read */ | ||
1249 | } | 931 | } |
1250 | 932 | ||
1251 | /* writes OOB data to the device */ | 933 | /* writes OOB data to the device */ |
@@ -1253,38 +935,35 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | |||
1253 | { | 935 | { |
1254 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 936 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1255 | uint32_t irq_status = 0; | 937 | uint32_t irq_status = 0; |
1256 | uint32_t irq_mask = INTR_STATUS0__PROGRAM_COMP | | 938 | uint32_t irq_mask = INTR_STATUS0__PROGRAM_COMP | |
1257 | INTR_STATUS0__PROGRAM_FAIL; | 939 | INTR_STATUS0__PROGRAM_FAIL; |
1258 | int status = 0; | 940 | int status = 0; |
1259 | 941 | ||
1260 | denali->page = page; | 942 | denali->page = page; |
1261 | 943 | ||
1262 | if (denali_send_pipeline_cmd(denali, false, false, SPARE_ACCESS, | 944 | if (denali_send_pipeline_cmd(denali, false, false, SPARE_ACCESS, |
1263 | DENALI_WRITE) == PASS) | 945 | DENALI_WRITE) == PASS) { |
1264 | { | ||
1265 | write_data_to_flash_mem(denali, buf, mtd->oobsize); | 946 | write_data_to_flash_mem(denali, buf, mtd->oobsize); |
1266 | 947 | ||
1267 | #if DEBUG_DENALI | 948 | #if DEBUG_DENALI |
1268 | spin_lock_irq(&denali->irq_lock); | 949 | spin_lock_irq(&denali->irq_lock); |
1269 | denali->irq_debug_array[denali->idx++] = 0x80000000 | mtd->oobsize; | 950 | denali->irq_debug_array[denali->idx++] = |
951 | 0x80000000 | mtd->oobsize; | ||
1270 | denali->idx %= 32; | 952 | denali->idx %= 32; |
1271 | spin_unlock_irq(&denali->irq_lock); | 953 | spin_unlock_irq(&denali->irq_lock); |
1272 | #endif | 954 | #endif |
1273 | 955 | ||
1274 | 956 | ||
1275 | /* wait for operation to complete */ | 957 | /* wait for operation to complete */ |
1276 | irq_status = wait_for_irq(denali, irq_mask); | 958 | irq_status = wait_for_irq(denali, irq_mask); |
1277 | 959 | ||
1278 | if (irq_status == 0) | 960 | if (irq_status == 0) { |
1279 | { | ||
1280 | printk(KERN_ERR "OOB write failed\n"); | 961 | printk(KERN_ERR "OOB write failed\n"); |
1281 | status = -EIO; | 962 | status = -EIO; |
1282 | } | 963 | } |
1283 | } | 964 | } else { |
1284 | else | ||
1285 | { | ||
1286 | printk(KERN_ERR "unable to send pipeline command\n"); | 965 | printk(KERN_ERR "unable to send pipeline command\n"); |
1287 | status = -EIO; | 966 | status = -EIO; |
1288 | } | 967 | } |
1289 | return status; | 968 | return status; |
1290 | } | 969 | } |
@@ -1293,60 +972,56 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | |||
1293 | static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) | 972 | static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) |
1294 | { | 973 | { |
1295 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 974 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1296 | uint32_t irq_mask = INTR_STATUS0__LOAD_COMP, irq_status = 0, addr = 0x0, cmd = 0x0; | 975 | uint32_t irq_mask = INTR_STATUS0__LOAD_COMP, |
976 | irq_status = 0, addr = 0x0, cmd = 0x0; | ||
1297 | 977 | ||
1298 | denali->page = page; | 978 | denali->page = page; |
1299 | 979 | ||
1300 | #if DEBUG_DENALI | 980 | #if DEBUG_DENALI |
1301 | printk("read_oob %d\n", page); | 981 | printk(KERN_INFO "read_oob %d\n", page); |
1302 | #endif | 982 | #endif |
1303 | if (denali_send_pipeline_cmd(denali, false, true, SPARE_ACCESS, | 983 | if (denali_send_pipeline_cmd(denali, false, true, SPARE_ACCESS, |
1304 | DENALI_READ) == PASS) | 984 | DENALI_READ) == PASS) { |
1305 | { | 985 | read_data_from_flash_mem(denali, buf, mtd->oobsize); |
1306 | read_data_from_flash_mem(denali, buf, mtd->oobsize); | ||
1307 | 986 | ||
1308 | /* wait for command to be accepted | 987 | /* wait for command to be accepted |
1309 | * can always use status0 bit as the mask is identical for each | 988 | * can always use status0 bit as the mask is identical for each |
1310 | * bank. */ | 989 | * bank. */ |
1311 | irq_status = wait_for_irq(denali, irq_mask); | 990 | irq_status = wait_for_irq(denali, irq_mask); |
1312 | 991 | ||
1313 | if (irq_status == 0) | 992 | if (irq_status == 0) |
1314 | { | 993 | printk(KERN_ERR "page on OOB timeout %d\n", |
1315 | printk(KERN_ERR "page on OOB timeout %d\n", denali->page); | 994 | denali->page); |
1316 | } | ||
1317 | 995 | ||
1318 | /* We set the device back to MAIN_ACCESS here as I observed | 996 | /* We set the device back to MAIN_ACCESS here as I observed |
1319 | * instability with the controller if you do a block erase | 997 | * instability with the controller if you do a block erase |
1320 | * and the last transaction was a SPARE_ACCESS. Block erase | 998 | * and the last transaction was a SPARE_ACCESS. Block erase |
1321 | * is reliable (according to the MTD test infrastructure) | 999 | * is reliable (according to the MTD test infrastructure) |
1322 | * if you are in MAIN_ACCESS. | 1000 | * if you are in MAIN_ACCESS. |
1323 | */ | 1001 | */ |
1324 | addr = BANK(denali->flash_bank) | denali->page; | 1002 | addr = BANK(denali->flash_bank) | denali->page; |
1325 | cmd = MODE_10 | addr; | 1003 | cmd = MODE_10 | addr; |
1326 | index_addr(denali, (uint32_t)cmd, MAIN_ACCESS); | 1004 | index_addr(denali, (uint32_t)cmd, MAIN_ACCESS); |
1327 | 1005 | ||
1328 | #if DEBUG_DENALI | 1006 | #if DEBUG_DENALI |
1329 | spin_lock_irq(&denali->irq_lock); | 1007 | spin_lock_irq(&denali->irq_lock); |
1330 | denali->irq_debug_array[denali->idx++] = 0x60000000 | mtd->oobsize; | 1008 | denali->irq_debug_array[denali->idx++] = |
1009 | 0x60000000 | mtd->oobsize; | ||
1331 | denali->idx %= 32; | 1010 | denali->idx %= 32; |
1332 | spin_unlock_irq(&denali->irq_lock); | 1011 | spin_unlock_irq(&denali->irq_lock); |
1333 | #endif | 1012 | #endif |
1334 | } | 1013 | } |
1335 | } | 1014 | } |
1336 | 1015 | ||
1337 | /* this function examines buffers to see if they contain data that | 1016 | /* this function examines buffers to see if they contain data that |
1338 | * indicate that the buffer is part of an erased region of flash. | 1017 | * indicate that the buffer is part of an erased region of flash. |
1339 | */ | 1018 | */ |
1340 | bool is_erased(uint8_t *buf, int len) | 1019 | bool is_erased(uint8_t *buf, int len) |
1341 | { | 1020 | { |
1342 | int i = 0; | 1021 | int i = 0; |
1343 | for (i = 0; i < len; i++) | 1022 | for (i = 0; i < len; i++) |
1344 | { | ||
1345 | if (buf[i] != 0xFF) | 1023 | if (buf[i] != 0xFF) |
1346 | { | ||
1347 | return false; | 1024 | return false; |
1348 | } | ||
1349 | } | ||
1350 | return true; | 1025 | return true; |
1351 | } | 1026 | } |
1352 | #define ECC_SECTOR_SIZE 512 | 1027 | #define ECC_SECTOR_SIZE 512 |
@@ -1358,65 +1033,59 @@ bool is_erased(uint8_t *buf, int len) | |||
1358 | #define ECC_ERR_DEVICE(x) ((x) & ERR_CORRECTION_INFO__DEVICE_NR >> 8) | 1033 | #define ECC_ERR_DEVICE(x) ((x) & ERR_CORRECTION_INFO__DEVICE_NR >> 8) |
1359 | #define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO) | 1034 | #define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO) |
1360 | 1035 | ||
1361 | static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, | 1036 | static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, |
1362 | uint8_t *oobbuf, uint32_t irq_status) | 1037 | uint8_t *oobbuf, uint32_t irq_status) |
1363 | { | 1038 | { |
1364 | bool check_erased_page = false; | 1039 | bool check_erased_page = false; |
1365 | 1040 | ||
1366 | if (irq_status & INTR_STATUS0__ECC_ERR) | 1041 | if (irq_status & INTR_STATUS0__ECC_ERR) { |
1367 | { | ||
1368 | /* read the ECC errors. we'll ignore them for now */ | 1042 | /* read the ECC errors. we'll ignore them for now */ |
1369 | uint32_t err_address = 0, err_correction_info = 0; | 1043 | uint32_t err_address = 0, err_correction_info = 0; |
1370 | uint32_t err_byte = 0, err_sector = 0, err_device = 0; | 1044 | uint32_t err_byte = 0, err_sector = 0, err_device = 0; |
1371 | uint32_t err_correction_value = 0; | 1045 | uint32_t err_correction_value = 0; |
1372 | 1046 | ||
1373 | do | 1047 | do { |
1374 | { | 1048 | err_address = ioread32(denali->flash_reg + |
1375 | err_address = ioread32(denali->flash_reg + | ||
1376 | ECC_ERROR_ADDRESS); | 1049 | ECC_ERROR_ADDRESS); |
1377 | err_sector = ECC_SECTOR(err_address); | 1050 | err_sector = ECC_SECTOR(err_address); |
1378 | err_byte = ECC_BYTE(err_address); | 1051 | err_byte = ECC_BYTE(err_address); |
1379 | 1052 | ||
1380 | 1053 | ||
1381 | err_correction_info = ioread32(denali->flash_reg + | 1054 | err_correction_info = ioread32(denali->flash_reg + |
1382 | ERR_CORRECTION_INFO); | 1055 | ERR_CORRECTION_INFO); |
1383 | err_correction_value = | 1056 | err_correction_value = |
1384 | ECC_CORRECTION_VALUE(err_correction_info); | 1057 | ECC_CORRECTION_VALUE(err_correction_info); |
1385 | err_device = ECC_ERR_DEVICE(err_correction_info); | 1058 | err_device = ECC_ERR_DEVICE(err_correction_info); |
1386 | 1059 | ||
1387 | if (ECC_ERROR_CORRECTABLE(err_correction_info)) | 1060 | if (ECC_ERROR_CORRECTABLE(err_correction_info)) { |
1388 | { | ||
1389 | /* offset in our buffer is computed as: | 1061 | /* offset in our buffer is computed as: |
1390 | sector number * sector size + offset in | 1062 | sector number * sector size + offset in |
1391 | sector | 1063 | sector |
1392 | */ | 1064 | */ |
1393 | int offset = err_sector * ECC_SECTOR_SIZE + | 1065 | int offset = err_sector * ECC_SECTOR_SIZE + |
1394 | err_byte; | 1066 | err_byte; |
1395 | if (offset < denali->mtd.writesize) | 1067 | if (offset < denali->mtd.writesize) { |
1396 | { | ||
1397 | /* correct the ECC error */ | 1068 | /* correct the ECC error */ |
1398 | buf[offset] ^= err_correction_value; | 1069 | buf[offset] ^= err_correction_value; |
1399 | denali->mtd.ecc_stats.corrected++; | 1070 | denali->mtd.ecc_stats.corrected++; |
1400 | } | 1071 | } else { |
1401 | else | ||
1402 | { | ||
1403 | /* bummer, couldn't correct the error */ | 1072 | /* bummer, couldn't correct the error */ |
1404 | printk(KERN_ERR "ECC offset invalid\n"); | 1073 | printk(KERN_ERR "ECC offset invalid\n"); |
1405 | denali->mtd.ecc_stats.failed++; | 1074 | denali->mtd.ecc_stats.failed++; |
1406 | } | 1075 | } |
1407 | } | 1076 | } else { |
1408 | else | 1077 | /* if the error is not correctable, need to |
1409 | { | 1078 | * look at the page to see if it is an erased |
1410 | /* if the error is not correctable, need to | 1079 | * page. if so, then it's not a real ECC error |
1411 | * look at the page to see if it is an erased page. | 1080 | * */ |
1412 | * if so, then it's not a real ECC error */ | ||
1413 | check_erased_page = true; | 1081 | check_erased_page = true; |
1414 | } | 1082 | } |
1415 | 1083 | ||
1416 | #if DEBUG_DENALI | 1084 | #if DEBUG_DENALI |
1417 | printk("Detected ECC error in page %d: err_addr = 0x%08x," | 1085 | printk(KERN_INFO "Detected ECC error in page %d:" |
1418 | " info to fix is 0x%08x\n", denali->page, err_address, | 1086 | " err_addr = 0x%08x, info to fix is" |
1419 | err_correction_info); | 1087 | " 0x%08x\n", denali->page, err_address, |
1088 | err_correction_info); | ||
1420 | #endif | 1089 | #endif |
1421 | } while (!ECC_LAST_ERR(err_correction_info)); | 1090 | } while (!ECC_LAST_ERR(err_correction_info)); |
1422 | } | 1091 | } |
@@ -1428,7 +1097,8 @@ static void denali_enable_dma(struct denali_nand_info *denali, bool en) | |||
1428 | { | 1097 | { |
1429 | uint32_t reg_val = 0x0; | 1098 | uint32_t reg_val = 0x0; |
1430 | 1099 | ||
1431 | if (en) reg_val = DMA_ENABLE__FLAG; | 1100 | if (en) |
1101 | reg_val = DMA_ENABLE__FLAG; | ||
1432 | 1102 | ||
1433 | denali_write32(reg_val, denali->flash_reg + DMA_ENABLE); | 1103 | denali_write32(reg_val, denali->flash_reg + DMA_ENABLE); |
1434 | ioread32(denali->flash_reg + DMA_ENABLE); | 1104 | ioread32(denali->flash_reg + DMA_ENABLE); |
@@ -1458,9 +1128,9 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op) | |||
1458 | index_addr(denali, mode | 0x14000, 0x2400); | 1128 | index_addr(denali, mode | 0x14000, 0x2400); |
1459 | } | 1129 | } |
1460 | 1130 | ||
1461 | /* writes a page. user specifies type, and this function handles the | 1131 | /* writes a page. user specifies type, and this function handles the |
1462 | configuration details. */ | 1132 | configuration details. */ |
1463 | static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | 1133 | static void write_page(struct mtd_info *mtd, struct nand_chip *chip, |
1464 | const uint8_t *buf, bool raw_xfer) | 1134 | const uint8_t *buf, bool raw_xfer) |
1465 | { | 1135 | { |
1466 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1136 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
@@ -1470,7 +1140,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1470 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; | 1140 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; |
1471 | 1141 | ||
1472 | uint32_t irq_status = 0; | 1142 | uint32_t irq_status = 0; |
1473 | uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP | | 1143 | uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP | |
1474 | INTR_STATUS0__PROGRAM_FAIL; | 1144 | INTR_STATUS0__PROGRAM_FAIL; |
1475 | 1145 | ||
1476 | /* if it is a raw xfer, we want to disable ecc, and send | 1146 | /* if it is a raw xfer, we want to disable ecc, and send |
@@ -1483,74 +1153,73 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1483 | /* copy buffer into DMA buffer */ | 1153 | /* copy buffer into DMA buffer */ |
1484 | memcpy(denali->buf.buf, buf, mtd->writesize); | 1154 | memcpy(denali->buf.buf, buf, mtd->writesize); |
1485 | 1155 | ||
1486 | if (raw_xfer) | 1156 | if (raw_xfer) { |
1487 | { | ||
1488 | /* transfer the data to the spare area */ | 1157 | /* transfer the data to the spare area */ |
1489 | memcpy(denali->buf.buf + mtd->writesize, | 1158 | memcpy(denali->buf.buf + mtd->writesize, |
1490 | chip->oob_poi, | 1159 | chip->oob_poi, |
1491 | mtd->oobsize); | 1160 | mtd->oobsize); |
1492 | } | 1161 | } |
1493 | 1162 | ||
1494 | pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_TODEVICE); | 1163 | pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_TODEVICE); |
1495 | 1164 | ||
1496 | clear_interrupts(denali); | 1165 | clear_interrupts(denali); |
1497 | denali_enable_dma(denali, true); | 1166 | denali_enable_dma(denali, true); |
1498 | 1167 | ||
1499 | denali_setup_dma(denali, DENALI_WRITE); | 1168 | denali_setup_dma(denali, DENALI_WRITE); |
1500 | 1169 | ||
1501 | /* wait for operation to complete */ | 1170 | /* wait for operation to complete */ |
1502 | irq_status = wait_for_irq(denali, irq_mask); | 1171 | irq_status = wait_for_irq(denali, irq_mask); |
1503 | 1172 | ||
1504 | if (irq_status == 0) | 1173 | if (irq_status == 0) { |
1505 | { | 1174 | printk(KERN_ERR "timeout on write_page" |
1506 | printk(KERN_ERR "timeout on write_page (type = %d)\n", raw_xfer); | 1175 | " (type = %d)\n", raw_xfer); |
1507 | denali->status = | 1176 | denali->status = |
1508 | (irq_status & INTR_STATUS0__PROGRAM_FAIL) ? NAND_STATUS_FAIL : | 1177 | (irq_status & INTR_STATUS0__PROGRAM_FAIL) ? |
1509 | PASS; | 1178 | NAND_STATUS_FAIL : PASS; |
1510 | } | 1179 | } |
1511 | 1180 | ||
1512 | denali_enable_dma(denali, false); | 1181 | denali_enable_dma(denali, false); |
1513 | pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_TODEVICE); | 1182 | pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_TODEVICE); |
1514 | } | 1183 | } |
1515 | 1184 | ||
1516 | /* NAND core entry points */ | 1185 | /* NAND core entry points */ |
1517 | 1186 | ||
1518 | /* this is the callback that the NAND core calls to write a page. Since | 1187 | /* this is the callback that the NAND core calls to write a page. Since |
1519 | writing a page with ECC or without is similar, all the work is done | 1188 | writing a page with ECC or without is similar, all the work is done |
1520 | by write_page above. */ | 1189 | by write_page above. */ |
1521 | static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, | 1190 | static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
1522 | const uint8_t *buf) | 1191 | const uint8_t *buf) |
1523 | { | 1192 | { |
1524 | /* for regular page writes, we let HW handle all the ECC | 1193 | /* for regular page writes, we let HW handle all the ECC |
1525 | * data written to the device. */ | 1194 | * data written to the device. */ |
1526 | write_page(mtd, chip, buf, false); | 1195 | write_page(mtd, chip, buf, false); |
1527 | } | 1196 | } |
1528 | 1197 | ||
1529 | /* This is the callback that the NAND core calls to write a page without ECC. | 1198 | /* This is the callback that the NAND core calls to write a page without ECC. |
1530 | raw access is similiar to ECC page writes, so all the work is done in the | 1199 | raw access is similiar to ECC page writes, so all the work is done in the |
1531 | write_page() function above. | 1200 | write_page() function above. |
1532 | */ | 1201 | */ |
1533 | static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1202 | static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
1534 | const uint8_t *buf) | 1203 | const uint8_t *buf) |
1535 | { | 1204 | { |
1536 | /* for raw page writes, we want to disable ECC and simply write | 1205 | /* for raw page writes, we want to disable ECC and simply write |
1537 | whatever data is in the buffer. */ | 1206 | whatever data is in the buffer. */ |
1538 | write_page(mtd, chip, buf, true); | 1207 | write_page(mtd, chip, buf, true); |
1539 | } | 1208 | } |
1540 | 1209 | ||
1541 | static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip, | 1210 | static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip, |
1542 | int page) | 1211 | int page) |
1543 | { | 1212 | { |
1544 | return write_oob_data(mtd, chip->oob_poi, page); | 1213 | return write_oob_data(mtd, chip->oob_poi, page); |
1545 | } | 1214 | } |
1546 | 1215 | ||
1547 | static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | 1216 | static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, |
1548 | int page, int sndcmd) | 1217 | int page, int sndcmd) |
1549 | { | 1218 | { |
1550 | read_oob_data(mtd, chip->oob_poi, page); | 1219 | read_oob_data(mtd, chip->oob_poi, page); |
1551 | 1220 | ||
1552 | return 0; /* notify NAND core to send command to | 1221 | return 0; /* notify NAND core to send command to |
1553 | * NAND device. */ | 1222 | NAND device. */ |
1554 | } | 1223 | } |
1555 | 1224 | ||
1556 | static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | 1225 | static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
@@ -1563,7 +1232,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1563 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; | 1232 | size_t size = denali->mtd.writesize + denali->mtd.oobsize; |
1564 | 1233 | ||
1565 | uint32_t irq_status = 0; | 1234 | uint32_t irq_status = 0; |
1566 | uint32_t irq_mask = INTR_STATUS0__ECC_TRANSACTION_DONE | | 1235 | uint32_t irq_mask = INTR_STATUS0__ECC_TRANSACTION_DONE | |
1567 | INTR_STATUS0__ECC_ERR; | 1236 | INTR_STATUS0__ECC_ERR; |
1568 | bool check_erased_page = false; | 1237 | bool check_erased_page = false; |
1569 | 1238 | ||
@@ -1581,26 +1250,20 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1581 | pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE); | 1250 | pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE); |
1582 | 1251 | ||
1583 | memcpy(buf, denali->buf.buf, mtd->writesize); | 1252 | memcpy(buf, denali->buf.buf, mtd->writesize); |
1584 | 1253 | ||
1585 | check_erased_page = handle_ecc(denali, buf, chip->oob_poi, irq_status); | 1254 | check_erased_page = handle_ecc(denali, buf, chip->oob_poi, irq_status); |
1586 | denali_enable_dma(denali, false); | 1255 | denali_enable_dma(denali, false); |
1587 | 1256 | ||
1588 | if (check_erased_page) | 1257 | if (check_erased_page) { |
1589 | { | ||
1590 | read_oob_data(&denali->mtd, chip->oob_poi, denali->page); | 1258 | read_oob_data(&denali->mtd, chip->oob_poi, denali->page); |
1591 | 1259 | ||
1592 | /* check ECC failures that may have occurred on erased pages */ | 1260 | /* check ECC failures that may have occurred on erased pages */ |
1593 | if (check_erased_page) | 1261 | if (check_erased_page) { |
1594 | { | ||
1595 | if (!is_erased(buf, denali->mtd.writesize)) | 1262 | if (!is_erased(buf, denali->mtd.writesize)) |
1596 | { | ||
1597 | denali->mtd.ecc_stats.failed++; | 1263 | denali->mtd.ecc_stats.failed++; |
1598 | } | ||
1599 | if (!is_erased(buf, denali->mtd.oobsize)) | 1264 | if (!is_erased(buf, denali->mtd.oobsize)) |
1600 | { | ||
1601 | denali->mtd.ecc_stats.failed++; | 1265 | denali->mtd.ecc_stats.failed++; |
1602 | } | 1266 | } |
1603 | } | ||
1604 | } | 1267 | } |
1605 | return 0; | 1268 | return 0; |
1606 | } | 1269 | } |
@@ -1616,7 +1279,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1616 | 1279 | ||
1617 | uint32_t irq_status = 0; | 1280 | uint32_t irq_status = 0; |
1618 | uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP; | 1281 | uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP; |
1619 | 1282 | ||
1620 | setup_ecc_for_xfer(denali, false, true); | 1283 | setup_ecc_for_xfer(denali, false, true); |
1621 | denali_enable_dma(denali, true); | 1284 | denali_enable_dma(denali, true); |
1622 | 1285 | ||
@@ -1644,12 +1307,10 @@ static uint8_t denali_read_byte(struct mtd_info *mtd) | |||
1644 | uint8_t result = 0xff; | 1307 | uint8_t result = 0xff; |
1645 | 1308 | ||
1646 | if (denali->buf.head < denali->buf.tail) | 1309 | if (denali->buf.head < denali->buf.tail) |
1647 | { | ||
1648 | result = denali->buf.buf[denali->buf.head++]; | 1310 | result = denali->buf.buf[denali->buf.head++]; |
1649 | } | ||
1650 | 1311 | ||
1651 | #if DEBUG_DENALI | 1312 | #if DEBUG_DENALI |
1652 | printk("read byte -> 0x%02x\n", result); | 1313 | printk(KERN_INFO "read byte -> 0x%02x\n", result); |
1653 | #endif | 1314 | #endif |
1654 | return result; | 1315 | return result; |
1655 | } | 1316 | } |
@@ -1658,7 +1319,7 @@ static void denali_select_chip(struct mtd_info *mtd, int chip) | |||
1658 | { | 1319 | { |
1659 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1320 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1660 | #if DEBUG_DENALI | 1321 | #if DEBUG_DENALI |
1661 | printk("denali select chip %d\n", chip); | 1322 | printk(KERN_INFO "denali select chip %d\n", chip); |
1662 | #endif | 1323 | #endif |
1663 | spin_lock_irq(&denali->irq_lock); | 1324 | spin_lock_irq(&denali->irq_lock); |
1664 | denali->flash_bank = chip; | 1325 | denali->flash_bank = chip; |
@@ -1672,7 +1333,7 @@ static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) | |||
1672 | denali->status = 0; | 1333 | denali->status = 0; |
1673 | 1334 | ||
1674 | #if DEBUG_DENALI | 1335 | #if DEBUG_DENALI |
1675 | printk("waitfunc %d\n", status); | 1336 | printk(KERN_INFO "waitfunc %d\n", status); |
1676 | #endif | 1337 | #endif |
1677 | return status; | 1338 | return status; |
1678 | } | 1339 | } |
@@ -1684,76 +1345,74 @@ static void denali_erase(struct mtd_info *mtd, int page) | |||
1684 | uint32_t cmd = 0x0, irq_status = 0; | 1345 | uint32_t cmd = 0x0, irq_status = 0; |
1685 | 1346 | ||
1686 | #if DEBUG_DENALI | 1347 | #if DEBUG_DENALI |
1687 | printk("erase page: %d\n", page); | 1348 | printk(KERN_INFO "erase page: %d\n", page); |
1688 | #endif | 1349 | #endif |
1689 | /* clear interrupts */ | 1350 | /* clear interrupts */ |
1690 | clear_interrupts(denali); | 1351 | clear_interrupts(denali); |
1691 | 1352 | ||
1692 | /* setup page read request for access type */ | 1353 | /* setup page read request for access type */ |
1693 | cmd = MODE_10 | BANK(denali->flash_bank) | page; | 1354 | cmd = MODE_10 | BANK(denali->flash_bank) | page; |
1694 | index_addr(denali, (uint32_t)cmd, 0x1); | 1355 | index_addr(denali, (uint32_t)cmd, 0x1); |
1695 | 1356 | ||
1696 | /* wait for erase to complete or failure to occur */ | 1357 | /* wait for erase to complete or failure to occur */ |
1697 | irq_status = wait_for_irq(denali, INTR_STATUS0__ERASE_COMP | | 1358 | irq_status = wait_for_irq(denali, INTR_STATUS0__ERASE_COMP | |
1698 | INTR_STATUS0__ERASE_FAIL); | 1359 | INTR_STATUS0__ERASE_FAIL); |
1699 | 1360 | ||
1700 | denali->status = (irq_status & INTR_STATUS0__ERASE_FAIL) ? NAND_STATUS_FAIL : | 1361 | denali->status = (irq_status & INTR_STATUS0__ERASE_FAIL) ? |
1701 | PASS; | 1362 | NAND_STATUS_FAIL : PASS; |
1702 | } | 1363 | } |
1703 | 1364 | ||
1704 | static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | 1365 | static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, |
1705 | int page) | 1366 | int page) |
1706 | { | 1367 | { |
1707 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1368 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1369 | uint32_t addr, id; | ||
1370 | int i; | ||
1708 | 1371 | ||
1709 | #if DEBUG_DENALI | 1372 | #if DEBUG_DENALI |
1710 | printk("cmdfunc: 0x%x %d %d\n", cmd, col, page); | 1373 | printk(KERN_INFO "cmdfunc: 0x%x %d %d\n", cmd, col, page); |
1711 | #endif | 1374 | #endif |
1712 | switch (cmd) | 1375 | switch (cmd) { |
1713 | { | 1376 | case NAND_CMD_PAGEPROG: |
1714 | case NAND_CMD_PAGEPROG: | 1377 | break; |
1715 | break; | 1378 | case NAND_CMD_STATUS: |
1716 | case NAND_CMD_STATUS: | 1379 | read_status(denali); |
1717 | read_status(denali); | 1380 | break; |
1718 | break; | 1381 | case NAND_CMD_READID: |
1719 | case NAND_CMD_READID: | 1382 | reset_buf(denali); |
1720 | reset_buf(denali); | 1383 | /*sometimes ManufactureId read from register is not right |
1721 | if (denali->flash_bank < denali->total_used_banks) | 1384 | * e.g. some of Micron MT29F32G08QAA MLC NAND chips |
1722 | { | 1385 | * So here we send READID cmd to NAND insteand |
1723 | /* write manufacturer information into nand | 1386 | * */ |
1724 | buffer for NAND subsystem to fetch. | 1387 | addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); |
1725 | */ | 1388 | index_addr(denali, (uint32_t)addr | 0, 0x90); |
1726 | write_byte_to_buf(denali, denali->dev_info.wDeviceMaker); | 1389 | index_addr(denali, (uint32_t)addr | 1, 0); |
1727 | write_byte_to_buf(denali, denali->dev_info.wDeviceID); | 1390 | for (i = 0; i < 5; i++) { |
1728 | write_byte_to_buf(denali, denali->dev_info.bDeviceParam0); | 1391 | index_addr_read_data(denali, |
1729 | write_byte_to_buf(denali, denali->dev_info.bDeviceParam1); | 1392 | (uint32_t)addr | 2, |
1730 | write_byte_to_buf(denali, denali->dev_info.bDeviceParam2); | 1393 | &id); |
1731 | } | 1394 | write_byte_to_buf(denali, id); |
1732 | else | 1395 | } |
1733 | { | 1396 | break; |
1734 | int i; | 1397 | case NAND_CMD_READ0: |
1735 | for (i = 0; i < 5; i++) | 1398 | case NAND_CMD_SEQIN: |
1736 | write_byte_to_buf(denali, 0xff); | 1399 | denali->page = page; |
1737 | } | 1400 | break; |
1738 | break; | 1401 | case NAND_CMD_RESET: |
1739 | case NAND_CMD_READ0: | 1402 | reset_bank(denali); |
1740 | case NAND_CMD_SEQIN: | 1403 | break; |
1741 | denali->page = page; | 1404 | case NAND_CMD_READOOB: |
1742 | break; | 1405 | /* TODO: Read OOB data */ |
1743 | case NAND_CMD_RESET: | 1406 | break; |
1744 | reset_bank(denali); | 1407 | default: |
1745 | break; | 1408 | printk(KERN_ERR ": unsupported command" |
1746 | case NAND_CMD_READOOB: | 1409 | " received 0x%x\n", cmd); |
1747 | /* TODO: Read OOB data */ | 1410 | break; |
1748 | break; | ||
1749 | default: | ||
1750 | printk(KERN_ERR ": unsupported command received 0x%x\n", cmd); | ||
1751 | break; | ||
1752 | } | 1411 | } |
1753 | } | 1412 | } |
1754 | 1413 | ||
1755 | /* stubs for ECC functions not used by the NAND core */ | 1414 | /* stubs for ECC functions not used by the NAND core */ |
1756 | static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, | 1415 | static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, |
1757 | uint8_t *ecc_code) | 1416 | uint8_t *ecc_code) |
1758 | { | 1417 | { |
1759 | printk(KERN_ERR "denali_ecc_calculate called unexpectedly\n"); | 1418 | printk(KERN_ERR "denali_ecc_calculate called unexpectedly\n"); |
@@ -1761,7 +1420,7 @@ static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data, | |||
1761 | return -EIO; | 1420 | return -EIO; |
1762 | } | 1421 | } |
1763 | 1422 | ||
1764 | static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data, | 1423 | static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data, |
1765 | uint8_t *read_ecc, uint8_t *calc_ecc) | 1424 | uint8_t *read_ecc, uint8_t *calc_ecc) |
1766 | { | 1425 | { |
1767 | printk(KERN_ERR "denali_ecc_correct called unexpectedly\n"); | 1426 | printk(KERN_ERR "denali_ecc_correct called unexpectedly\n"); |
@@ -1779,10 +1438,18 @@ static void denali_ecc_hwctl(struct mtd_info *mtd, int mode) | |||
1779 | /* Initialization code to bring the device up to a known good state */ | 1438 | /* Initialization code to bring the device up to a known good state */ |
1780 | static void denali_hw_init(struct denali_nand_info *denali) | 1439 | static void denali_hw_init(struct denali_nand_info *denali) |
1781 | { | 1440 | { |
1441 | /* tell driver how many bit controller will skip before | ||
1442 | * writing ECC code in OOB, this register may be already | ||
1443 | * set by firmware. So we read this value out. | ||
1444 | * if this value is 0, just let it be. | ||
1445 | * */ | ||
1446 | denali->bbtskipbytes = ioread32(denali->flash_reg + | ||
1447 | SPARE_AREA_SKIP_BYTES); | ||
1782 | denali_irq_init(denali); | 1448 | denali_irq_init(denali); |
1783 | NAND_Flash_Reset(denali); | 1449 | denali_nand_reset(denali); |
1784 | denali_write32(0x0F, denali->flash_reg + RB_PIN_ENABLED); | 1450 | denali_write32(0x0F, denali->flash_reg + RB_PIN_ENABLED); |
1785 | denali_write32(CHIP_EN_DONT_CARE__FLAG, denali->flash_reg + CHIP_ENABLE_DONT_CARE); | 1451 | denali_write32(CHIP_EN_DONT_CARE__FLAG, |
1452 | denali->flash_reg + CHIP_ENABLE_DONT_CARE); | ||
1786 | 1453 | ||
1787 | denali_write32(0x0, denali->flash_reg + SPARE_AREA_SKIP_BYTES); | 1454 | denali_write32(0x0, denali->flash_reg + SPARE_AREA_SKIP_BYTES); |
1788 | denali_write32(0xffff, denali->flash_reg + SPARE_AREA_MARKER); | 1455 | denali_write32(0xffff, denali->flash_reg + SPARE_AREA_MARKER); |
@@ -1792,25 +1459,18 @@ static void denali_hw_init(struct denali_nand_info *denali) | |||
1792 | denali_write32(1, denali->flash_reg + ECC_ENABLE); | 1459 | denali_write32(1, denali->flash_reg + ECC_ENABLE); |
1793 | } | 1460 | } |
1794 | 1461 | ||
1795 | /* ECC layout for SLC devices. Denali spec indicates SLC fixed at 4 bytes */ | 1462 | /* Althogh controller spec said SLC ECC is forceb to be 4bit, |
1796 | #define ECC_BYTES_SLC 4 * (2048 / ECC_SECTOR_SIZE) | 1463 | * but denali controller in MRST only support 15bit and 8bit ECC |
1797 | static struct nand_ecclayout nand_oob_slc = { | 1464 | * correction |
1798 | .eccbytes = 4, | 1465 | * */ |
1799 | .eccpos = { 0, 1, 2, 3 }, /* not used */ | 1466 | #define ECC_8BITS 14 |
1800 | .oobfree = {{ | 1467 | static struct nand_ecclayout nand_8bit_oob = { |
1801 | .offset = ECC_BYTES_SLC, | 1468 | .eccbytes = 14, |
1802 | .length = 64 - ECC_BYTES_SLC | ||
1803 | }} | ||
1804 | }; | 1469 | }; |
1805 | 1470 | ||
1806 | #define ECC_BYTES_MLC 14 * (2048 / ECC_SECTOR_SIZE) | 1471 | #define ECC_15BITS 26 |
1807 | static struct nand_ecclayout nand_oob_mlc_14bit = { | 1472 | static struct nand_ecclayout nand_15bit_oob = { |
1808 | .eccbytes = 14, | 1473 | .eccbytes = 26, |
1809 | .eccpos = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13 }, /* not used */ | ||
1810 | .oobfree = {{ | ||
1811 | .offset = ECC_BYTES_MLC, | ||
1812 | .length = 64 - ECC_BYTES_MLC | ||
1813 | }} | ||
1814 | }; | 1474 | }; |
1815 | 1475 | ||
1816 | static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; | 1476 | static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; |
@@ -1842,12 +1502,12 @@ void denali_drv_init(struct denali_nand_info *denali) | |||
1842 | denali->idx = 0; | 1502 | denali->idx = 0; |
1843 | 1503 | ||
1844 | /* setup interrupt handler */ | 1504 | /* setup interrupt handler */ |
1845 | /* the completion object will be used to notify | 1505 | /* the completion object will be used to notify |
1846 | * the callee that the interrupt is done */ | 1506 | * the callee that the interrupt is done */ |
1847 | init_completion(&denali->complete); | 1507 | init_completion(&denali->complete); |
1848 | 1508 | ||
1849 | /* the spinlock will be used to synchronize the ISR | 1509 | /* the spinlock will be used to synchronize the ISR |
1850 | * with any element that might be access shared | 1510 | * with any element that might be access shared |
1851 | * data (interrupt status) */ | 1511 | * data (interrupt status) */ |
1852 | spin_lock_init(&denali->irq_lock); | 1512 | spin_lock_init(&denali->irq_lock); |
1853 | 1513 | ||
@@ -1880,13 +1540,12 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1880 | } | 1540 | } |
1881 | 1541 | ||
1882 | if (id->driver_data == INTEL_CE4100) { | 1542 | if (id->driver_data == INTEL_CE4100) { |
1883 | /* Due to a silicon limitation, we can only support | 1543 | /* Due to a silicon limitation, we can only support |
1884 | * ONFI timing mode 1 and below. | 1544 | * ONFI timing mode 1 and below. |
1885 | */ | 1545 | */ |
1886 | if (onfi_timing_mode < -1 || onfi_timing_mode > 1) | 1546 | if (onfi_timing_mode < -1 || onfi_timing_mode > 1) { |
1887 | { | 1547 | printk(KERN_ERR "Intel CE4100 only supports" |
1888 | printk("Intel CE4100 only supports ONFI timing mode 1 " | 1548 | " ONFI timing mode 1 or below\n"); |
1889 | "or below\n"); | ||
1890 | ret = -EINVAL; | 1549 | ret = -EINVAL; |
1891 | goto failed_enable; | 1550 | goto failed_enable; |
1892 | } | 1551 | } |
@@ -1905,7 +1564,9 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1905 | mem_base = csr_base + csr_len; | 1564 | mem_base = csr_base + csr_len; |
1906 | mem_len = csr_len; | 1565 | mem_len = csr_len; |
1907 | nand_dbg_print(NAND_DBG_WARN, | 1566 | nand_dbg_print(NAND_DBG_WARN, |
1908 | "Spectra: No second BAR for PCI device; assuming %08Lx\n", | 1567 | "Spectra: No second" |
1568 | " BAR for PCI device;" | ||
1569 | " assuming %08Lx\n", | ||
1909 | (uint64_t)csr_base); | 1570 | (uint64_t)csr_base); |
1910 | } | 1571 | } |
1911 | } | 1572 | } |
@@ -1913,16 +1574,16 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1913 | /* Is 32-bit DMA supported? */ | 1574 | /* Is 32-bit DMA supported? */ |
1914 | ret = pci_set_dma_mask(dev, DMA_BIT_MASK(32)); | 1575 | ret = pci_set_dma_mask(dev, DMA_BIT_MASK(32)); |
1915 | 1576 | ||
1916 | if (ret) | 1577 | if (ret) { |
1917 | { | ||
1918 | printk(KERN_ERR "Spectra: no usable DMA configuration\n"); | 1578 | printk(KERN_ERR "Spectra: no usable DMA configuration\n"); |
1919 | goto failed_enable; | 1579 | goto failed_enable; |
1920 | } | 1580 | } |
1921 | denali->buf.dma_buf = pci_map_single(dev, denali->buf.buf, DENALI_BUF_SIZE, | 1581 | denali->buf.dma_buf = |
1922 | PCI_DMA_BIDIRECTIONAL); | 1582 | pci_map_single(dev, denali->buf.buf, |
1583 | DENALI_BUF_SIZE, | ||
1584 | PCI_DMA_BIDIRECTIONAL); | ||
1923 | 1585 | ||
1924 | if (pci_dma_mapping_error(dev, denali->buf.dma_buf)) | 1586 | if (pci_dma_mapping_error(dev, denali->buf.dma_buf)) { |
1925 | { | ||
1926 | printk(KERN_ERR "Spectra: failed to map DMA buffer\n"); | 1587 | printk(KERN_ERR "Spectra: failed to map DMA buffer\n"); |
1927 | goto failed_enable; | 1588 | goto failed_enable; |
1928 | } | 1589 | } |
@@ -1970,22 +1631,11 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1970 | } | 1631 | } |
1971 | 1632 | ||
1972 | /* now that our ISR is registered, we can enable interrupts */ | 1633 | /* now that our ISR is registered, we can enable interrupts */ |
1973 | NAND_LLD_Enable_Disable_Interrupts(denali, true); | 1634 | denali_set_intr_modes(denali, true); |
1974 | 1635 | ||
1975 | pci_set_drvdata(dev, denali); | 1636 | pci_set_drvdata(dev, denali); |
1976 | 1637 | ||
1977 | NAND_Read_Device_ID(denali); | 1638 | denali_nand_timing_set(denali); |
1978 | |||
1979 | /* MTD supported page sizes vary by kernel. We validate our | ||
1980 | kernel supports the device here. | ||
1981 | */ | ||
1982 | if (denali->dev_info.wPageSize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) | ||
1983 | { | ||
1984 | ret = -ENODEV; | ||
1985 | printk(KERN_ERR "Spectra: device size not supported by this " | ||
1986 | "version of MTD."); | ||
1987 | goto failed_nand; | ||
1988 | } | ||
1989 | 1639 | ||
1990 | nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" | 1640 | nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" |
1991 | "acc_clks: %d, re_2_we: %d, we_2_re: %d," | 1641 | "acc_clks: %d, re_2_we: %d, we_2_re: %d," |
@@ -2009,18 +1659,46 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
2009 | denali->nand.read_byte = denali_read_byte; | 1659 | denali->nand.read_byte = denali_read_byte; |
2010 | denali->nand.waitfunc = denali_waitfunc; | 1660 | denali->nand.waitfunc = denali_waitfunc; |
2011 | 1661 | ||
2012 | /* scan for NAND devices attached to the controller | 1662 | /* scan for NAND devices attached to the controller |
2013 | * this is the first stage in a two step process to register | 1663 | * this is the first stage in a two step process to register |
2014 | * with the nand subsystem */ | 1664 | * with the nand subsystem */ |
2015 | if (nand_scan_ident(&denali->mtd, LLD_MAX_FLASH_BANKS, NULL)) | 1665 | if (nand_scan_ident(&denali->mtd, LLD_MAX_FLASH_BANKS, NULL)) { |
2016 | { | ||
2017 | ret = -ENXIO; | 1666 | ret = -ENXIO; |
2018 | goto failed_nand; | 1667 | goto failed_nand; |
2019 | } | 1668 | } |
2020 | 1669 | ||
2021 | /* second stage of the NAND scan | 1670 | /* MTD supported page sizes vary by kernel. We validate our |
2022 | * this stage requires information regarding ECC and | 1671 | * kernel supports the device here. |
2023 | * bad block management. */ | 1672 | */ |
1673 | if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) { | ||
1674 | ret = -ENODEV; | ||
1675 | printk(KERN_ERR "Spectra: device size not supported by this " | ||
1676 | "version of MTD."); | ||
1677 | goto failed_nand; | ||
1678 | } | ||
1679 | |||
1680 | /* support for multi nand | ||
1681 | * MTD known nothing about multi nand, | ||
1682 | * so we should tell it the real pagesize | ||
1683 | * and anything necessery | ||
1684 | */ | ||
1685 | denali->devnum = ioread32(denali->flash_reg + DEVICES_CONNECTED); | ||
1686 | denali->nand.chipsize <<= (denali->devnum - 1); | ||
1687 | denali->nand.page_shift += (denali->devnum - 1); | ||
1688 | denali->nand.pagemask = (denali->nand.chipsize >> | ||
1689 | denali->nand.page_shift) - 1; | ||
1690 | denali->nand.bbt_erase_shift += (denali->devnum - 1); | ||
1691 | denali->nand.phys_erase_shift = denali->nand.bbt_erase_shift; | ||
1692 | denali->nand.chip_shift += (denali->devnum - 1); | ||
1693 | denali->mtd.writesize <<= (denali->devnum - 1); | ||
1694 | denali->mtd.oobsize <<= (denali->devnum - 1); | ||
1695 | denali->mtd.erasesize <<= (denali->devnum - 1); | ||
1696 | denali->mtd.size = denali->nand.numchips * denali->nand.chipsize; | ||
1697 | denali->bbtskipbytes *= denali->devnum; | ||
1698 | |||
1699 | /* second stage of the NAND scan | ||
1700 | * this stage requires information regarding ECC and | ||
1701 | * bad block management. */ | ||
2024 | 1702 | ||
2025 | /* Bad block management */ | 1703 | /* Bad block management */ |
2026 | denali->nand.bbt_td = &bbt_main_descr; | 1704 | denali->nand.bbt_td = &bbt_main_descr; |
@@ -2030,26 +1708,57 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
2030 | denali->nand.options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN; | 1708 | denali->nand.options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN; |
2031 | denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME; | 1709 | denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME; |
2032 | 1710 | ||
2033 | if (denali->dev_info.MLCDevice) | 1711 | /* Denali Controller only support 15bit and 8bit ECC in MRST, |
2034 | { | 1712 | * so just let controller do 15bit ECC for MLC and 8bit ECC for |
2035 | denali->nand.ecc.layout = &nand_oob_mlc_14bit; | 1713 | * SLC if possible. |
2036 | denali->nand.ecc.bytes = ECC_BYTES_MLC; | 1714 | * */ |
2037 | } | 1715 | if (denali->nand.cellinfo & 0xc && |
2038 | else /* SLC */ | 1716 | (denali->mtd.oobsize > (denali->bbtskipbytes + |
2039 | { | 1717 | ECC_15BITS * (denali->mtd.writesize / |
2040 | denali->nand.ecc.layout = &nand_oob_slc; | 1718 | ECC_SECTOR_SIZE)))) { |
2041 | denali->nand.ecc.bytes = ECC_BYTES_SLC; | 1719 | /* if MLC OOB size is large enough, use 15bit ECC*/ |
1720 | denali->nand.ecc.layout = &nand_15bit_oob; | ||
1721 | denali->nand.ecc.bytes = ECC_15BITS; | ||
1722 | denali_write32(15, denali->flash_reg + ECC_CORRECTION); | ||
1723 | } else if (denali->mtd.oobsize < (denali->bbtskipbytes + | ||
1724 | ECC_8BITS * (denali->mtd.writesize / | ||
1725 | ECC_SECTOR_SIZE))) { | ||
1726 | printk(KERN_ERR "Your NAND chip OOB is not large enough to" | ||
1727 | " contain 8bit ECC correction codes"); | ||
1728 | goto failed_nand; | ||
1729 | } else { | ||
1730 | denali->nand.ecc.layout = &nand_8bit_oob; | ||
1731 | denali->nand.ecc.bytes = ECC_8BITS; | ||
1732 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); | ||
2042 | } | 1733 | } |
2043 | 1734 | ||
2044 | /* These functions are required by the NAND core framework, otherwise, | 1735 | denali->nand.ecc.bytes *= denali->devnum; |
2045 | the NAND core will assert. However, we don't need them, so we'll stub | 1736 | denali->nand.ecc.layout->eccbytes *= |
2046 | them out. */ | 1737 | denali->mtd.writesize / ECC_SECTOR_SIZE; |
1738 | denali->nand.ecc.layout->oobfree[0].offset = | ||
1739 | denali->bbtskipbytes + denali->nand.ecc.layout->eccbytes; | ||
1740 | denali->nand.ecc.layout->oobfree[0].length = | ||
1741 | denali->mtd.oobsize - denali->nand.ecc.layout->eccbytes - | ||
1742 | denali->bbtskipbytes; | ||
1743 | |||
1744 | /* Let driver know the total blocks number and | ||
1745 | * how many blocks contained by each nand chip. | ||
1746 | * blksperchip will help driver to know how many | ||
1747 | * blocks is taken by FW. | ||
1748 | * */ | ||
1749 | denali->totalblks = denali->mtd.size >> | ||
1750 | denali->nand.phys_erase_shift; | ||
1751 | denali->blksperchip = denali->totalblks / denali->nand.numchips; | ||
1752 | |||
1753 | /* These functions are required by the NAND core framework, otherwise, | ||
1754 | * the NAND core will assert. However, we don't need them, so we'll stub | ||
1755 | * them out. */ | ||
2047 | denali->nand.ecc.calculate = denali_ecc_calculate; | 1756 | denali->nand.ecc.calculate = denali_ecc_calculate; |
2048 | denali->nand.ecc.correct = denali_ecc_correct; | 1757 | denali->nand.ecc.correct = denali_ecc_correct; |
2049 | denali->nand.ecc.hwctl = denali_ecc_hwctl; | 1758 | denali->nand.ecc.hwctl = denali_ecc_hwctl; |
2050 | 1759 | ||
2051 | /* override the default read operations */ | 1760 | /* override the default read operations */ |
2052 | denali->nand.ecc.size = denali->mtd.writesize; | 1761 | denali->nand.ecc.size = ECC_SECTOR_SIZE * denali->devnum; |
2053 | denali->nand.ecc.read_page = denali_read_page; | 1762 | denali->nand.ecc.read_page = denali_read_page; |
2054 | denali->nand.ecc.read_page_raw = denali_read_page_raw; | 1763 | denali->nand.ecc.read_page_raw = denali_read_page_raw; |
2055 | denali->nand.ecc.write_page = denali_write_page; | 1764 | denali->nand.ecc.write_page = denali_write_page; |
@@ -2058,15 +1767,15 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
2058 | denali->nand.ecc.write_oob = denali_write_oob; | 1767 | denali->nand.ecc.write_oob = denali_write_oob; |
2059 | denali->nand.erase_cmd = denali_erase; | 1768 | denali->nand.erase_cmd = denali_erase; |
2060 | 1769 | ||
2061 | if (nand_scan_tail(&denali->mtd)) | 1770 | if (nand_scan_tail(&denali->mtd)) { |
2062 | { | ||
2063 | ret = -ENXIO; | 1771 | ret = -ENXIO; |
2064 | goto failed_nand; | 1772 | goto failed_nand; |
2065 | } | 1773 | } |
2066 | 1774 | ||
2067 | ret = add_mtd_device(&denali->mtd); | 1775 | ret = add_mtd_device(&denali->mtd); |
2068 | if (ret) { | 1776 | if (ret) { |
2069 | printk(KERN_ERR "Spectra: Failed to register MTD device: %d\n", ret); | 1777 | printk(KERN_ERR "Spectra: Failed to register" |
1778 | " MTD device: %d\n", ret); | ||
2070 | goto failed_nand; | 1779 | goto failed_nand; |
2071 | } | 1780 | } |
2072 | return 0; | 1781 | return 0; |
@@ -2079,7 +1788,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
2079 | failed_remap_csr: | 1788 | failed_remap_csr: |
2080 | pci_release_regions(dev); | 1789 | pci_release_regions(dev); |
2081 | failed_req_csr: | 1790 | failed_req_csr: |
2082 | pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | 1791 | pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, |
2083 | PCI_DMA_BIDIRECTIONAL); | 1792 | PCI_DMA_BIDIRECTIONAL); |
2084 | failed_enable: | 1793 | failed_enable: |
2085 | kfree(denali); | 1794 | kfree(denali); |
@@ -2103,7 +1812,7 @@ static void denali_pci_remove(struct pci_dev *dev) | |||
2103 | iounmap(denali->flash_mem); | 1812 | iounmap(denali->flash_mem); |
2104 | pci_release_regions(dev); | 1813 | pci_release_regions(dev); |
2105 | pci_disable_device(dev); | 1814 | pci_disable_device(dev); |
2106 | pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | 1815 | pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE, |
2107 | PCI_DMA_BIDIRECTIONAL); | 1816 | PCI_DMA_BIDIRECTIONAL); |
2108 | pci_set_drvdata(dev, NULL); | 1817 | pci_set_drvdata(dev, NULL); |
2109 | kfree(denali); | 1818 | kfree(denali); |
@@ -2120,7 +1829,8 @@ static struct pci_driver denali_pci_driver = { | |||
2120 | 1829 | ||
2121 | static int __devinit denali_init(void) | 1830 | static int __devinit denali_init(void) |
2122 | { | 1831 | { |
2123 | printk(KERN_INFO "Spectra MTD driver built on %s @ %s\n", __DATE__, __TIME__); | 1832 | printk(KERN_INFO "Spectra MTD driver built on %s @ %s\n", |
1833 | __DATE__, __TIME__); | ||
2124 | return pci_register_driver(&denali_pci_driver); | 1834 | return pci_register_driver(&denali_pci_driver); |
2125 | } | 1835 | } |
2126 | 1836 | ||
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 422a29ab2f60..b680474e6333 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h | |||
@@ -17,7 +17,7 @@ | |||
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/mtd/nand.h> | 20 | #include <linux/mtd/nand.h> |
21 | 21 | ||
22 | #define DEVICE_RESET 0x0 | 22 | #define DEVICE_RESET 0x0 |
23 | #define DEVICE_RESET__BANK0 0x0001 | 23 | #define DEVICE_RESET__BANK0 0x0001 |
@@ -29,7 +29,7 @@ | |||
29 | #define TRANSFER_SPARE_REG__FLAG 0x0001 | 29 | #define TRANSFER_SPARE_REG__FLAG 0x0001 |
30 | 30 | ||
31 | #define LOAD_WAIT_CNT 0x20 | 31 | #define LOAD_WAIT_CNT 0x20 |
32 | #define LOAD_WAIT_CNT__VALUE 0xffff | 32 | #define LOAD_WAIT_CNT__VALUE 0xffff |
33 | 33 | ||
34 | #define PROGRAM_WAIT_CNT 0x30 | 34 | #define PROGRAM_WAIT_CNT 0x30 |
35 | #define PROGRAM_WAIT_CNT__VALUE 0xffff | 35 | #define PROGRAM_WAIT_CNT__VALUE 0xffff |
@@ -83,7 +83,7 @@ | |||
83 | #define RE_2_WE 0x120 | 83 | #define RE_2_WE 0x120 |
84 | #define RE_2_WE__VALUE 0x003f | 84 | #define RE_2_WE__VALUE 0x003f |
85 | 85 | ||
86 | #define ACC_CLKS 0x130 | 86 | #define ACC_CLKS 0x130 |
87 | #define ACC_CLKS__VALUE 0x000f | 87 | #define ACC_CLKS__VALUE 0x000f |
88 | 88 | ||
89 | #define NUMBER_OF_PLANES 0x140 | 89 | #define NUMBER_OF_PLANES 0x140 |
@@ -140,7 +140,7 @@ | |||
140 | #define DEVICES_CONNECTED 0x250 | 140 | #define DEVICES_CONNECTED 0x250 |
141 | #define DEVICES_CONNECTED__VALUE 0x0007 | 141 | #define DEVICES_CONNECTED__VALUE 0x0007 |
142 | 142 | ||
143 | #define DIE_MASK 0x260 | 143 | #define DIE_MASK 0x260 |
144 | #define DIE_MASK__VALUE 0x00ff | 144 | #define DIE_MASK__VALUE 0x00ff |
145 | 145 | ||
146 | #define FIRST_BLOCK_OF_NEXT_PLANE 0x270 | 146 | #define FIRST_BLOCK_OF_NEXT_PLANE 0x270 |
@@ -152,7 +152,7 @@ | |||
152 | #define RE_2_RE 0x290 | 152 | #define RE_2_RE 0x290 |
153 | #define RE_2_RE__VALUE 0x003f | 153 | #define RE_2_RE__VALUE 0x003f |
154 | 154 | ||
155 | #define MANUFACTURER_ID 0x300 | 155 | #define MANUFACTURER_ID 0x300 |
156 | #define MANUFACTURER_ID__VALUE 0x00ff | 156 | #define MANUFACTURER_ID__VALUE 0x00ff |
157 | 157 | ||
158 | #define DEVICE_ID 0x310 | 158 | #define DEVICE_ID 0x310 |
@@ -173,13 +173,13 @@ | |||
173 | #define LOGICAL_PAGE_SPARE_SIZE 0x360 | 173 | #define LOGICAL_PAGE_SPARE_SIZE 0x360 |
174 | #define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff | 174 | #define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff |
175 | 175 | ||
176 | #define REVISION 0x370 | 176 | #define REVISION 0x370 |
177 | #define REVISION__VALUE 0xffff | 177 | #define REVISION__VALUE 0xffff |
178 | 178 | ||
179 | #define ONFI_DEVICE_FEATURES 0x380 | 179 | #define ONFI_DEVICE_FEATURES 0x380 |
180 | #define ONFI_DEVICE_FEATURES__VALUE 0x003f | 180 | #define ONFI_DEVICE_FEATURES__VALUE 0x003f |
181 | 181 | ||
182 | #define ONFI_OPTIONAL_COMMANDS 0x390 | 182 | #define ONFI_OPTIONAL_COMMANDS 0x390 |
183 | #define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f | 183 | #define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f |
184 | 184 | ||
185 | #define ONFI_TIMING_MODE 0x3a0 | 185 | #define ONFI_TIMING_MODE 0x3a0 |
@@ -201,12 +201,12 @@ | |||
201 | #define FEATURES 0x3f0 | 201 | #define FEATURES 0x3f0 |
202 | #define FEATURES__N_BANKS 0x0003 | 202 | #define FEATURES__N_BANKS 0x0003 |
203 | #define FEATURES__ECC_MAX_ERR 0x003c | 203 | #define FEATURES__ECC_MAX_ERR 0x003c |
204 | #define FEATURES__DMA 0x0040 | 204 | #define FEATURES__DMA 0x0040 |
205 | #define FEATURES__CMD_DMA 0x0080 | 205 | #define FEATURES__CMD_DMA 0x0080 |
206 | #define FEATURES__PARTITION 0x0100 | 206 | #define FEATURES__PARTITION 0x0100 |
207 | #define FEATURES__XDMA_SIDEBAND 0x0200 | 207 | #define FEATURES__XDMA_SIDEBAND 0x0200 |
208 | #define FEATURES__GPREG 0x0400 | 208 | #define FEATURES__GPREG 0x0400 |
209 | #define FEATURES__INDEX_ADDR 0x0800 | 209 | #define FEATURES__INDEX_ADDR 0x0800 |
210 | 210 | ||
211 | #define TRANSFER_MODE 0x400 | 211 | #define TRANSFER_MODE 0x400 |
212 | #define TRANSFER_MODE__VALUE 0x0003 | 212 | #define TRANSFER_MODE__VALUE 0x0003 |
@@ -235,12 +235,12 @@ | |||
235 | #define INTR_EN0__DMA_CMD_COMP 0x0004 | 235 | #define INTR_EN0__DMA_CMD_COMP 0x0004 |
236 | #define INTR_EN0__TIME_OUT 0x0008 | 236 | #define INTR_EN0__TIME_OUT 0x0008 |
237 | #define INTR_EN0__PROGRAM_FAIL 0x0010 | 237 | #define INTR_EN0__PROGRAM_FAIL 0x0010 |
238 | #define INTR_EN0__ERASE_FAIL 0x0020 | 238 | #define INTR_EN0__ERASE_FAIL 0x0020 |
239 | #define INTR_EN0__LOAD_COMP 0x0040 | 239 | #define INTR_EN0__LOAD_COMP 0x0040 |
240 | #define INTR_EN0__PROGRAM_COMP 0x0080 | 240 | #define INTR_EN0__PROGRAM_COMP 0x0080 |
241 | #define INTR_EN0__ERASE_COMP 0x0100 | 241 | #define INTR_EN0__ERASE_COMP 0x0100 |
242 | #define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200 | 242 | #define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200 |
243 | #define INTR_EN0__LOCKED_BLK 0x0400 | 243 | #define INTR_EN0__LOCKED_BLK 0x0400 |
244 | #define INTR_EN0__UNSUP_CMD 0x0800 | 244 | #define INTR_EN0__UNSUP_CMD 0x0800 |
245 | #define INTR_EN0__INT_ACT 0x1000 | 245 | #define INTR_EN0__INT_ACT 0x1000 |
246 | #define INTR_EN0__RST_COMP 0x2000 | 246 | #define INTR_EN0__RST_COMP 0x2000 |
@@ -253,7 +253,7 @@ | |||
253 | #define ERR_PAGE_ADDR0 0x440 | 253 | #define ERR_PAGE_ADDR0 0x440 |
254 | #define ERR_PAGE_ADDR0__VALUE 0xffff | 254 | #define ERR_PAGE_ADDR0__VALUE 0xffff |
255 | 255 | ||
256 | #define ERR_BLOCK_ADDR0 0x450 | 256 | #define ERR_BLOCK_ADDR0 0x450 |
257 | #define ERR_BLOCK_ADDR0__VALUE 0xffff | 257 | #define ERR_BLOCK_ADDR0__VALUE 0xffff |
258 | 258 | ||
259 | #define INTR_STATUS1 0x460 | 259 | #define INTR_STATUS1 0x460 |
@@ -280,12 +280,12 @@ | |||
280 | #define INTR_EN1__DMA_CMD_COMP 0x0004 | 280 | #define INTR_EN1__DMA_CMD_COMP 0x0004 |
281 | #define INTR_EN1__TIME_OUT 0x0008 | 281 | #define INTR_EN1__TIME_OUT 0x0008 |
282 | #define INTR_EN1__PROGRAM_FAIL 0x0010 | 282 | #define INTR_EN1__PROGRAM_FAIL 0x0010 |
283 | #define INTR_EN1__ERASE_FAIL 0x0020 | 283 | #define INTR_EN1__ERASE_FAIL 0x0020 |
284 | #define INTR_EN1__LOAD_COMP 0x0040 | 284 | #define INTR_EN1__LOAD_COMP 0x0040 |
285 | #define INTR_EN1__PROGRAM_COMP 0x0080 | 285 | #define INTR_EN1__PROGRAM_COMP 0x0080 |
286 | #define INTR_EN1__ERASE_COMP 0x0100 | 286 | #define INTR_EN1__ERASE_COMP 0x0100 |
287 | #define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200 | 287 | #define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200 |
288 | #define INTR_EN1__LOCKED_BLK 0x0400 | 288 | #define INTR_EN1__LOCKED_BLK 0x0400 |
289 | #define INTR_EN1__UNSUP_CMD 0x0800 | 289 | #define INTR_EN1__UNSUP_CMD 0x0800 |
290 | #define INTR_EN1__INT_ACT 0x1000 | 290 | #define INTR_EN1__INT_ACT 0x1000 |
291 | #define INTR_EN1__RST_COMP 0x2000 | 291 | #define INTR_EN1__RST_COMP 0x2000 |
@@ -298,7 +298,7 @@ | |||
298 | #define ERR_PAGE_ADDR1 0x490 | 298 | #define ERR_PAGE_ADDR1 0x490 |
299 | #define ERR_PAGE_ADDR1__VALUE 0xffff | 299 | #define ERR_PAGE_ADDR1__VALUE 0xffff |
300 | 300 | ||
301 | #define ERR_BLOCK_ADDR1 0x4a0 | 301 | #define ERR_BLOCK_ADDR1 0x4a0 |
302 | #define ERR_BLOCK_ADDR1__VALUE 0xffff | 302 | #define ERR_BLOCK_ADDR1__VALUE 0xffff |
303 | 303 | ||
304 | #define INTR_STATUS2 0x4b0 | 304 | #define INTR_STATUS2 0x4b0 |
@@ -325,12 +325,12 @@ | |||
325 | #define INTR_EN2__DMA_CMD_COMP 0x0004 | 325 | #define INTR_EN2__DMA_CMD_COMP 0x0004 |
326 | #define INTR_EN2__TIME_OUT 0x0008 | 326 | #define INTR_EN2__TIME_OUT 0x0008 |
327 | #define INTR_EN2__PROGRAM_FAIL 0x0010 | 327 | #define INTR_EN2__PROGRAM_FAIL 0x0010 |
328 | #define INTR_EN2__ERASE_FAIL 0x0020 | 328 | #define INTR_EN2__ERASE_FAIL 0x0020 |
329 | #define INTR_EN2__LOAD_COMP 0x0040 | 329 | #define INTR_EN2__LOAD_COMP 0x0040 |
330 | #define INTR_EN2__PROGRAM_COMP 0x0080 | 330 | #define INTR_EN2__PROGRAM_COMP 0x0080 |
331 | #define INTR_EN2__ERASE_COMP 0x0100 | 331 | #define INTR_EN2__ERASE_COMP 0x0100 |
332 | #define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200 | 332 | #define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200 |
333 | #define INTR_EN2__LOCKED_BLK 0x0400 | 333 | #define INTR_EN2__LOCKED_BLK 0x0400 |
334 | #define INTR_EN2__UNSUP_CMD 0x0800 | 334 | #define INTR_EN2__UNSUP_CMD 0x0800 |
335 | #define INTR_EN2__INT_ACT 0x1000 | 335 | #define INTR_EN2__INT_ACT 0x1000 |
336 | #define INTR_EN2__RST_COMP 0x2000 | 336 | #define INTR_EN2__RST_COMP 0x2000 |
@@ -343,7 +343,7 @@ | |||
343 | #define ERR_PAGE_ADDR2 0x4e0 | 343 | #define ERR_PAGE_ADDR2 0x4e0 |
344 | #define ERR_PAGE_ADDR2__VALUE 0xffff | 344 | #define ERR_PAGE_ADDR2__VALUE 0xffff |
345 | 345 | ||
346 | #define ERR_BLOCK_ADDR2 0x4f0 | 346 | #define ERR_BLOCK_ADDR2 0x4f0 |
347 | #define ERR_BLOCK_ADDR2__VALUE 0xffff | 347 | #define ERR_BLOCK_ADDR2__VALUE 0xffff |
348 | 348 | ||
349 | #define INTR_STATUS3 0x500 | 349 | #define INTR_STATUS3 0x500 |
@@ -370,12 +370,12 @@ | |||
370 | #define INTR_EN3__DMA_CMD_COMP 0x0004 | 370 | #define INTR_EN3__DMA_CMD_COMP 0x0004 |
371 | #define INTR_EN3__TIME_OUT 0x0008 | 371 | #define INTR_EN3__TIME_OUT 0x0008 |
372 | #define INTR_EN3__PROGRAM_FAIL 0x0010 | 372 | #define INTR_EN3__PROGRAM_FAIL 0x0010 |
373 | #define INTR_EN3__ERASE_FAIL 0x0020 | 373 | #define INTR_EN3__ERASE_FAIL 0x0020 |
374 | #define INTR_EN3__LOAD_COMP 0x0040 | 374 | #define INTR_EN3__LOAD_COMP 0x0040 |
375 | #define INTR_EN3__PROGRAM_COMP 0x0080 | 375 | #define INTR_EN3__PROGRAM_COMP 0x0080 |
376 | #define INTR_EN3__ERASE_COMP 0x0100 | 376 | #define INTR_EN3__ERASE_COMP 0x0100 |
377 | #define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200 | 377 | #define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200 |
378 | #define INTR_EN3__LOCKED_BLK 0x0400 | 378 | #define INTR_EN3__LOCKED_BLK 0x0400 |
379 | #define INTR_EN3__UNSUP_CMD 0x0800 | 379 | #define INTR_EN3__UNSUP_CMD 0x0800 |
380 | #define INTR_EN3__INT_ACT 0x1000 | 380 | #define INTR_EN3__INT_ACT 0x1000 |
381 | #define INTR_EN3__RST_COMP 0x2000 | 381 | #define INTR_EN3__RST_COMP 0x2000 |
@@ -388,7 +388,7 @@ | |||
388 | #define ERR_PAGE_ADDR3 0x530 | 388 | #define ERR_PAGE_ADDR3 0x530 |
389 | #define ERR_PAGE_ADDR3__VALUE 0xffff | 389 | #define ERR_PAGE_ADDR3__VALUE 0xffff |
390 | 390 | ||
391 | #define ERR_BLOCK_ADDR3 0x540 | 391 | #define ERR_BLOCK_ADDR3 0x540 |
392 | #define ERR_BLOCK_ADDR3__VALUE 0xffff | 392 | #define ERR_BLOCK_ADDR3__VALUE 0xffff |
393 | 393 | ||
394 | #define DATA_INTR 0x550 | 394 | #define DATA_INTR 0x550 |
@@ -412,9 +412,9 @@ | |||
412 | #define GPREG_3__VALUE 0xffff | 412 | #define GPREG_3__VALUE 0xffff |
413 | 413 | ||
414 | #define ECC_THRESHOLD 0x600 | 414 | #define ECC_THRESHOLD 0x600 |
415 | #define ECC_THRESHOLD__VALUE 0x03ff | 415 | #define ECC_THRESHOLD__VALUE 0x03ff |
416 | 416 | ||
417 | #define ECC_ERROR_BLOCK_ADDRESS 0x610 | 417 | #define ECC_ERROR_BLOCK_ADDRESS 0x610 |
418 | #define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff | 418 | #define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff |
419 | 419 | ||
420 | #define ECC_ERROR_PAGE_ADDRESS 0x620 | 420 | #define ECC_ERROR_PAGE_ADDRESS 0x620 |
@@ -466,7 +466,7 @@ | |||
466 | #define CHNL_ACTIVE__CHANNEL3 0x0008 | 466 | #define CHNL_ACTIVE__CHANNEL3 0x0008 |
467 | 467 | ||
468 | #define ACTIVE_SRC_ID 0x800 | 468 | #define ACTIVE_SRC_ID 0x800 |
469 | #define ACTIVE_SRC_ID__VALUE 0x00ff | 469 | #define ACTIVE_SRC_ID__VALUE 0x00ff |
470 | 470 | ||
471 | #define PTN_INTR 0x810 | 471 | #define PTN_INTR 0x810 |
472 | #define PTN_INTR__CONFIG_ERROR 0x0001 | 472 | #define PTN_INTR__CONFIG_ERROR 0x0001 |
@@ -485,7 +485,7 @@ | |||
485 | #define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020 | 485 | #define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020 |
486 | 486 | ||
487 | #define PERM_SRC_ID_0 0x830 | 487 | #define PERM_SRC_ID_0 0x830 |
488 | #define PERM_SRC_ID_0__SRCID 0x00ff | 488 | #define PERM_SRC_ID_0__SRCID 0x00ff |
489 | #define PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE 0x0800 | 489 | #define PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE 0x0800 |
490 | #define PERM_SRC_ID_0__WRITE_ACTIVE 0x2000 | 490 | #define PERM_SRC_ID_0__WRITE_ACTIVE 0x2000 |
491 | #define PERM_SRC_ID_0__READ_ACTIVE 0x4000 | 491 | #define PERM_SRC_ID_0__READ_ACTIVE 0x4000 |
@@ -502,7 +502,7 @@ | |||
502 | #define MIN_MAX_BANK_0__MAX_VALUE 0x000c | 502 | #define MIN_MAX_BANK_0__MAX_VALUE 0x000c |
503 | 503 | ||
504 | #define PERM_SRC_ID_1 0x870 | 504 | #define PERM_SRC_ID_1 0x870 |
505 | #define PERM_SRC_ID_1__SRCID 0x00ff | 505 | #define PERM_SRC_ID_1__SRCID 0x00ff |
506 | #define PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE 0x0800 | 506 | #define PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE 0x0800 |
507 | #define PERM_SRC_ID_1__WRITE_ACTIVE 0x2000 | 507 | #define PERM_SRC_ID_1__WRITE_ACTIVE 0x2000 |
508 | #define PERM_SRC_ID_1__READ_ACTIVE 0x4000 | 508 | #define PERM_SRC_ID_1__READ_ACTIVE 0x4000 |
@@ -519,7 +519,7 @@ | |||
519 | #define MIN_MAX_BANK_1__MAX_VALUE 0x000c | 519 | #define MIN_MAX_BANK_1__MAX_VALUE 0x000c |
520 | 520 | ||
521 | #define PERM_SRC_ID_2 0x8b0 | 521 | #define PERM_SRC_ID_2 0x8b0 |
522 | #define PERM_SRC_ID_2__SRCID 0x00ff | 522 | #define PERM_SRC_ID_2__SRCID 0x00ff |
523 | #define PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE 0x0800 | 523 | #define PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE 0x0800 |
524 | #define PERM_SRC_ID_2__WRITE_ACTIVE 0x2000 | 524 | #define PERM_SRC_ID_2__WRITE_ACTIVE 0x2000 |
525 | #define PERM_SRC_ID_2__READ_ACTIVE 0x4000 | 525 | #define PERM_SRC_ID_2__READ_ACTIVE 0x4000 |
@@ -536,7 +536,7 @@ | |||
536 | #define MIN_MAX_BANK_2__MAX_VALUE 0x000c | 536 | #define MIN_MAX_BANK_2__MAX_VALUE 0x000c |
537 | 537 | ||
538 | #define PERM_SRC_ID_3 0x8f0 | 538 | #define PERM_SRC_ID_3 0x8f0 |
539 | #define PERM_SRC_ID_3__SRCID 0x00ff | 539 | #define PERM_SRC_ID_3__SRCID 0x00ff |
540 | #define PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE 0x0800 | 540 | #define PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE 0x0800 |
541 | #define PERM_SRC_ID_3__WRITE_ACTIVE 0x2000 | 541 | #define PERM_SRC_ID_3__WRITE_ACTIVE 0x2000 |
542 | #define PERM_SRC_ID_3__READ_ACTIVE 0x4000 | 542 | #define PERM_SRC_ID_3__READ_ACTIVE 0x4000 |
@@ -553,7 +553,7 @@ | |||
553 | #define MIN_MAX_BANK_3__MAX_VALUE 0x000c | 553 | #define MIN_MAX_BANK_3__MAX_VALUE 0x000c |
554 | 554 | ||
555 | #define PERM_SRC_ID_4 0x930 | 555 | #define PERM_SRC_ID_4 0x930 |
556 | #define PERM_SRC_ID_4__SRCID 0x00ff | 556 | #define PERM_SRC_ID_4__SRCID 0x00ff |
557 | #define PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE 0x0800 | 557 | #define PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE 0x0800 |
558 | #define PERM_SRC_ID_4__WRITE_ACTIVE 0x2000 | 558 | #define PERM_SRC_ID_4__WRITE_ACTIVE 0x2000 |
559 | #define PERM_SRC_ID_4__READ_ACTIVE 0x4000 | 559 | #define PERM_SRC_ID_4__READ_ACTIVE 0x4000 |
@@ -570,7 +570,7 @@ | |||
570 | #define MIN_MAX_BANK_4__MAX_VALUE 0x000c | 570 | #define MIN_MAX_BANK_4__MAX_VALUE 0x000c |
571 | 571 | ||
572 | #define PERM_SRC_ID_5 0x970 | 572 | #define PERM_SRC_ID_5 0x970 |
573 | #define PERM_SRC_ID_5__SRCID 0x00ff | 573 | #define PERM_SRC_ID_5__SRCID 0x00ff |
574 | #define PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE 0x0800 | 574 | #define PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE 0x0800 |
575 | #define PERM_SRC_ID_5__WRITE_ACTIVE 0x2000 | 575 | #define PERM_SRC_ID_5__WRITE_ACTIVE 0x2000 |
576 | #define PERM_SRC_ID_5__READ_ACTIVE 0x4000 | 576 | #define PERM_SRC_ID_5__READ_ACTIVE 0x4000 |
@@ -587,7 +587,7 @@ | |||
587 | #define MIN_MAX_BANK_5__MAX_VALUE 0x000c | 587 | #define MIN_MAX_BANK_5__MAX_VALUE 0x000c |
588 | 588 | ||
589 | #define PERM_SRC_ID_6 0x9b0 | 589 | #define PERM_SRC_ID_6 0x9b0 |
590 | #define PERM_SRC_ID_6__SRCID 0x00ff | 590 | #define PERM_SRC_ID_6__SRCID 0x00ff |
591 | #define PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE 0x0800 | 591 | #define PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE 0x0800 |
592 | #define PERM_SRC_ID_6__WRITE_ACTIVE 0x2000 | 592 | #define PERM_SRC_ID_6__WRITE_ACTIVE 0x2000 |
593 | #define PERM_SRC_ID_6__READ_ACTIVE 0x4000 | 593 | #define PERM_SRC_ID_6__READ_ACTIVE 0x4000 |
@@ -604,7 +604,7 @@ | |||
604 | #define MIN_MAX_BANK_6__MAX_VALUE 0x000c | 604 | #define MIN_MAX_BANK_6__MAX_VALUE 0x000c |
605 | 605 | ||
606 | #define PERM_SRC_ID_7 0x9f0 | 606 | #define PERM_SRC_ID_7 0x9f0 |
607 | #define PERM_SRC_ID_7__SRCID 0x00ff | 607 | #define PERM_SRC_ID_7__SRCID 0x00ff |
608 | #define PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE 0x0800 | 608 | #define PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE 0x0800 |
609 | #define PERM_SRC_ID_7__WRITE_ACTIVE 0x2000 | 609 | #define PERM_SRC_ID_7__WRITE_ACTIVE 0x2000 |
610 | #define PERM_SRC_ID_7__READ_ACTIVE 0x4000 | 610 | #define PERM_SRC_ID_7__READ_ACTIVE 0x4000 |
@@ -620,47 +620,6 @@ | |||
620 | #define MIN_MAX_BANK_7__MIN_VALUE 0x0003 | 620 | #define MIN_MAX_BANK_7__MIN_VALUE 0x0003 |
621 | #define MIN_MAX_BANK_7__MAX_VALUE 0x000c | 621 | #define MIN_MAX_BANK_7__MAX_VALUE 0x000c |
622 | 622 | ||
623 | /* flash.h */ | ||
624 | struct device_info_tag { | ||
625 | uint16_t wDeviceMaker; | ||
626 | uint16_t wDeviceID; | ||
627 | uint8_t bDeviceParam0; | ||
628 | uint8_t bDeviceParam1; | ||
629 | uint8_t bDeviceParam2; | ||
630 | uint32_t wDeviceType; | ||
631 | uint32_t wSpectraStartBlock; | ||
632 | uint32_t wSpectraEndBlock; | ||
633 | uint32_t wTotalBlocks; | ||
634 | uint16_t wPagesPerBlock; | ||
635 | uint16_t wPageSize; | ||
636 | uint16_t wPageDataSize; | ||
637 | uint16_t wPageSpareSize; | ||
638 | uint16_t wNumPageSpareFlag; | ||
639 | uint16_t wECCBytesPerSector; | ||
640 | uint32_t wBlockSize; | ||
641 | uint32_t wBlockDataSize; | ||
642 | uint32_t wDataBlockNum; | ||
643 | uint8_t bPlaneNum; | ||
644 | uint16_t wDeviceMainAreaSize; | ||
645 | uint16_t wDeviceSpareAreaSize; | ||
646 | uint16_t wDevicesConnected; | ||
647 | uint16_t wDeviceWidth; | ||
648 | uint16_t wHWRevision; | ||
649 | uint16_t wHWFeatures; | ||
650 | |||
651 | uint16_t wONFIDevFeatures; | ||
652 | uint16_t wONFIOptCommands; | ||
653 | uint16_t wONFITimingMode; | ||
654 | uint16_t wONFIPgmCacheTimingMode; | ||
655 | |||
656 | uint16_t MLCDevice; | ||
657 | uint16_t wSpareSkipBytes; | ||
658 | |||
659 | uint8_t nBitsInPageNumber; | ||
660 | uint8_t nBitsInPageDataSize; | ||
661 | uint8_t nBitsInBlockDataSize; | ||
662 | }; | ||
663 | |||
664 | /* ffsdefs.h */ | 623 | /* ffsdefs.h */ |
665 | #define CLEAR 0 /*use this to clear a field instead of "fail"*/ | 624 | #define CLEAR 0 /*use this to clear a field instead of "fail"*/ |
666 | #define SET 1 /*use this to set a field instead of "pass"*/ | 625 | #define SET 1 /*use this to set a field instead of "pass"*/ |
@@ -684,11 +643,11 @@ struct device_info_tag { | |||
684 | #define NAND_DBG_TRACE 3 | 643 | #define NAND_DBG_TRACE 3 |
685 | 644 | ||
686 | #ifdef VERBOSE | 645 | #ifdef VERBOSE |
687 | #define nand_dbg_print(level, args...) \ | 646 | #define nand_dbg_print(level, args...) \ |
688 | do { \ | 647 | do { \ |
689 | if (level <= nand_debug_level) \ | 648 | if (level <= nand_debug_level) \ |
690 | printk(KERN_ALERT args); \ | 649 | printk(KERN_ALERT args); \ |
691 | } while (0) | 650 | } while (0) |
692 | #else | 651 | #else |
693 | #define nand_dbg_print(level, args...) | 652 | #define nand_dbg_print(level, args...) |
694 | #endif | 653 | #endif |
@@ -772,10 +731,9 @@ struct device_info_tag { | |||
772 | #define ECC_SECTOR_SIZE 512 | 731 | #define ECC_SECTOR_SIZE 512 |
773 | #define LLD_MAX_FLASH_BANKS 4 | 732 | #define LLD_MAX_FLASH_BANKS 4 |
774 | 733 | ||
775 | #define DENALI_BUF_SIZE NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE | 734 | #define DENALI_BUF_SIZE (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) |
776 | 735 | ||
777 | struct nand_buf | 736 | struct nand_buf { |
778 | { | ||
779 | int head; | 737 | int head; |
780 | int tail; | 738 | int tail; |
781 | uint8_t buf[DENALI_BUF_SIZE]; | 739 | uint8_t buf[DENALI_BUF_SIZE]; |
@@ -788,7 +746,6 @@ struct nand_buf | |||
788 | struct denali_nand_info { | 746 | struct denali_nand_info { |
789 | struct mtd_info mtd; | 747 | struct mtd_info mtd; |
790 | struct nand_chip nand; | 748 | struct nand_chip nand; |
791 | struct device_info_tag dev_info; | ||
792 | int flash_bank; /* currently selected chip */ | 749 | int flash_bank; /* currently selected chip */ |
793 | int status; | 750 | int status; |
794 | int platform; | 751 | int platform; |
@@ -806,11 +763,12 @@ struct denali_nand_info { | |||
806 | uint32_t irq_status; | 763 | uint32_t irq_status; |
807 | int irq_debug_array[32]; | 764 | int irq_debug_array[32]; |
808 | int idx; | 765 | int idx; |
809 | }; | ||
810 | 766 | ||
811 | static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali); | 767 | uint32_t devnum; /* represent how many nands connected */ |
812 | static uint16_t NAND_Read_Device_ID(struct denali_nand_info *denali); | 768 | uint32_t fwblks; /* represent how many blocks FW used */ |
813 | static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *denali, uint16_t INT_ENABLE); | 769 | uint32_t totalblks; |
770 | uint32_t blksperchip; | ||
771 | uint32_t bbtskipbytes; | ||
772 | }; | ||
814 | 773 | ||
815 | #endif /*_LLD_NAND_*/ | 774 | #endif /*_LLD_NAND_*/ |
816 | |||
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 47067bc98248..b7f8de7b2780 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/mtd/mtd.h> | 29 | #include <linux/mtd/mtd.h> |
30 | #include <linux/mtd/nand.h> | 30 | #include <linux/mtd/nand.h> |
31 | #include <linux/mtd/doc2000.h> | 31 | #include <linux/mtd/doc2000.h> |
32 | #include <linux/mtd/compatmac.h> | ||
33 | #include <linux/mtd/partitions.h> | 32 | #include <linux/mtd/partitions.h> |
34 | #include <linux/mtd/inftl.h> | 33 | #include <linux/mtd/inftl.h> |
35 | 34 | ||
@@ -146,6 +145,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
146 | uint8_t parity; | 145 | uint8_t parity; |
147 | uint16_t ds[4], s[5], tmp, errval[8], syn[4]; | 146 | uint16_t ds[4], s[5], tmp, errval[8], syn[4]; |
148 | 147 | ||
148 | memset(syn, 0, sizeof(syn)); | ||
149 | /* Convert the ecc bytes into words */ | 149 | /* Convert the ecc bytes into words */ |
150 | ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8); | 150 | ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8); |
151 | ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6); | 151 | ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6); |
@@ -169,9 +169,9 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
169 | s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; | 169 | s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; |
170 | } | 170 | } |
171 | 171 | ||
172 | /* Calc s[i] = s[i] / alpha^(v + i) */ | 172 | /* Calc syn[i] = s[i] / alpha^(v + i) */ |
173 | for (i = 0; i < NROOTS; i++) { | 173 | for (i = 0; i < NROOTS; i++) { |
174 | if (syn[i]) | 174 | if (s[i]) |
175 | syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); | 175 | syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); |
176 | } | 176 | } |
177 | /* Call the decoder library */ | 177 | /* Call the decoder library */ |
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 0d76b169482f..fcf8ceb277d4 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -39,60 +39,96 @@ | |||
39 | 39 | ||
40 | #define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) | 40 | #define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) |
41 | #define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21()) | 41 | #define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21()) |
42 | #define nfc_is_v3_2() cpu_is_mx51() | ||
43 | #define nfc_is_v3() nfc_is_v3_2() | ||
42 | 44 | ||
43 | /* Addresses for NFC registers */ | 45 | /* Addresses for NFC registers */ |
44 | #define NFC_BUF_SIZE 0xE00 | 46 | #define NFC_V1_V2_BUF_SIZE (host->regs + 0x00) |
45 | #define NFC_BUF_ADDR 0xE04 | 47 | #define NFC_V1_V2_BUF_ADDR (host->regs + 0x04) |
46 | #define NFC_FLASH_ADDR 0xE06 | 48 | #define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06) |
47 | #define NFC_FLASH_CMD 0xE08 | 49 | #define NFC_V1_V2_FLASH_CMD (host->regs + 0x08) |
48 | #define NFC_CONFIG 0xE0A | 50 | #define NFC_V1_V2_CONFIG (host->regs + 0x0a) |
49 | #define NFC_ECC_STATUS_RESULT 0xE0C | 51 | #define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c) |
50 | #define NFC_RSLTMAIN_AREA 0xE0E | 52 | #define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e) |
51 | #define NFC_RSLTSPARE_AREA 0xE10 | 53 | #define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10) |
52 | #define NFC_WRPROT 0xE12 | 54 | #define NFC_V1_V2_WRPROT (host->regs + 0x12) |
53 | #define NFC_V1_UNLOCKSTART_BLKADDR 0xe14 | 55 | #define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14) |
54 | #define NFC_V1_UNLOCKEND_BLKADDR 0xe16 | 56 | #define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16) |
55 | #define NFC_V21_UNLOCKSTART_BLKADDR 0xe20 | 57 | #define NFC_V21_UNLOCKSTART_BLKADDR (host->regs + 0x20) |
56 | #define NFC_V21_UNLOCKEND_BLKADDR 0xe22 | 58 | #define NFC_V21_UNLOCKEND_BLKADDR (host->regs + 0x22) |
57 | #define NFC_NF_WRPRST 0xE18 | 59 | #define NFC_V1_V2_NF_WRPRST (host->regs + 0x18) |
58 | #define NFC_CONFIG1 0xE1A | 60 | #define NFC_V1_V2_CONFIG1 (host->regs + 0x1a) |
59 | #define NFC_CONFIG2 0xE1C | 61 | #define NFC_V1_V2_CONFIG2 (host->regs + 0x1c) |
60 | 62 | ||
61 | /* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register | 63 | #define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0) |
62 | * for Command operation */ | 64 | #define NFC_V1_V2_CONFIG1_SP_EN (1 << 2) |
63 | #define NFC_CMD 0x1 | 65 | #define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3) |
64 | 66 | #define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4) | |
65 | /* Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register | 67 | #define NFC_V1_V2_CONFIG1_BIG (1 << 5) |
66 | * for Address operation */ | 68 | #define NFC_V1_V2_CONFIG1_RST (1 << 6) |
67 | #define NFC_ADDR 0x2 | 69 | #define NFC_V1_V2_CONFIG1_CE (1 << 7) |
68 | 70 | #define NFC_V1_V2_CONFIG1_ONE_CYCLE (1 << 8) | |
69 | /* Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register | 71 | |
70 | * for Input operation */ | 72 | #define NFC_V1_V2_CONFIG2_INT (1 << 15) |
71 | #define NFC_INPUT 0x4 | 73 | |
72 | 74 | /* | |
73 | /* Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register | 75 | * Operation modes for the NFC. Valid for v1, v2 and v3 |
74 | * for Data Output operation */ | 76 | * type controllers. |
75 | #define NFC_OUTPUT 0x8 | 77 | */ |
76 | 78 | #define NFC_CMD (1 << 0) | |
77 | /* Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register | 79 | #define NFC_ADDR (1 << 1) |
78 | * for Read ID operation */ | 80 | #define NFC_INPUT (1 << 2) |
79 | #define NFC_ID 0x10 | 81 | #define NFC_OUTPUT (1 << 3) |
80 | 82 | #define NFC_ID (1 << 4) | |
81 | /* Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register | 83 | #define NFC_STATUS (1 << 5) |
82 | * for Read Status operation */ | 84 | |
83 | #define NFC_STATUS 0x20 | 85 | #define NFC_V3_FLASH_CMD (host->regs_axi + 0x00) |
84 | 86 | #define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04) | |
85 | /* Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read | 87 | |
86 | * Status operation */ | 88 | #define NFC_V3_CONFIG1 (host->regs_axi + 0x34) |
87 | #define NFC_INT 0x8000 | 89 | #define NFC_V3_CONFIG1_SP_EN (1 << 0) |
88 | 90 | #define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4) | |
89 | #define NFC_SP_EN (1 << 2) | 91 | |
90 | #define NFC_ECC_EN (1 << 3) | 92 | #define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38) |
91 | #define NFC_INT_MSK (1 << 4) | 93 | |
92 | #define NFC_BIG (1 << 5) | 94 | #define NFC_V3_LAUNCH (host->regs_axi + 0x40) |
93 | #define NFC_RST (1 << 6) | 95 | |
94 | #define NFC_CE (1 << 7) | 96 | #define NFC_V3_WRPROT (host->regs_ip + 0x0) |
95 | #define NFC_ONE_CYCLE (1 << 8) | 97 | #define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0) |
98 | #define NFC_V3_WRPROT_LOCK (1 << 1) | ||
99 | #define NFC_V3_WRPROT_UNLOCK (1 << 2) | ||
100 | #define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6) | ||
101 | |||
102 | #define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04) | ||
103 | |||
104 | #define NFC_V3_CONFIG2 (host->regs_ip + 0x24) | ||
105 | #define NFC_V3_CONFIG2_PS_512 (0 << 0) | ||
106 | #define NFC_V3_CONFIG2_PS_2048 (1 << 0) | ||
107 | #define NFC_V3_CONFIG2_PS_4096 (2 << 0) | ||
108 | #define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2) | ||
109 | #define NFC_V3_CONFIG2_ECC_EN (1 << 3) | ||
110 | #define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4) | ||
111 | #define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5) | ||
112 | #define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6) | ||
113 | #define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7) | ||
114 | #define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12) | ||
115 | #define NFC_V3_CONFIG2_INT_MSK (1 << 15) | ||
116 | #define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24) | ||
117 | #define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16) | ||
118 | |||
119 | #define NFC_V3_CONFIG3 (host->regs_ip + 0x28) | ||
120 | #define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0) | ||
121 | #define NFC_V3_CONFIG3_FW8 (1 << 3) | ||
122 | #define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8) | ||
123 | #define NFC_V3_CONFIG3_NUM_OF_DEVICES(x) (((x) & 0x7) << 12) | ||
124 | #define NFC_V3_CONFIG3_RBB_MODE (1 << 15) | ||
125 | #define NFC_V3_CONFIG3_NO_SDMA (1 << 20) | ||
126 | |||
127 | #define NFC_V3_IPC (host->regs_ip + 0x2C) | ||
128 | #define NFC_V3_IPC_CREQ (1 << 0) | ||
129 | #define NFC_V3_IPC_INT (1 << 31) | ||
130 | |||
131 | #define NFC_V3_DELAY_LINE (host->regs_ip + 0x34) | ||
96 | 132 | ||
97 | struct mxc_nand_host { | 133 | struct mxc_nand_host { |
98 | struct mtd_info mtd; | 134 | struct mtd_info mtd; |
@@ -102,20 +138,30 @@ struct mxc_nand_host { | |||
102 | 138 | ||
103 | void *spare0; | 139 | void *spare0; |
104 | void *main_area0; | 140 | void *main_area0; |
105 | void *main_area1; | ||
106 | 141 | ||
107 | void __iomem *base; | 142 | void __iomem *base; |
108 | void __iomem *regs; | 143 | void __iomem *regs; |
144 | void __iomem *regs_axi; | ||
145 | void __iomem *regs_ip; | ||
109 | int status_request; | 146 | int status_request; |
110 | struct clk *clk; | 147 | struct clk *clk; |
111 | int clk_act; | 148 | int clk_act; |
112 | int irq; | 149 | int irq; |
150 | int eccsize; | ||
113 | 151 | ||
114 | wait_queue_head_t irq_waitq; | 152 | wait_queue_head_t irq_waitq; |
115 | 153 | ||
116 | uint8_t *data_buf; | 154 | uint8_t *data_buf; |
117 | unsigned int buf_start; | 155 | unsigned int buf_start; |
118 | int spare_len; | 156 | int spare_len; |
157 | |||
158 | void (*preset)(struct mtd_info *); | ||
159 | void (*send_cmd)(struct mxc_nand_host *, uint16_t, int); | ||
160 | void (*send_addr)(struct mxc_nand_host *, uint16_t, int); | ||
161 | void (*send_page)(struct mtd_info *, unsigned int); | ||
162 | void (*send_read_id)(struct mxc_nand_host *); | ||
163 | uint16_t (*get_dev_status)(struct mxc_nand_host *); | ||
164 | int (*check_int)(struct mxc_nand_host *); | ||
119 | }; | 165 | }; |
120 | 166 | ||
121 | /* OOB placement block for use with hardware ecc generation */ | 167 | /* OOB placement block for use with hardware ecc generation */ |
@@ -175,34 +221,52 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | |||
175 | return IRQ_HANDLED; | 221 | return IRQ_HANDLED; |
176 | } | 222 | } |
177 | 223 | ||
224 | static int check_int_v3(struct mxc_nand_host *host) | ||
225 | { | ||
226 | uint32_t tmp; | ||
227 | |||
228 | tmp = readl(NFC_V3_IPC); | ||
229 | if (!(tmp & NFC_V3_IPC_INT)) | ||
230 | return 0; | ||
231 | |||
232 | tmp &= ~NFC_V3_IPC_INT; | ||
233 | writel(tmp, NFC_V3_IPC); | ||
234 | |||
235 | return 1; | ||
236 | } | ||
237 | |||
238 | static int check_int_v1_v2(struct mxc_nand_host *host) | ||
239 | { | ||
240 | uint32_t tmp; | ||
241 | |||
242 | tmp = readw(NFC_V1_V2_CONFIG2); | ||
243 | if (!(tmp & NFC_V1_V2_CONFIG2_INT)) | ||
244 | return 0; | ||
245 | |||
246 | writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); | ||
247 | |||
248 | return 1; | ||
249 | } | ||
250 | |||
178 | /* This function polls the NANDFC to wait for the basic operation to | 251 | /* This function polls the NANDFC to wait for the basic operation to |
179 | * complete by checking the INT bit of config2 register. | 252 | * complete by checking the INT bit of config2 register. |
180 | */ | 253 | */ |
181 | static void wait_op_done(struct mxc_nand_host *host, int useirq) | 254 | static void wait_op_done(struct mxc_nand_host *host, int useirq) |
182 | { | 255 | { |
183 | uint16_t tmp; | ||
184 | int max_retries = 8000; | 256 | int max_retries = 8000; |
185 | 257 | ||
186 | if (useirq) { | 258 | if (useirq) { |
187 | if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) { | 259 | if (!host->check_int(host)) { |
188 | 260 | ||
189 | enable_irq(host->irq); | 261 | enable_irq(host->irq); |
190 | 262 | ||
191 | wait_event(host->irq_waitq, | 263 | wait_event(host->irq_waitq, host->check_int(host)); |
192 | readw(host->regs + NFC_CONFIG2) & NFC_INT); | ||
193 | |||
194 | tmp = readw(host->regs + NFC_CONFIG2); | ||
195 | tmp &= ~NFC_INT; | ||
196 | writew(tmp, host->regs + NFC_CONFIG2); | ||
197 | } | 264 | } |
198 | } else { | 265 | } else { |
199 | while (max_retries-- > 0) { | 266 | while (max_retries-- > 0) { |
200 | if (readw(host->regs + NFC_CONFIG2) & NFC_INT) { | 267 | if (host->check_int(host)) |
201 | tmp = readw(host->regs + NFC_CONFIG2); | ||
202 | tmp &= ~NFC_INT; | ||
203 | writew(tmp, host->regs + NFC_CONFIG2); | ||
204 | break; | 268 | break; |
205 | } | 269 | |
206 | udelay(1); | 270 | udelay(1); |
207 | } | 271 | } |
208 | if (max_retries < 0) | 272 | if (max_retries < 0) |
@@ -211,21 +275,33 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq) | |||
211 | } | 275 | } |
212 | } | 276 | } |
213 | 277 | ||
278 | static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq) | ||
279 | { | ||
280 | /* fill command */ | ||
281 | writel(cmd, NFC_V3_FLASH_CMD); | ||
282 | |||
283 | /* send out command */ | ||
284 | writel(NFC_CMD, NFC_V3_LAUNCH); | ||
285 | |||
286 | /* Wait for operation to complete */ | ||
287 | wait_op_done(host, useirq); | ||
288 | } | ||
289 | |||
214 | /* This function issues the specified command to the NAND device and | 290 | /* This function issues the specified command to the NAND device and |
215 | * waits for completion. */ | 291 | * waits for completion. */ |
216 | static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq) | 292 | static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq) |
217 | { | 293 | { |
218 | DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq); | 294 | DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq); |
219 | 295 | ||
220 | writew(cmd, host->regs + NFC_FLASH_CMD); | 296 | writew(cmd, NFC_V1_V2_FLASH_CMD); |
221 | writew(NFC_CMD, host->regs + NFC_CONFIG2); | 297 | writew(NFC_CMD, NFC_V1_V2_CONFIG2); |
222 | 298 | ||
223 | if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { | 299 | if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { |
224 | int max_retries = 100; | 300 | int max_retries = 100; |
225 | /* Reset completion is indicated by NFC_CONFIG2 */ | 301 | /* Reset completion is indicated by NFC_CONFIG2 */ |
226 | /* being set to 0 */ | 302 | /* being set to 0 */ |
227 | while (max_retries-- > 0) { | 303 | while (max_retries-- > 0) { |
228 | if (readw(host->regs + NFC_CONFIG2) == 0) { | 304 | if (readw(NFC_V1_V2_CONFIG2) == 0) { |
229 | break; | 305 | break; |
230 | } | 306 | } |
231 | udelay(1); | 307 | udelay(1); |
@@ -239,21 +315,48 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq) | |||
239 | } | 315 | } |
240 | } | 316 | } |
241 | 317 | ||
318 | static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast) | ||
319 | { | ||
320 | /* fill address */ | ||
321 | writel(addr, NFC_V3_FLASH_ADDR0); | ||
322 | |||
323 | /* send out address */ | ||
324 | writel(NFC_ADDR, NFC_V3_LAUNCH); | ||
325 | |||
326 | wait_op_done(host, 0); | ||
327 | } | ||
328 | |||
242 | /* This function sends an address (or partial address) to the | 329 | /* This function sends an address (or partial address) to the |
243 | * NAND device. The address is used to select the source/destination for | 330 | * NAND device. The address is used to select the source/destination for |
244 | * a NAND command. */ | 331 | * a NAND command. */ |
245 | static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast) | 332 | static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast) |
246 | { | 333 | { |
247 | DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast); | 334 | DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast); |
248 | 335 | ||
249 | writew(addr, host->regs + NFC_FLASH_ADDR); | 336 | writew(addr, NFC_V1_V2_FLASH_ADDR); |
250 | writew(NFC_ADDR, host->regs + NFC_CONFIG2); | 337 | writew(NFC_ADDR, NFC_V1_V2_CONFIG2); |
251 | 338 | ||
252 | /* Wait for operation to complete */ | 339 | /* Wait for operation to complete */ |
253 | wait_op_done(host, islast); | 340 | wait_op_done(host, islast); |
254 | } | 341 | } |
255 | 342 | ||
256 | static void send_page(struct mtd_info *mtd, unsigned int ops) | 343 | static void send_page_v3(struct mtd_info *mtd, unsigned int ops) |
344 | { | ||
345 | struct nand_chip *nand_chip = mtd->priv; | ||
346 | struct mxc_nand_host *host = nand_chip->priv; | ||
347 | uint32_t tmp; | ||
348 | |||
349 | tmp = readl(NFC_V3_CONFIG1); | ||
350 | tmp &= ~(7 << 4); | ||
351 | writel(tmp, NFC_V3_CONFIG1); | ||
352 | |||
353 | /* transfer data from NFC ram to nand */ | ||
354 | writel(ops, NFC_V3_LAUNCH); | ||
355 | |||
356 | wait_op_done(host, false); | ||
357 | } | ||
358 | |||
359 | static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops) | ||
257 | { | 360 | { |
258 | struct nand_chip *nand_chip = mtd->priv; | 361 | struct nand_chip *nand_chip = mtd->priv; |
259 | struct mxc_nand_host *host = nand_chip->priv; | 362 | struct mxc_nand_host *host = nand_chip->priv; |
@@ -267,24 +370,34 @@ static void send_page(struct mtd_info *mtd, unsigned int ops) | |||
267 | for (i = 0; i < bufs; i++) { | 370 | for (i = 0; i < bufs; i++) { |
268 | 371 | ||
269 | /* NANDFC buffer 0 is used for page read/write */ | 372 | /* NANDFC buffer 0 is used for page read/write */ |
270 | writew(i, host->regs + NFC_BUF_ADDR); | 373 | writew(i, NFC_V1_V2_BUF_ADDR); |
271 | 374 | ||
272 | writew(ops, host->regs + NFC_CONFIG2); | 375 | writew(ops, NFC_V1_V2_CONFIG2); |
273 | 376 | ||
274 | /* Wait for operation to complete */ | 377 | /* Wait for operation to complete */ |
275 | wait_op_done(host, true); | 378 | wait_op_done(host, true); |
276 | } | 379 | } |
277 | } | 380 | } |
278 | 381 | ||
382 | static void send_read_id_v3(struct mxc_nand_host *host) | ||
383 | { | ||
384 | /* Read ID into main buffer */ | ||
385 | writel(NFC_ID, NFC_V3_LAUNCH); | ||
386 | |||
387 | wait_op_done(host, true); | ||
388 | |||
389 | memcpy(host->data_buf, host->main_area0, 16); | ||
390 | } | ||
391 | |||
279 | /* Request the NANDFC to perform a read of the NAND device ID. */ | 392 | /* Request the NANDFC to perform a read of the NAND device ID. */ |
280 | static void send_read_id(struct mxc_nand_host *host) | 393 | static void send_read_id_v1_v2(struct mxc_nand_host *host) |
281 | { | 394 | { |
282 | struct nand_chip *this = &host->nand; | 395 | struct nand_chip *this = &host->nand; |
283 | 396 | ||
284 | /* NANDFC buffer 0 is used for device ID output */ | 397 | /* NANDFC buffer 0 is used for device ID output */ |
285 | writew(0x0, host->regs + NFC_BUF_ADDR); | 398 | writew(0x0, NFC_V1_V2_BUF_ADDR); |
286 | 399 | ||
287 | writew(NFC_ID, host->regs + NFC_CONFIG2); | 400 | writew(NFC_ID, NFC_V1_V2_CONFIG2); |
288 | 401 | ||
289 | /* Wait for operation to complete */ | 402 | /* Wait for operation to complete */ |
290 | wait_op_done(host, true); | 403 | wait_op_done(host, true); |
@@ -301,29 +414,36 @@ static void send_read_id(struct mxc_nand_host *host) | |||
301 | memcpy(host->data_buf, host->main_area0, 16); | 414 | memcpy(host->data_buf, host->main_area0, 16); |
302 | } | 415 | } |
303 | 416 | ||
417 | static uint16_t get_dev_status_v3(struct mxc_nand_host *host) | ||
418 | { | ||
419 | writew(NFC_STATUS, NFC_V3_LAUNCH); | ||
420 | wait_op_done(host, true); | ||
421 | |||
422 | return readl(NFC_V3_CONFIG1) >> 16; | ||
423 | } | ||
424 | |||
304 | /* This function requests the NANDFC to perform a read of the | 425 | /* This function requests the NANDFC to perform a read of the |
305 | * NAND device status and returns the current status. */ | 426 | * NAND device status and returns the current status. */ |
306 | static uint16_t get_dev_status(struct mxc_nand_host *host) | 427 | static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host) |
307 | { | 428 | { |
308 | void __iomem *main_buf = host->main_area1; | 429 | void __iomem *main_buf = host->main_area0; |
309 | uint32_t store; | 430 | uint32_t store; |
310 | uint16_t ret; | 431 | uint16_t ret; |
311 | /* Issue status request to NAND device */ | ||
312 | 432 | ||
313 | /* store the main area1 first word, later do recovery */ | 433 | writew(0x0, NFC_V1_V2_BUF_ADDR); |
314 | store = readl(main_buf); | ||
315 | /* NANDFC buffer 1 is used for device status to prevent | ||
316 | * corruption of read/write buffer on status requests. */ | ||
317 | writew(1, host->regs + NFC_BUF_ADDR); | ||
318 | 434 | ||
319 | writew(NFC_STATUS, host->regs + NFC_CONFIG2); | 435 | /* |
436 | * The device status is stored in main_area0. To | ||
437 | * prevent corruption of the buffer save the value | ||
438 | * and restore it afterwards. | ||
439 | */ | ||
440 | store = readl(main_buf); | ||
320 | 441 | ||
321 | /* Wait for operation to complete */ | 442 | writew(NFC_STATUS, NFC_V1_V2_CONFIG2); |
322 | wait_op_done(host, true); | 443 | wait_op_done(host, true); |
323 | 444 | ||
324 | /* Status is placed in first word of main buffer */ | ||
325 | /* get status, then recovery area 1 data */ | ||
326 | ret = readw(main_buf); | 445 | ret = readw(main_buf); |
446 | |||
327 | writel(store, main_buf); | 447 | writel(store, main_buf); |
328 | 448 | ||
329 | return ret; | 449 | return ret; |
@@ -347,7 +467,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) | |||
347 | */ | 467 | */ |
348 | } | 468 | } |
349 | 469 | ||
350 | static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, | 470 | static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, |
351 | u_char *read_ecc, u_char *calc_ecc) | 471 | u_char *read_ecc, u_char *calc_ecc) |
352 | { | 472 | { |
353 | struct nand_chip *nand_chip = mtd->priv; | 473 | struct nand_chip *nand_chip = mtd->priv; |
@@ -358,7 +478,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, | |||
358 | * additional correction. 2-Bit errors cannot be corrected by | 478 | * additional correction. 2-Bit errors cannot be corrected by |
359 | * HW ECC, so we need to return failure | 479 | * HW ECC, so we need to return failure |
360 | */ | 480 | */ |
361 | uint16_t ecc_status = readw(host->regs + NFC_ECC_STATUS_RESULT); | 481 | uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT); |
362 | 482 | ||
363 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { | 483 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { |
364 | DEBUG(MTD_DEBUG_LEVEL0, | 484 | DEBUG(MTD_DEBUG_LEVEL0, |
@@ -369,6 +489,43 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, | |||
369 | return 0; | 489 | return 0; |
370 | } | 490 | } |
371 | 491 | ||
492 | static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, | ||
493 | u_char *read_ecc, u_char *calc_ecc) | ||
494 | { | ||
495 | struct nand_chip *nand_chip = mtd->priv; | ||
496 | struct mxc_nand_host *host = nand_chip->priv; | ||
497 | u32 ecc_stat, err; | ||
498 | int no_subpages = 1; | ||
499 | int ret = 0; | ||
500 | u8 ecc_bit_mask, err_limit; | ||
501 | |||
502 | ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf; | ||
503 | err_limit = (host->eccsize == 4) ? 0x4 : 0x8; | ||
504 | |||
505 | no_subpages = mtd->writesize >> 9; | ||
506 | |||
507 | if (nfc_is_v21()) | ||
508 | ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT); | ||
509 | else | ||
510 | ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT); | ||
511 | |||
512 | do { | ||
513 | err = ecc_stat & ecc_bit_mask; | ||
514 | if (err > err_limit) { | ||
515 | printk(KERN_WARNING "UnCorrectable RS-ECC Error\n"); | ||
516 | return -1; | ||
517 | } else { | ||
518 | ret += err; | ||
519 | } | ||
520 | ecc_stat >>= 4; | ||
521 | } while (--no_subpages); | ||
522 | |||
523 | mtd->ecc_stats.corrected += ret; | ||
524 | pr_debug("%d Symbol Correctable RS-ECC Error\n", ret); | ||
525 | |||
526 | return ret; | ||
527 | } | ||
528 | |||
372 | static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, | 529 | static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, |
373 | u_char *ecc_code) | 530 | u_char *ecc_code) |
374 | { | 531 | { |
@@ -383,7 +540,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) | |||
383 | 540 | ||
384 | /* Check for status request */ | 541 | /* Check for status request */ |
385 | if (host->status_request) | 542 | if (host->status_request) |
386 | return get_dev_status(host) & 0xFF; | 543 | return host->get_dev_status(host) & 0xFF; |
387 | 544 | ||
388 | ret = *(uint8_t *)(host->data_buf + host->buf_start); | 545 | ret = *(uint8_t *)(host->data_buf + host->buf_start); |
389 | host->buf_start++; | 546 | host->buf_start++; |
@@ -519,71 +676,163 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) | |||
519 | * we will used the saved column address to index into | 676 | * we will used the saved column address to index into |
520 | * the full page. | 677 | * the full page. |
521 | */ | 678 | */ |
522 | send_addr(host, 0, page_addr == -1); | 679 | host->send_addr(host, 0, page_addr == -1); |
523 | if (mtd->writesize > 512) | 680 | if (mtd->writesize > 512) |
524 | /* another col addr cycle for 2k page */ | 681 | /* another col addr cycle for 2k page */ |
525 | send_addr(host, 0, false); | 682 | host->send_addr(host, 0, false); |
526 | } | 683 | } |
527 | 684 | ||
528 | /* Write out page address, if necessary */ | 685 | /* Write out page address, if necessary */ |
529 | if (page_addr != -1) { | 686 | if (page_addr != -1) { |
530 | /* paddr_0 - p_addr_7 */ | 687 | /* paddr_0 - p_addr_7 */ |
531 | send_addr(host, (page_addr & 0xff), false); | 688 | host->send_addr(host, (page_addr & 0xff), false); |
532 | 689 | ||
533 | if (mtd->writesize > 512) { | 690 | if (mtd->writesize > 512) { |
534 | if (mtd->size >= 0x10000000) { | 691 | if (mtd->size >= 0x10000000) { |
535 | /* paddr_8 - paddr_15 */ | 692 | /* paddr_8 - paddr_15 */ |
536 | send_addr(host, (page_addr >> 8) & 0xff, false); | 693 | host->send_addr(host, (page_addr >> 8) & 0xff, false); |
537 | send_addr(host, (page_addr >> 16) & 0xff, true); | 694 | host->send_addr(host, (page_addr >> 16) & 0xff, true); |
538 | } else | 695 | } else |
539 | /* paddr_8 - paddr_15 */ | 696 | /* paddr_8 - paddr_15 */ |
540 | send_addr(host, (page_addr >> 8) & 0xff, true); | 697 | host->send_addr(host, (page_addr >> 8) & 0xff, true); |
541 | } else { | 698 | } else { |
542 | /* One more address cycle for higher density devices */ | 699 | /* One more address cycle for higher density devices */ |
543 | if (mtd->size >= 0x4000000) { | 700 | if (mtd->size >= 0x4000000) { |
544 | /* paddr_8 - paddr_15 */ | 701 | /* paddr_8 - paddr_15 */ |
545 | send_addr(host, (page_addr >> 8) & 0xff, false); | 702 | host->send_addr(host, (page_addr >> 8) & 0xff, false); |
546 | send_addr(host, (page_addr >> 16) & 0xff, true); | 703 | host->send_addr(host, (page_addr >> 16) & 0xff, true); |
547 | } else | 704 | } else |
548 | /* paddr_8 - paddr_15 */ | 705 | /* paddr_8 - paddr_15 */ |
549 | send_addr(host, (page_addr >> 8) & 0xff, true); | 706 | host->send_addr(host, (page_addr >> 8) & 0xff, true); |
550 | } | 707 | } |
551 | } | 708 | } |
552 | } | 709 | } |
553 | 710 | ||
554 | static void preset(struct mtd_info *mtd) | 711 | /* |
712 | * v2 and v3 type controllers can do 4bit or 8bit ecc depending | ||
713 | * on how much oob the nand chip has. For 8bit ecc we need at least | ||
714 | * 26 bytes of oob data per 512 byte block. | ||
715 | */ | ||
716 | static int get_eccsize(struct mtd_info *mtd) | ||
717 | { | ||
718 | int oobbytes_per_512 = 0; | ||
719 | |||
720 | oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize; | ||
721 | |||
722 | if (oobbytes_per_512 < 26) | ||
723 | return 4; | ||
724 | else | ||
725 | return 8; | ||
726 | } | ||
727 | |||
728 | static void preset_v1_v2(struct mtd_info *mtd) | ||
555 | { | 729 | { |
556 | struct nand_chip *nand_chip = mtd->priv; | 730 | struct nand_chip *nand_chip = mtd->priv; |
557 | struct mxc_nand_host *host = nand_chip->priv; | 731 | struct mxc_nand_host *host = nand_chip->priv; |
558 | uint16_t tmp; | 732 | uint16_t tmp; |
559 | 733 | ||
560 | /* enable interrupt, disable spare enable */ | 734 | /* enable interrupt, disable spare enable */ |
561 | tmp = readw(host->regs + NFC_CONFIG1); | 735 | tmp = readw(NFC_V1_V2_CONFIG1); |
562 | tmp &= ~NFC_INT_MSK; | 736 | tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK; |
563 | tmp &= ~NFC_SP_EN; | 737 | tmp &= ~NFC_V1_V2_CONFIG1_SP_EN; |
564 | if (nand_chip->ecc.mode == NAND_ECC_HW) { | 738 | if (nand_chip->ecc.mode == NAND_ECC_HW) { |
565 | tmp |= NFC_ECC_EN; | 739 | tmp |= NFC_V1_V2_CONFIG1_ECC_EN; |
740 | } else { | ||
741 | tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN; | ||
742 | } | ||
743 | |||
744 | if (nfc_is_v21() && mtd->writesize) { | ||
745 | host->eccsize = get_eccsize(mtd); | ||
746 | if (host->eccsize == 4) | ||
747 | tmp |= NFC_V2_CONFIG1_ECC_MODE_4; | ||
566 | } else { | 748 | } else { |
567 | tmp &= ~NFC_ECC_EN; | 749 | host->eccsize = 1; |
568 | } | 750 | } |
569 | writew(tmp, host->regs + NFC_CONFIG1); | 751 | |
752 | writew(tmp, NFC_V1_V2_CONFIG1); | ||
570 | /* preset operation */ | 753 | /* preset operation */ |
571 | 754 | ||
572 | /* Unlock the internal RAM Buffer */ | 755 | /* Unlock the internal RAM Buffer */ |
573 | writew(0x2, host->regs + NFC_CONFIG); | 756 | writew(0x2, NFC_V1_V2_CONFIG); |
574 | 757 | ||
575 | /* Blocks to be unlocked */ | 758 | /* Blocks to be unlocked */ |
576 | if (nfc_is_v21()) { | 759 | if (nfc_is_v21()) { |
577 | writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR); | 760 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR); |
578 | writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR); | 761 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR); |
579 | } else if (nfc_is_v1()) { | 762 | } else if (nfc_is_v1()) { |
580 | writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR); | 763 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); |
581 | writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR); | 764 | writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR); |
582 | } else | 765 | } else |
583 | BUG(); | 766 | BUG(); |
584 | 767 | ||
585 | /* Unlock Block Command for given address range */ | 768 | /* Unlock Block Command for given address range */ |
586 | writew(0x4, host->regs + NFC_WRPROT); | 769 | writew(0x4, NFC_V1_V2_WRPROT); |
770 | } | ||
771 | |||
772 | static void preset_v3(struct mtd_info *mtd) | ||
773 | { | ||
774 | struct nand_chip *chip = mtd->priv; | ||
775 | struct mxc_nand_host *host = chip->priv; | ||
776 | uint32_t config2, config3; | ||
777 | int i, addr_phases; | ||
778 | |||
779 | writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1); | ||
780 | writel(NFC_V3_IPC_CREQ, NFC_V3_IPC); | ||
781 | |||
782 | /* Unlock the internal RAM Buffer */ | ||
783 | writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK, | ||
784 | NFC_V3_WRPROT); | ||
785 | |||
786 | /* Blocks to be unlocked */ | ||
787 | for (i = 0; i < NAND_MAX_CHIPS; i++) | ||
788 | writel(0x0 | (0xffff << 16), | ||
789 | NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2)); | ||
790 | |||
791 | writel(0, NFC_V3_IPC); | ||
792 | |||
793 | config2 = NFC_V3_CONFIG2_ONE_CYCLE | | ||
794 | NFC_V3_CONFIG2_2CMD_PHASES | | ||
795 | NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) | | ||
796 | NFC_V3_CONFIG2_ST_CMD(0x70) | | ||
797 | NFC_V3_CONFIG2_NUM_ADDR_PHASE0; | ||
798 | |||
799 | if (chip->ecc.mode == NAND_ECC_HW) | ||
800 | config2 |= NFC_V3_CONFIG2_ECC_EN; | ||
801 | |||
802 | addr_phases = fls(chip->pagemask) >> 3; | ||
803 | |||
804 | if (mtd->writesize == 2048) { | ||
805 | config2 |= NFC_V3_CONFIG2_PS_2048; | ||
806 | config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases); | ||
807 | } else if (mtd->writesize == 4096) { | ||
808 | config2 |= NFC_V3_CONFIG2_PS_4096; | ||
809 | config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases); | ||
810 | } else { | ||
811 | config2 |= NFC_V3_CONFIG2_PS_512; | ||
812 | config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1); | ||
813 | } | ||
814 | |||
815 | if (mtd->writesize) { | ||
816 | config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6); | ||
817 | host->eccsize = get_eccsize(mtd); | ||
818 | if (host->eccsize == 8) | ||
819 | config2 |= NFC_V3_CONFIG2_ECC_MODE_8; | ||
820 | } | ||
821 | |||
822 | writel(config2, NFC_V3_CONFIG2); | ||
823 | |||
824 | config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) | | ||
825 | NFC_V3_CONFIG3_NO_SDMA | | ||
826 | NFC_V3_CONFIG3_RBB_MODE | | ||
827 | NFC_V3_CONFIG3_SBB(6) | /* Reset default */ | ||
828 | NFC_V3_CONFIG3_ADD_OP(0); | ||
829 | |||
830 | if (!(chip->options & NAND_BUSWIDTH_16)) | ||
831 | config3 |= NFC_V3_CONFIG3_FW8; | ||
832 | |||
833 | writel(config3, NFC_V3_CONFIG3); | ||
834 | |||
835 | writel(0, NFC_V3_DELAY_LINE); | ||
587 | } | 836 | } |
588 | 837 | ||
589 | /* Used by the upper layer to write command to NAND Flash for | 838 | /* Used by the upper layer to write command to NAND Flash for |
@@ -604,15 +853,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
604 | /* Command pre-processing step */ | 853 | /* Command pre-processing step */ |
605 | switch (command) { | 854 | switch (command) { |
606 | case NAND_CMD_RESET: | 855 | case NAND_CMD_RESET: |
607 | send_cmd(host, command, false); | 856 | host->preset(mtd); |
608 | preset(mtd); | 857 | host->send_cmd(host, command, false); |
609 | break; | 858 | break; |
610 | 859 | ||
611 | case NAND_CMD_STATUS: | 860 | case NAND_CMD_STATUS: |
612 | host->buf_start = 0; | 861 | host->buf_start = 0; |
613 | host->status_request = true; | 862 | host->status_request = true; |
614 | 863 | ||
615 | send_cmd(host, command, true); | 864 | host->send_cmd(host, command, true); |
616 | mxc_do_addr_cycle(mtd, column, page_addr); | 865 | mxc_do_addr_cycle(mtd, column, page_addr); |
617 | break; | 866 | break; |
618 | 867 | ||
@@ -625,13 +874,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
625 | 874 | ||
626 | command = NAND_CMD_READ0; /* only READ0 is valid */ | 875 | command = NAND_CMD_READ0; /* only READ0 is valid */ |
627 | 876 | ||
628 | send_cmd(host, command, false); | 877 | host->send_cmd(host, command, false); |
629 | mxc_do_addr_cycle(mtd, column, page_addr); | 878 | mxc_do_addr_cycle(mtd, column, page_addr); |
630 | 879 | ||
631 | if (mtd->writesize > 512) | 880 | if (mtd->writesize > 512) |
632 | send_cmd(host, NAND_CMD_READSTART, true); | 881 | host->send_cmd(host, NAND_CMD_READSTART, true); |
633 | 882 | ||
634 | send_page(mtd, NFC_OUTPUT); | 883 | host->send_page(mtd, NFC_OUTPUT); |
635 | 884 | ||
636 | memcpy(host->data_buf, host->main_area0, mtd->writesize); | 885 | memcpy(host->data_buf, host->main_area0, mtd->writesize); |
637 | copy_spare(mtd, true); | 886 | copy_spare(mtd, true); |
@@ -644,28 +893,28 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
644 | 893 | ||
645 | host->buf_start = column; | 894 | host->buf_start = column; |
646 | 895 | ||
647 | send_cmd(host, command, false); | 896 | host->send_cmd(host, command, false); |
648 | mxc_do_addr_cycle(mtd, column, page_addr); | 897 | mxc_do_addr_cycle(mtd, column, page_addr); |
649 | break; | 898 | break; |
650 | 899 | ||
651 | case NAND_CMD_PAGEPROG: | 900 | case NAND_CMD_PAGEPROG: |
652 | memcpy(host->main_area0, host->data_buf, mtd->writesize); | 901 | memcpy(host->main_area0, host->data_buf, mtd->writesize); |
653 | copy_spare(mtd, false); | 902 | copy_spare(mtd, false); |
654 | send_page(mtd, NFC_INPUT); | 903 | host->send_page(mtd, NFC_INPUT); |
655 | send_cmd(host, command, true); | 904 | host->send_cmd(host, command, true); |
656 | mxc_do_addr_cycle(mtd, column, page_addr); | 905 | mxc_do_addr_cycle(mtd, column, page_addr); |
657 | break; | 906 | break; |
658 | 907 | ||
659 | case NAND_CMD_READID: | 908 | case NAND_CMD_READID: |
660 | send_cmd(host, command, true); | 909 | host->send_cmd(host, command, true); |
661 | mxc_do_addr_cycle(mtd, column, page_addr); | 910 | mxc_do_addr_cycle(mtd, column, page_addr); |
662 | send_read_id(host); | 911 | host->send_read_id(host); |
663 | host->buf_start = column; | 912 | host->buf_start = column; |
664 | break; | 913 | break; |
665 | 914 | ||
666 | case NAND_CMD_ERASE1: | 915 | case NAND_CMD_ERASE1: |
667 | case NAND_CMD_ERASE2: | 916 | case NAND_CMD_ERASE2: |
668 | send_cmd(host, command, false); | 917 | host->send_cmd(host, command, false); |
669 | mxc_do_addr_cycle(mtd, column, page_addr); | 918 | mxc_do_addr_cycle(mtd, column, page_addr); |
670 | 919 | ||
671 | break; | 920 | break; |
@@ -761,22 +1010,55 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
761 | } | 1010 | } |
762 | 1011 | ||
763 | host->main_area0 = host->base; | 1012 | host->main_area0 = host->base; |
764 | host->main_area1 = host->base + 0x200; | 1013 | |
1014 | if (nfc_is_v1() || nfc_is_v21()) { | ||
1015 | host->preset = preset_v1_v2; | ||
1016 | host->send_cmd = send_cmd_v1_v2; | ||
1017 | host->send_addr = send_addr_v1_v2; | ||
1018 | host->send_page = send_page_v1_v2; | ||
1019 | host->send_read_id = send_read_id_v1_v2; | ||
1020 | host->get_dev_status = get_dev_status_v1_v2; | ||
1021 | host->check_int = check_int_v1_v2; | ||
1022 | } | ||
765 | 1023 | ||
766 | if (nfc_is_v21()) { | 1024 | if (nfc_is_v21()) { |
767 | host->regs = host->base + 0x1000; | 1025 | host->regs = host->base + 0x1e00; |
768 | host->spare0 = host->base + 0x1000; | 1026 | host->spare0 = host->base + 0x1000; |
769 | host->spare_len = 64; | 1027 | host->spare_len = 64; |
770 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | 1028 | oob_smallpage = &nandv2_hw_eccoob_smallpage; |
771 | oob_largepage = &nandv2_hw_eccoob_largepage; | 1029 | oob_largepage = &nandv2_hw_eccoob_largepage; |
772 | this->ecc.bytes = 9; | 1030 | this->ecc.bytes = 9; |
773 | } else if (nfc_is_v1()) { | 1031 | } else if (nfc_is_v1()) { |
774 | host->regs = host->base; | 1032 | host->regs = host->base + 0xe00; |
775 | host->spare0 = host->base + 0x800; | 1033 | host->spare0 = host->base + 0x800; |
776 | host->spare_len = 16; | 1034 | host->spare_len = 16; |
777 | oob_smallpage = &nandv1_hw_eccoob_smallpage; | 1035 | oob_smallpage = &nandv1_hw_eccoob_smallpage; |
778 | oob_largepage = &nandv1_hw_eccoob_largepage; | 1036 | oob_largepage = &nandv1_hw_eccoob_largepage; |
779 | this->ecc.bytes = 3; | 1037 | this->ecc.bytes = 3; |
1038 | host->eccsize = 1; | ||
1039 | } else if (nfc_is_v3_2()) { | ||
1040 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
1041 | if (!res) { | ||
1042 | err = -ENODEV; | ||
1043 | goto eirq; | ||
1044 | } | ||
1045 | host->regs_ip = ioremap(res->start, resource_size(res)); | ||
1046 | if (!host->regs_ip) { | ||
1047 | err = -ENOMEM; | ||
1048 | goto eirq; | ||
1049 | } | ||
1050 | host->regs_axi = host->base + 0x1e00; | ||
1051 | host->spare0 = host->base + 0x1000; | ||
1052 | host->spare_len = 64; | ||
1053 | host->preset = preset_v3; | ||
1054 | host->send_cmd = send_cmd_v3; | ||
1055 | host->send_addr = send_addr_v3; | ||
1056 | host->send_page = send_page_v3; | ||
1057 | host->send_read_id = send_read_id_v3; | ||
1058 | host->check_int = check_int_v3; | ||
1059 | host->get_dev_status = get_dev_status_v3; | ||
1060 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | ||
1061 | oob_largepage = &nandv2_hw_eccoob_largepage; | ||
780 | } else | 1062 | } else |
781 | BUG(); | 1063 | BUG(); |
782 | 1064 | ||
@@ -786,7 +1068,10 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
786 | if (pdata->hw_ecc) { | 1068 | if (pdata->hw_ecc) { |
787 | this->ecc.calculate = mxc_nand_calculate_ecc; | 1069 | this->ecc.calculate = mxc_nand_calculate_ecc; |
788 | this->ecc.hwctl = mxc_nand_enable_hwecc; | 1070 | this->ecc.hwctl = mxc_nand_enable_hwecc; |
789 | this->ecc.correct = mxc_nand_correct_data; | 1071 | if (nfc_is_v1()) |
1072 | this->ecc.correct = mxc_nand_correct_data_v1; | ||
1073 | else | ||
1074 | this->ecc.correct = mxc_nand_correct_data_v2_v3; | ||
790 | this->ecc.mode = NAND_ECC_HW; | 1075 | this->ecc.mode = NAND_ECC_HW; |
791 | } else { | 1076 | } else { |
792 | this->ecc.mode = NAND_ECC_SOFT; | 1077 | this->ecc.mode = NAND_ECC_SOFT; |
@@ -817,6 +1102,9 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
817 | goto escan; | 1102 | goto escan; |
818 | } | 1103 | } |
819 | 1104 | ||
1105 | /* Call preset again, with correct writesize this time */ | ||
1106 | host->preset(mtd); | ||
1107 | |||
820 | if (mtd->writesize == 2048) | 1108 | if (mtd->writesize == 2048) |
821 | this->ecc.layout = oob_largepage; | 1109 | this->ecc.layout = oob_largepage; |
822 | 1110 | ||
@@ -848,6 +1136,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
848 | escan: | 1136 | escan: |
849 | free_irq(host->irq, host); | 1137 | free_irq(host->irq, host); |
850 | eirq: | 1138 | eirq: |
1139 | if (host->regs_ip) | ||
1140 | iounmap(host->regs_ip); | ||
851 | iounmap(host->base); | 1141 | iounmap(host->base); |
852 | eres: | 1142 | eres: |
853 | clk_put(host->clk); | 1143 | clk_put(host->clk); |
@@ -867,59 +1157,19 @@ static int __devexit mxcnd_remove(struct platform_device *pdev) | |||
867 | 1157 | ||
868 | nand_release(&host->mtd); | 1158 | nand_release(&host->mtd); |
869 | free_irq(host->irq, host); | 1159 | free_irq(host->irq, host); |
1160 | if (host->regs_ip) | ||
1161 | iounmap(host->regs_ip); | ||
870 | iounmap(host->base); | 1162 | iounmap(host->base); |
871 | kfree(host); | 1163 | kfree(host); |
872 | 1164 | ||
873 | return 0; | 1165 | return 0; |
874 | } | 1166 | } |
875 | 1167 | ||
876 | #ifdef CONFIG_PM | ||
877 | static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state) | ||
878 | { | ||
879 | struct mtd_info *mtd = platform_get_drvdata(pdev); | ||
880 | struct nand_chip *nand_chip = mtd->priv; | ||
881 | struct mxc_nand_host *host = nand_chip->priv; | ||
882 | int ret = 0; | ||
883 | |||
884 | DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n"); | ||
885 | |||
886 | ret = mtd->suspend(mtd); | ||
887 | |||
888 | /* | ||
889 | * nand_suspend locks the device for exclusive access, so | ||
890 | * the clock must already be off. | ||
891 | */ | ||
892 | BUG_ON(!ret && host->clk_act); | ||
893 | |||
894 | return ret; | ||
895 | } | ||
896 | |||
897 | static int mxcnd_resume(struct platform_device *pdev) | ||
898 | { | ||
899 | struct mtd_info *mtd = platform_get_drvdata(pdev); | ||
900 | struct nand_chip *nand_chip = mtd->priv; | ||
901 | struct mxc_nand_host *host = nand_chip->priv; | ||
902 | int ret = 0; | ||
903 | |||
904 | DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n"); | ||
905 | |||
906 | mtd->resume(mtd); | ||
907 | |||
908 | return ret; | ||
909 | } | ||
910 | |||
911 | #else | ||
912 | # define mxcnd_suspend NULL | ||
913 | # define mxcnd_resume NULL | ||
914 | #endif /* CONFIG_PM */ | ||
915 | |||
916 | static struct platform_driver mxcnd_driver = { | 1168 | static struct platform_driver mxcnd_driver = { |
917 | .driver = { | 1169 | .driver = { |
918 | .name = DRIVER_NAME, | 1170 | .name = DRIVER_NAME, |
919 | }, | 1171 | }, |
920 | .remove = __devexit_p(mxcnd_remove), | 1172 | .remove = __devexit_p(mxcnd_remove), |
921 | .suspend = mxcnd_suspend, | ||
922 | .resume = mxcnd_resume, | ||
923 | }; | 1173 | }; |
924 | 1174 | ||
925 | static int __init mxc_nd_init(void) | 1175 | static int __init mxc_nd_init(void) |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 4a7b86423ee9..16a1714df008 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/mtd/mtd.h> | 42 | #include <linux/mtd/mtd.h> |
43 | #include <linux/mtd/nand.h> | 43 | #include <linux/mtd/nand.h> |
44 | #include <linux/mtd/nand_ecc.h> | 44 | #include <linux/mtd/nand_ecc.h> |
45 | #include <linux/mtd/compatmac.h> | ||
46 | #include <linux/interrupt.h> | 45 | #include <linux/interrupt.h> |
47 | #include <linux/bitops.h> | 46 | #include <linux/bitops.h> |
48 | #include <linux/leds.h> | 47 | #include <linux/leds.h> |
@@ -347,7 +346,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |||
347 | struct nand_chip *chip = mtd->priv; | 346 | struct nand_chip *chip = mtd->priv; |
348 | u16 bad; | 347 | u16 bad; |
349 | 348 | ||
350 | if (chip->options & NAND_BB_LAST_PAGE) | 349 | if (chip->options & NAND_BBT_SCANLASTPAGE) |
351 | ofs += mtd->erasesize - mtd->writesize; | 350 | ofs += mtd->erasesize - mtd->writesize; |
352 | 351 | ||
353 | page = (int)(ofs >> chip->page_shift) & chip->pagemask; | 352 | page = (int)(ofs >> chip->page_shift) & chip->pagemask; |
@@ -397,9 +396,9 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
397 | { | 396 | { |
398 | struct nand_chip *chip = mtd->priv; | 397 | struct nand_chip *chip = mtd->priv; |
399 | uint8_t buf[2] = { 0, 0 }; | 398 | uint8_t buf[2] = { 0, 0 }; |
400 | int block, ret; | 399 | int block, ret, i = 0; |
401 | 400 | ||
402 | if (chip->options & NAND_BB_LAST_PAGE) | 401 | if (chip->options & NAND_BBT_SCANLASTPAGE) |
403 | ofs += mtd->erasesize - mtd->writesize; | 402 | ofs += mtd->erasesize - mtd->writesize; |
404 | 403 | ||
405 | /* Get block number */ | 404 | /* Get block number */ |
@@ -411,17 +410,31 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
411 | if (chip->options & NAND_USE_FLASH_BBT) | 410 | if (chip->options & NAND_USE_FLASH_BBT) |
412 | ret = nand_update_bbt(mtd, ofs); | 411 | ret = nand_update_bbt(mtd, ofs); |
413 | else { | 412 | else { |
414 | /* We write two bytes, so we dont have to mess with 16 bit | ||
415 | * access | ||
416 | */ | ||
417 | nand_get_device(chip, mtd, FL_WRITING); | 413 | nand_get_device(chip, mtd, FL_WRITING); |
418 | ofs += mtd->oobsize; | ||
419 | chip->ops.len = chip->ops.ooblen = 2; | ||
420 | chip->ops.datbuf = NULL; | ||
421 | chip->ops.oobbuf = buf; | ||
422 | chip->ops.ooboffs = chip->badblockpos & ~0x01; | ||
423 | 414 | ||
424 | ret = nand_do_write_oob(mtd, ofs, &chip->ops); | 415 | /* Write to first two pages and to byte 1 and 6 if necessary. |
416 | * If we write to more than one location, the first error | ||
417 | * encountered quits the procedure. We write two bytes per | ||
418 | * location, so we dont have to mess with 16 bit access. | ||
419 | */ | ||
420 | do { | ||
421 | chip->ops.len = chip->ops.ooblen = 2; | ||
422 | chip->ops.datbuf = NULL; | ||
423 | chip->ops.oobbuf = buf; | ||
424 | chip->ops.ooboffs = chip->badblockpos & ~0x01; | ||
425 | |||
426 | ret = nand_do_write_oob(mtd, ofs, &chip->ops); | ||
427 | |||
428 | if (!ret && (chip->options & NAND_BBT_SCANBYTE1AND6)) { | ||
429 | chip->ops.ooboffs = NAND_SMALL_BADBLOCK_POS | ||
430 | & ~0x01; | ||
431 | ret = nand_do_write_oob(mtd, ofs, &chip->ops); | ||
432 | } | ||
433 | i++; | ||
434 | ofs += mtd->writesize; | ||
435 | } while (!ret && (chip->options & NAND_BBT_SCAN2NDPAGE) && | ||
436 | i < 2); | ||
437 | |||
425 | nand_release_device(mtd); | 438 | nand_release_device(mtd); |
426 | } | 439 | } |
427 | if (!ret) | 440 | if (!ret) |
@@ -2920,9 +2933,14 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2920 | chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1; | 2933 | chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1; |
2921 | 2934 | ||
2922 | /* Set the bad block position */ | 2935 | /* Set the bad block position */ |
2923 | chip->badblockpos = mtd->writesize > 512 ? | 2936 | if (!(busw & NAND_BUSWIDTH_16) && (*maf_id == NAND_MFR_STMICRO || |
2924 | NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; | 2937 | (*maf_id == NAND_MFR_SAMSUNG && |
2925 | chip->badblockbits = 8; | 2938 | mtd->writesize == 512) || |
2939 | *maf_id == NAND_MFR_AMD)) | ||
2940 | chip->badblockpos = NAND_SMALL_BADBLOCK_POS; | ||
2941 | else | ||
2942 | chip->badblockpos = NAND_LARGE_BADBLOCK_POS; | ||
2943 | |||
2926 | 2944 | ||
2927 | /* Get chip options, preserve non chip based options */ | 2945 | /* Get chip options, preserve non chip based options */ |
2928 | chip->options &= ~NAND_CHIPOPTIONS_MSK; | 2946 | chip->options &= ~NAND_CHIPOPTIONS_MSK; |
@@ -2941,12 +2959,32 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2941 | 2959 | ||
2942 | /* | 2960 | /* |
2943 | * Bad block marker is stored in the last page of each block | 2961 | * Bad block marker is stored in the last page of each block |
2944 | * on Samsung and Hynix MLC devices | 2962 | * on Samsung and Hynix MLC devices; stored in first two pages |
2963 | * of each block on Micron devices with 2KiB pages and on | ||
2964 | * SLC Samsung, Hynix, and AMD/Spansion. All others scan only | ||
2965 | * the first page. | ||
2945 | */ | 2966 | */ |
2946 | if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | 2967 | if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && |
2947 | (*maf_id == NAND_MFR_SAMSUNG || | 2968 | (*maf_id == NAND_MFR_SAMSUNG || |
2948 | *maf_id == NAND_MFR_HYNIX)) | 2969 | *maf_id == NAND_MFR_HYNIX)) |
2949 | chip->options |= NAND_BB_LAST_PAGE; | 2970 | chip->options |= NAND_BBT_SCANLASTPAGE; |
2971 | else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | ||
2972 | (*maf_id == NAND_MFR_SAMSUNG || | ||
2973 | *maf_id == NAND_MFR_HYNIX || | ||
2974 | *maf_id == NAND_MFR_AMD)) || | ||
2975 | (mtd->writesize == 2048 && | ||
2976 | *maf_id == NAND_MFR_MICRON)) | ||
2977 | chip->options |= NAND_BBT_SCAN2NDPAGE; | ||
2978 | |||
2979 | /* | ||
2980 | * Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6 | ||
2981 | */ | ||
2982 | if (!(busw & NAND_BUSWIDTH_16) && | ||
2983 | *maf_id == NAND_MFR_STMICRO && | ||
2984 | mtd->writesize == 2048) { | ||
2985 | chip->options |= NAND_BBT_SCANBYTE1AND6; | ||
2986 | chip->badblockpos = 0; | ||
2987 | } | ||
2950 | 2988 | ||
2951 | /* Check for AND chips with 4 page planes */ | 2989 | /* Check for AND chips with 4 page planes */ |
2952 | if (chip->options & NAND_4PAGE_ARRAY) | 2990 | if (chip->options & NAND_4PAGE_ARRAY) |
@@ -3306,6 +3344,11 @@ void nand_release(struct mtd_info *mtd) | |||
3306 | kfree(chip->bbt); | 3344 | kfree(chip->bbt); |
3307 | if (!(chip->options & NAND_OWN_BUFFERS)) | 3345 | if (!(chip->options & NAND_OWN_BUFFERS)) |
3308 | kfree(chip->buffers); | 3346 | kfree(chip->buffers); |
3347 | |||
3348 | /* Free bad block descriptor memory */ | ||
3349 | if (chip->badblock_pattern && chip->badblock_pattern->options | ||
3350 | & NAND_BBT_DYNAMICSTRUCT) | ||
3351 | kfree(chip->badblock_pattern); | ||
3309 | } | 3352 | } |
3310 | 3353 | ||
3311 | EXPORT_SYMBOL_GPL(nand_lock); | 3354 | EXPORT_SYMBOL_GPL(nand_lock); |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index ad97c0ce73b2..5fedf4a74f16 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -55,7 +55,6 @@ | |||
55 | #include <linux/mtd/mtd.h> | 55 | #include <linux/mtd/mtd.h> |
56 | #include <linux/mtd/nand.h> | 56 | #include <linux/mtd/nand.h> |
57 | #include <linux/mtd/nand_ecc.h> | 57 | #include <linux/mtd/nand_ecc.h> |
58 | #include <linux/mtd/compatmac.h> | ||
59 | #include <linux/bitops.h> | 58 | #include <linux/bitops.h> |
60 | #include <linux/delay.h> | 59 | #include <linux/delay.h> |
61 | #include <linux/vmalloc.h> | 60 | #include <linux/vmalloc.h> |
@@ -93,6 +92,28 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc | |||
93 | return -1; | 92 | return -1; |
94 | } | 93 | } |
95 | 94 | ||
95 | /* Check both positions 1 and 6 for pattern? */ | ||
96 | if (td->options & NAND_BBT_SCANBYTE1AND6) { | ||
97 | if (td->options & NAND_BBT_SCANEMPTY) { | ||
98 | p += td->len; | ||
99 | end += NAND_SMALL_BADBLOCK_POS - td->offs; | ||
100 | /* Check region between positions 1 and 6 */ | ||
101 | for (i = 0; i < NAND_SMALL_BADBLOCK_POS - td->offs - td->len; | ||
102 | i++) { | ||
103 | if (*p++ != 0xff) | ||
104 | return -1; | ||
105 | } | ||
106 | } | ||
107 | else { | ||
108 | p += NAND_SMALL_BADBLOCK_POS - td->offs; | ||
109 | } | ||
110 | /* Compare the pattern */ | ||
111 | for (i = 0; i < td->len; i++) { | ||
112 | if (p[i] != td->pattern[i]) | ||
113 | return -1; | ||
114 | } | ||
115 | } | ||
116 | |||
96 | if (td->options & NAND_BBT_SCANEMPTY) { | 117 | if (td->options & NAND_BBT_SCANEMPTY) { |
97 | p += td->len; | 118 | p += td->len; |
98 | end += td->len; | 119 | end += td->len; |
@@ -124,6 +145,13 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td) | |||
124 | if (p[td->offs + i] != td->pattern[i]) | 145 | if (p[td->offs + i] != td->pattern[i]) |
125 | return -1; | 146 | return -1; |
126 | } | 147 | } |
148 | /* Need to check location 1 AND 6? */ | ||
149 | if (td->options & NAND_BBT_SCANBYTE1AND6) { | ||
150 | for (i = 0; i < td->len; i++) { | ||
151 | if (p[NAND_SMALL_BADBLOCK_POS + i] != td->pattern[i]) | ||
152 | return -1; | ||
153 | } | ||
154 | } | ||
127 | return 0; | 155 | return 0; |
128 | } | 156 | } |
129 | 157 | ||
@@ -397,12 +425,10 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
397 | 425 | ||
398 | if (bd->options & NAND_BBT_SCANALLPAGES) | 426 | if (bd->options & NAND_BBT_SCANALLPAGES) |
399 | len = 1 << (this->bbt_erase_shift - this->page_shift); | 427 | len = 1 << (this->bbt_erase_shift - this->page_shift); |
400 | else { | 428 | else if (bd->options & NAND_BBT_SCAN2NDPAGE) |
401 | if (bd->options & NAND_BBT_SCAN2NDPAGE) | 429 | len = 2; |
402 | len = 2; | 430 | else |
403 | else | 431 | len = 1; |
404 | len = 1; | ||
405 | } | ||
406 | 432 | ||
407 | if (!(bd->options & NAND_BBT_SCANEMPTY)) { | 433 | if (!(bd->options & NAND_BBT_SCANEMPTY)) { |
408 | /* We need only read few bytes from the OOB area */ | 434 | /* We need only read few bytes from the OOB area */ |
@@ -432,7 +458,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
432 | from = (loff_t)startblock << (this->bbt_erase_shift - 1); | 458 | from = (loff_t)startblock << (this->bbt_erase_shift - 1); |
433 | } | 459 | } |
434 | 460 | ||
435 | if (this->options & NAND_BB_LAST_PAGE) | 461 | if (this->options & NAND_BBT_SCANLASTPAGE) |
436 | from += mtd->erasesize - (mtd->writesize * len); | 462 | from += mtd->erasesize - (mtd->writesize * len); |
437 | 463 | ||
438 | for (i = startblock; i < numblocks;) { | 464 | for (i = startblock; i < numblocks;) { |
@@ -1092,30 +1118,16 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs) | |||
1092 | * while scanning a device for factory marked good / bad blocks. */ | 1118 | * while scanning a device for factory marked good / bad blocks. */ |
1093 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | 1119 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; |
1094 | 1120 | ||
1095 | static struct nand_bbt_descr smallpage_memorybased = { | ||
1096 | .options = NAND_BBT_SCAN2NDPAGE, | ||
1097 | .offs = 5, | ||
1098 | .len = 1, | ||
1099 | .pattern = scan_ff_pattern | ||
1100 | }; | ||
1101 | |||
1102 | static struct nand_bbt_descr largepage_memorybased = { | ||
1103 | .options = 0, | ||
1104 | .offs = 0, | ||
1105 | .len = 2, | ||
1106 | .pattern = scan_ff_pattern | ||
1107 | }; | ||
1108 | |||
1109 | static struct nand_bbt_descr smallpage_flashbased = { | 1121 | static struct nand_bbt_descr smallpage_flashbased = { |
1110 | .options = NAND_BBT_SCAN2NDPAGE, | 1122 | .options = NAND_BBT_SCAN2NDPAGE, |
1111 | .offs = 5, | 1123 | .offs = NAND_SMALL_BADBLOCK_POS, |
1112 | .len = 1, | 1124 | .len = 1, |
1113 | .pattern = scan_ff_pattern | 1125 | .pattern = scan_ff_pattern |
1114 | }; | 1126 | }; |
1115 | 1127 | ||
1116 | static struct nand_bbt_descr largepage_flashbased = { | 1128 | static struct nand_bbt_descr largepage_flashbased = { |
1117 | .options = NAND_BBT_SCAN2NDPAGE, | 1129 | .options = NAND_BBT_SCAN2NDPAGE, |
1118 | .offs = 0, | 1130 | .offs = NAND_LARGE_BADBLOCK_POS, |
1119 | .len = 2, | 1131 | .len = 2, |
1120 | .pattern = scan_ff_pattern | 1132 | .pattern = scan_ff_pattern |
1121 | }; | 1133 | }; |
@@ -1154,6 +1166,43 @@ static struct nand_bbt_descr bbt_mirror_descr = { | |||
1154 | .pattern = mirror_pattern | 1166 | .pattern = mirror_pattern |
1155 | }; | 1167 | }; |
1156 | 1168 | ||
1169 | #define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \ | ||
1170 | NAND_BBT_SCANBYTE1AND6) | ||
1171 | /** | ||
1172 | * nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure | ||
1173 | * @this: NAND chip to create descriptor for | ||
1174 | * | ||
1175 | * This function allocates and initializes a nand_bbt_descr for BBM detection | ||
1176 | * based on the properties of "this". The new descriptor is stored in | ||
1177 | * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when | ||
1178 | * passed to this function. | ||
1179 | * | ||
1180 | * TODO: Handle other flags, replace other static structs | ||
1181 | * (e.g. handle NAND_BBT_FLASH for flash-based BBT, | ||
1182 | * replace smallpage_flashbased) | ||
1183 | * | ||
1184 | */ | ||
1185 | static int nand_create_default_bbt_descr(struct nand_chip *this) | ||
1186 | { | ||
1187 | struct nand_bbt_descr *bd; | ||
1188 | if (this->badblock_pattern) { | ||
1189 | printk(KERN_WARNING "BBT descr already allocated; not replacing.\n"); | ||
1190 | return -EINVAL; | ||
1191 | } | ||
1192 | bd = kzalloc(sizeof(*bd), GFP_KERNEL); | ||
1193 | if (!bd) { | ||
1194 | printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n"); | ||
1195 | return -ENOMEM; | ||
1196 | } | ||
1197 | bd->options = this->options & BBT_SCAN_OPTIONS; | ||
1198 | bd->offs = this->badblockpos; | ||
1199 | bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1; | ||
1200 | bd->pattern = scan_ff_pattern; | ||
1201 | bd->options |= NAND_BBT_DYNAMICSTRUCT; | ||
1202 | this->badblock_pattern = bd; | ||
1203 | return 0; | ||
1204 | } | ||
1205 | |||
1157 | /** | 1206 | /** |
1158 | * nand_default_bbt - [NAND Interface] Select a default bad block table for the device | 1207 | * nand_default_bbt - [NAND Interface] Select a default bad block table for the device |
1159 | * @mtd: MTD device structure | 1208 | * @mtd: MTD device structure |
@@ -1196,10 +1245,8 @@ int nand_default_bbt(struct mtd_info *mtd) | |||
1196 | } else { | 1245 | } else { |
1197 | this->bbt_td = NULL; | 1246 | this->bbt_td = NULL; |
1198 | this->bbt_md = NULL; | 1247 | this->bbt_md = NULL; |
1199 | if (!this->badblock_pattern) { | 1248 | if (!this->badblock_pattern) |
1200 | this->badblock_pattern = (mtd->writesize > 512) ? | 1249 | nand_create_default_bbt_descr(this); |
1201 | &largepage_memorybased : &smallpage_memorybased; | ||
1202 | } | ||
1203 | } | 1250 | } |
1204 | return nand_scan_bbt(mtd, this->badblock_pattern); | 1251 | return nand_scan_bbt(mtd, this->badblock_pattern); |
1205 | } | 1252 | } |
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 89907ed99009..a04b89105b65 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -85,6 +85,7 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
85 | {"NAND 128MiB 3,3V 8-bit", 0xD1, 0, 128, 0, LP_OPTIONS}, | 85 | {"NAND 128MiB 3,3V 8-bit", 0xD1, 0, 128, 0, LP_OPTIONS}, |
86 | {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16}, | 86 | {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16}, |
87 | {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16}, | 87 | {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16}, |
88 | {"NAND 128MiB 1,8V 16-bit", 0xAD, 0, 128, 0, LP_OPTIONS16}, | ||
88 | 89 | ||
89 | /* 2 Gigabit */ | 90 | /* 2 Gigabit */ |
90 | {"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, LP_OPTIONS}, | 91 | {"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, LP_OPTIONS}, |
@@ -110,6 +111,9 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
110 | {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16}, | 111 | {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16}, |
111 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, | 112 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, |
112 | 113 | ||
114 | /* 32 Gigabit */ | ||
115 | {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS16}, | ||
116 | |||
113 | /* | 117 | /* |
114 | * Renesas AND 1 Gigabit. Those chips do not support extended id and | 118 | * Renesas AND 1 Gigabit. Those chips do not support extended id and |
115 | * have a strange page/block layout ! The chosen minimum erasesize is | 119 | * have a strange page/block layout ! The chosen minimum erasesize is |
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 261337efe0ee..c25648bb5793 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -553,8 +553,8 @@ static uint64_t divide(uint64_t n, uint32_t d) | |||
553 | */ | 553 | */ |
554 | static int init_nandsim(struct mtd_info *mtd) | 554 | static int init_nandsim(struct mtd_info *mtd) |
555 | { | 555 | { |
556 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | 556 | struct nand_chip *chip = mtd->priv; |
557 | struct nandsim *ns = (struct nandsim *)(chip->priv); | 557 | struct nandsim *ns = chip->priv; |
558 | int i, ret = 0; | 558 | int i, ret = 0; |
559 | uint64_t remains; | 559 | uint64_t remains; |
560 | uint64_t next_offset; | 560 | uint64_t next_offset; |
@@ -1877,7 +1877,7 @@ static void switch_state(struct nandsim *ns) | |||
1877 | 1877 | ||
1878 | static u_char ns_nand_read_byte(struct mtd_info *mtd) | 1878 | static u_char ns_nand_read_byte(struct mtd_info *mtd) |
1879 | { | 1879 | { |
1880 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 1880 | struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; |
1881 | u_char outb = 0x00; | 1881 | u_char outb = 0x00; |
1882 | 1882 | ||
1883 | /* Sanity and correctness checks */ | 1883 | /* Sanity and correctness checks */ |
@@ -1950,7 +1950,7 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd) | |||
1950 | 1950 | ||
1951 | static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | 1951 | static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) |
1952 | { | 1952 | { |
1953 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 1953 | struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; |
1954 | 1954 | ||
1955 | /* Sanity and correctness checks */ | 1955 | /* Sanity and correctness checks */ |
1956 | if (!ns->lines.ce) { | 1956 | if (!ns->lines.ce) { |
@@ -2132,7 +2132,7 @@ static uint16_t ns_nand_read_word(struct mtd_info *mtd) | |||
2132 | 2132 | ||
2133 | static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | 2133 | static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) |
2134 | { | 2134 | { |
2135 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 2135 | struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; |
2136 | 2136 | ||
2137 | /* Check that chip is expecting data input */ | 2137 | /* Check that chip is expecting data input */ |
2138 | if (!(ns->state & STATE_DATAIN_MASK)) { | 2138 | if (!(ns->state & STATE_DATAIN_MASK)) { |
@@ -2159,7 +2159,7 @@ static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
2159 | 2159 | ||
2160 | static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | 2160 | static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) |
2161 | { | 2161 | { |
2162 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | 2162 | struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; |
2163 | 2163 | ||
2164 | /* Sanity and correctness checks */ | 2164 | /* Sanity and correctness checks */ |
2165 | if (!ns->lines.ce) { | 2165 | if (!ns->lines.ce) { |
@@ -2352,7 +2352,7 @@ module_init(ns_init_module); | |||
2352 | */ | 2352 | */ |
2353 | static void __exit ns_cleanup_module(void) | 2353 | static void __exit ns_cleanup_module(void) |
2354 | { | 2354 | { |
2355 | struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv); | 2355 | struct nandsim *ns = ((struct nand_chip *)nsmtd->priv)->priv; |
2356 | int i; | 2356 | int i; |
2357 | 2357 | ||
2358 | free_nandsim(ns); /* Free nandsim private resources */ | 2358 | free_nandsim(ns); /* Free nandsim private resources */ |
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 8d467315f02b..90e143e5ad3e 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
@@ -91,7 +91,7 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) | |||
91 | } | 91 | } |
92 | 92 | ||
93 | /* Scan to find existance of the device */ | 93 | /* Scan to find existance of the device */ |
94 | if (nand_scan(&data->mtd, 1)) { | 94 | if (nand_scan(&data->mtd, pdata->chip.nr_chips)) { |
95 | err = -ENXIO; | 95 | err = -ENXIO; |
96 | goto out; | 96 | goto out; |
97 | } | 97 | } |
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index bcfc851fe550..5169ca6a66bc 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c | |||
@@ -64,8 +64,8 @@ static inline void r852_write_reg_dword(struct r852_device *dev, | |||
64 | /* returns pointer to our private structure */ | 64 | /* returns pointer to our private structure */ |
65 | static inline struct r852_device *r852_get_dev(struct mtd_info *mtd) | 65 | static inline struct r852_device *r852_get_dev(struct mtd_info *mtd) |
66 | { | 66 | { |
67 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | 67 | struct nand_chip *chip = mtd->priv; |
68 | return (struct r852_device *)chip->priv; | 68 | return chip->priv; |
69 | } | 69 | } |
70 | 70 | ||
71 | 71 | ||
@@ -380,7 +380,7 @@ void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl) | |||
380 | */ | 380 | */ |
381 | int r852_wait(struct mtd_info *mtd, struct nand_chip *chip) | 381 | int r852_wait(struct mtd_info *mtd, struct nand_chip *chip) |
382 | { | 382 | { |
383 | struct r852_device *dev = (struct r852_device *)chip->priv; | 383 | struct r852_device *dev = chip->priv; |
384 | 384 | ||
385 | unsigned long timeout; | 385 | unsigned long timeout; |
386 | int status; | 386 | int status; |
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c index a033c4cd8e16..67440b5beef8 100644 --- a/drivers/mtd/nand/rtc_from4.c +++ b/drivers/mtd/nand/rtc_from4.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/rslib.h> | 24 | #include <linux/rslib.h> |
25 | #include <linux/bitrev.h> | 25 | #include <linux/bitrev.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/mtd/compatmac.h> | ||
28 | #include <linux/mtd/mtd.h> | 27 | #include <linux/mtd/mtd.h> |
29 | #include <linux/mtd/nand.h> | 28 | #include <linux/mtd/nand.h> |
30 | #include <linux/mtd/partitions.h> | 29 | #include <linux/mtd/partitions.h> |
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 239aadfd01b0..33d832dddfdd 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -727,15 +727,12 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | |||
727 | if (set == NULL) | 727 | if (set == NULL) |
728 | return add_mtd_device(&mtd->mtd); | 728 | return add_mtd_device(&mtd->mtd); |
729 | 729 | ||
730 | if (set->nr_partitions == 0) { | 730 | mtd->mtd.name = set->name; |
731 | mtd->mtd.name = set->name; | 731 | nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0); |
732 | nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, | 732 | |
733 | &part_info, 0); | 733 | if (nr_part <= 0 && set->nr_partitions > 0) { |
734 | } else { | 734 | nr_part = set->nr_partitions; |
735 | if (set->nr_partitions > 0 && set->partitions != NULL) { | 735 | part_info = set->partitions; |
736 | nr_part = set->nr_partitions; | ||
737 | part_info = set->partitions; | ||
738 | } | ||
739 | } | 736 | } |
740 | 737 | ||
741 | if (nr_part > 0 && part_info) | 738 | if (nr_part > 0 && part_info) |
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c index ac80fb362e63..4a8f367c295c 100644 --- a/drivers/mtd/nand/sm_common.c +++ b/drivers/mtd/nand/sm_common.c | |||
@@ -109,7 +109,7 @@ static struct nand_flash_dev nand_xd_flash_ids[] = { | |||
109 | 109 | ||
110 | int sm_register_device(struct mtd_info *mtd, int smartmedia) | 110 | int sm_register_device(struct mtd_info *mtd, int smartmedia) |
111 | { | 111 | { |
112 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | 112 | struct nand_chip *chip = mtd->priv; |
113 | int ret; | 113 | int ret; |
114 | 114 | ||
115 | chip->options |= NAND_SKIP_BBTSCAN; | 115 | chip->options |= NAND_SKIP_BBTSCAN; |
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index a4578bf903aa..b155666acfbe 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c | |||
@@ -1,11 +1,22 @@ | |||
1 | /* Linux driver for NAND Flash Translation Layer */ | ||
2 | /* (c) 1999 Machine Vision Holdings, Inc. */ | ||
3 | /* Author: David Woodhouse <dwmw2@infradead.org> */ | ||
4 | |||
5 | /* | 1 | /* |
6 | The contents of this file are distributed under the GNU General | 2 | * Linux driver for NAND Flash Translation Layer |
7 | Public License version 2. The author places no additional | 3 | * |
8 | restrictions of any kind on it. | 4 | * Copyright © 1999 Machine Vision Holdings, Inc. |
5 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> | ||
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 | ||
9 | */ | 20 | */ |
10 | 21 | ||
11 | #define PRERELEASE | 22 | #define PRERELEASE |
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index 8b22b1836e9f..e3cd1ffad2f6 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c | |||
@@ -2,7 +2,8 @@ | |||
2 | * NFTL mount code with extensive checks | 2 | * NFTL mount code with extensive checks |
3 | * | 3 | * |
4 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) | 4 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) |
5 | * Copyright (C) 2000 Netgem S.A. | 5 | * Copyright © 2000 Netgem S.A. |
6 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * 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 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 4f0d635674f3..8bf7dc6d1ce6 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c | |||
@@ -1,11 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Flash partitions described by the OF (or flattened) device tree | 2 | * Flash partitions described by the OF (or flattened) device tree |
3 | * | 3 | * |
4 | * Copyright (C) 2006 MontaVista Software Inc. | 4 | * Copyright © 2006 MontaVista Software Inc. |
5 | * Author: Vitaly Wool <vwool@ru.mvista.com> | 5 | * Author: Vitaly Wool <vwool@ru.mvista.com> |
6 | * | 6 | * |
7 | * Revised to handle newer style flash binding by: | 7 | * Revised to handle newer style flash binding by: |
8 | * Copyright (C) 2007 David Gibson, IBM Corporation. | 8 | * Copyright © 2007 David Gibson, IBM Corporation. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
11 | * under the terms of the GNU General Public License as published by the | 11 | * under the terms of the GNU General Public License as published by the |
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 9a49d68ba5f9..3f32289fdbb5 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig | |||
@@ -25,14 +25,14 @@ config MTD_ONENAND_GENERIC | |||
25 | 25 | ||
26 | config MTD_ONENAND_OMAP2 | 26 | config MTD_ONENAND_OMAP2 |
27 | tristate "OneNAND on OMAP2/OMAP3 support" | 27 | tristate "OneNAND on OMAP2/OMAP3 support" |
28 | depends on MTD_ONENAND && (ARCH_OMAP2 || ARCH_OMAP3) | 28 | depends on ARCH_OMAP2 || ARCH_OMAP3 |
29 | help | 29 | help |
30 | Support for a OneNAND flash device connected to an OMAP2/OMAP3 CPU | 30 | Support for a OneNAND flash device connected to an OMAP2/OMAP3 CPU |
31 | via the GPMC memory controller. | 31 | via the GPMC memory controller. |
32 | 32 | ||
33 | config MTD_ONENAND_SAMSUNG | 33 | config MTD_ONENAND_SAMSUNG |
34 | tristate "OneNAND on Samsung SOC controller support" | 34 | tristate "OneNAND on Samsung SOC controller support" |
35 | depends on MTD_ONENAND && (ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210) | 35 | depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 |
36 | help | 36 | help |
37 | Support for a OneNAND flash device connected to an Samsung SOC | 37 | Support for a OneNAND flash device connected to an Samsung SOC |
38 | S3C64XX/S5PC1XX controller. | 38 | S3C64XX/S5PC1XX controller. |
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 26caf2590dae..a2bb520286f8 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
@@ -377,8 +377,11 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le | |||
377 | 377 | ||
378 | default: | 378 | default: |
379 | block = onenand_block(this, addr); | 379 | block = onenand_block(this, addr); |
380 | page = (int) (addr - onenand_addr(this, block)) >> this->page_shift; | 380 | if (FLEXONENAND(this)) |
381 | 381 | page = (int) (addr - onenand_addr(this, block))>>\ | |
382 | this->page_shift; | ||
383 | else | ||
384 | page = (int) (addr >> this->page_shift); | ||
382 | if (ONENAND_IS_2PLANE(this)) { | 385 | if (ONENAND_IS_2PLANE(this)) { |
383 | /* Make the even block number */ | 386 | /* Make the even block number */ |
384 | block &= ~1; | 387 | block &= ~1; |
@@ -3730,17 +3733,16 @@ out: | |||
3730 | } | 3733 | } |
3731 | 3734 | ||
3732 | /** | 3735 | /** |
3733 | * onenand_probe - [OneNAND Interface] Probe the OneNAND device | 3736 | * onenand_chip_probe - [OneNAND Interface] The generic chip probe |
3734 | * @param mtd MTD device structure | 3737 | * @param mtd MTD device structure |
3735 | * | 3738 | * |
3736 | * OneNAND detection method: | 3739 | * OneNAND detection method: |
3737 | * Compare the values from command with ones from register | 3740 | * Compare the values from command with ones from register |
3738 | */ | 3741 | */ |
3739 | static int onenand_probe(struct mtd_info *mtd) | 3742 | static int onenand_chip_probe(struct mtd_info *mtd) |
3740 | { | 3743 | { |
3741 | struct onenand_chip *this = mtd->priv; | 3744 | struct onenand_chip *this = mtd->priv; |
3742 | int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id; | 3745 | int bram_maf_id, bram_dev_id, maf_id, dev_id; |
3743 | int density; | ||
3744 | int syscfg; | 3746 | int syscfg; |
3745 | 3747 | ||
3746 | /* Save system configuration 1 */ | 3748 | /* Save system configuration 1 */ |
@@ -3763,12 +3765,6 @@ static int onenand_probe(struct mtd_info *mtd) | |||
3763 | /* Restore system configuration 1 */ | 3765 | /* Restore system configuration 1 */ |
3764 | this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); | 3766 | this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); |
3765 | 3767 | ||
3766 | /* Workaround */ | ||
3767 | if (syscfg & ONENAND_SYS_CFG1_SYNC_WRITE) { | ||
3768 | bram_maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); | ||
3769 | bram_dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); | ||
3770 | } | ||
3771 | |||
3772 | /* Check manufacturer ID */ | 3768 | /* Check manufacturer ID */ |
3773 | if (onenand_check_maf(bram_maf_id)) | 3769 | if (onenand_check_maf(bram_maf_id)) |
3774 | return -ENXIO; | 3770 | return -ENXIO; |
@@ -3776,13 +3772,35 @@ static int onenand_probe(struct mtd_info *mtd) | |||
3776 | /* Read manufacturer and device IDs from Register */ | 3772 | /* Read manufacturer and device IDs from Register */ |
3777 | maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); | 3773 | maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); |
3778 | dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); | 3774 | dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); |
3779 | ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); | ||
3780 | this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY); | ||
3781 | 3775 | ||
3782 | /* Check OneNAND device */ | 3776 | /* Check OneNAND device */ |
3783 | if (maf_id != bram_maf_id || dev_id != bram_dev_id) | 3777 | if (maf_id != bram_maf_id || dev_id != bram_dev_id) |
3784 | return -ENXIO; | 3778 | return -ENXIO; |
3785 | 3779 | ||
3780 | return 0; | ||
3781 | } | ||
3782 | |||
3783 | /** | ||
3784 | * onenand_probe - [OneNAND Interface] Probe the OneNAND device | ||
3785 | * @param mtd MTD device structure | ||
3786 | */ | ||
3787 | static int onenand_probe(struct mtd_info *mtd) | ||
3788 | { | ||
3789 | struct onenand_chip *this = mtd->priv; | ||
3790 | int maf_id, dev_id, ver_id; | ||
3791 | int density; | ||
3792 | int ret; | ||
3793 | |||
3794 | ret = this->chip_probe(mtd); | ||
3795 | if (ret) | ||
3796 | return ret; | ||
3797 | |||
3798 | /* Read manufacturer and device IDs from Register */ | ||
3799 | maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); | ||
3800 | dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); | ||
3801 | ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); | ||
3802 | this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY); | ||
3803 | |||
3786 | /* Flash device information */ | 3804 | /* Flash device information */ |
3787 | onenand_print_device_info(dev_id, ver_id); | 3805 | onenand_print_device_info(dev_id, ver_id); |
3788 | this->device_id = dev_id; | 3806 | this->device_id = dev_id; |
@@ -3909,6 +3927,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
3909 | if (!this->unlock_all) | 3927 | if (!this->unlock_all) |
3910 | this->unlock_all = onenand_unlock_all; | 3928 | this->unlock_all = onenand_unlock_all; |
3911 | 3929 | ||
3930 | if (!this->chip_probe) | ||
3931 | this->chip_probe = onenand_chip_probe; | ||
3932 | |||
3912 | if (!this->read_bufferram) | 3933 | if (!this->read_bufferram) |
3913 | this->read_bufferram = onenand_read_bufferram; | 3934 | this->read_bufferram = onenand_read_bufferram; |
3914 | if (!this->write_bufferram) | 3935 | if (!this->write_bufferram) |
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index a91fcac1af01..01ab5b3c453b 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/mtd/mtd.h> | 16 | #include <linux/mtd/mtd.h> |
17 | #include <linux/mtd/onenand.h> | 17 | #include <linux/mtd/onenand.h> |
18 | #include <linux/mtd/compatmac.h> | ||
19 | 18 | ||
20 | /** | 19 | /** |
21 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer | 20 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer |
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index 2750317cb58f..cb443af3d45f 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
@@ -630,6 +630,12 @@ normal: | |||
630 | return 0; | 630 | return 0; |
631 | } | 631 | } |
632 | 632 | ||
633 | static int s5pc110_chip_probe(struct mtd_info *mtd) | ||
634 | { | ||
635 | /* Now just return 0 */ | ||
636 | return 0; | ||
637 | } | ||
638 | |||
633 | static int s3c_onenand_bbt_wait(struct mtd_info *mtd, int state) | 639 | static int s3c_onenand_bbt_wait(struct mtd_info *mtd, int state) |
634 | { | 640 | { |
635 | unsigned int flags = INT_ACT | LOAD_CMP; | 641 | unsigned int flags = INT_ACT | LOAD_CMP; |
@@ -757,6 +763,7 @@ static void s3c_onenand_setup(struct mtd_info *mtd) | |||
757 | /* Use generic onenand functions */ | 763 | /* Use generic onenand functions */ |
758 | onenand->cmd_map = s5pc1xx_cmd_map; | 764 | onenand->cmd_map = s5pc1xx_cmd_map; |
759 | this->read_bufferram = s5pc110_read_bufferram; | 765 | this->read_bufferram = s5pc110_read_bufferram; |
766 | this->chip_probe = s5pc110_chip_probe; | ||
760 | return; | 767 | return; |
761 | } else { | 768 | } else { |
762 | BUG(); | 769 | BUG(); |
@@ -781,7 +788,6 @@ static int s3c_onenand_probe(struct platform_device *pdev) | |||
781 | struct mtd_info *mtd; | 788 | struct mtd_info *mtd; |
782 | struct resource *r; | 789 | struct resource *r; |
783 | int size, err; | 790 | int size, err; |
784 | unsigned long onenand_ctrl_cfg = 0; | ||
785 | 791 | ||
786 | pdata = pdev->dev.platform_data; | 792 | pdata = pdev->dev.platform_data; |
787 | /* No need to check pdata. the platform data is optional */ | 793 | /* No need to check pdata. the platform data is optional */ |
@@ -900,14 +906,6 @@ static int s3c_onenand_probe(struct platform_device *pdev) | |||
900 | } | 906 | } |
901 | 907 | ||
902 | onenand->phys_base = onenand->base_res->start; | 908 | onenand->phys_base = onenand->base_res->start; |
903 | |||
904 | onenand_ctrl_cfg = readl(onenand->dma_addr + 0x100); | ||
905 | if ((onenand_ctrl_cfg & ONENAND_SYS_CFG1_SYNC_WRITE) && | ||
906 | onenand->dma_addr) | ||
907 | writel(onenand_ctrl_cfg & ~ONENAND_SYS_CFG1_SYNC_WRITE, | ||
908 | onenand->dma_addr + 0x100); | ||
909 | else | ||
910 | onenand_ctrl_cfg = 0; | ||
911 | } | 909 | } |
912 | 910 | ||
913 | if (onenand_scan(mtd, 1)) { | 911 | if (onenand_scan(mtd, 1)) { |
@@ -915,10 +913,7 @@ static int s3c_onenand_probe(struct platform_device *pdev) | |||
915 | goto scan_failed; | 913 | goto scan_failed; |
916 | } | 914 | } |
917 | 915 | ||
918 | if (onenand->type == TYPE_S5PC110) { | 916 | if (onenand->type != TYPE_S5PC110) { |
919 | if (onenand_ctrl_cfg && onenand->dma_addr) | ||
920 | writel(onenand_ctrl_cfg, onenand->dma_addr + 0x100); | ||
921 | } else { | ||
922 | /* S3C doesn't handle subpage write */ | 917 | /* S3C doesn't handle subpage write */ |
923 | mtd->subpage_sft = 0; | 918 | mtd->subpage_sft = 0; |
924 | this->subpagesize = mtd->writesize; | 919 | this->subpagesize = mtd->writesize; |
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c index 2d600a1bf2aa..7a87d07cd79f 100644 --- a/drivers/mtd/redboot.c +++ b/drivers/mtd/redboot.c | |||
@@ -1,6 +1,24 @@ | |||
1 | /* | 1 | /* |
2 | * Parse RedBoot-style Flash Image System (FIS) tables and | 2 | * Parse RedBoot-style Flash Image System (FIS) tables and |
3 | * produce a Linux partition array to match. | 3 | * produce a Linux partition array to match. |
4 | * | ||
5 | * Copyright © 2001 Red Hat UK Limited | ||
6 | * Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org> | ||
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 as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | * | ||
4 | */ | 22 | */ |
5 | 23 | ||
6 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c index 63b83c0d9a13..cc4d1805b864 100644 --- a/drivers/mtd/rfd_ftl.c +++ b/drivers/mtd/rfd_ftl.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * rfd_ftl.c -- resident flash disk (flash translation layer) | 2 | * rfd_ftl.c -- resident flash disk (flash translation layer) |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Sean Young <sean@mess.org> | 4 | * Copyright © 2005 Sean Young <sean@mess.org> |
5 | * | 5 | * |
6 | * This type of flash translation layer (FTL) is used by the Embedded BIOS | 6 | * This type of flash translation layer (FTL) is used by the Embedded BIOS |
7 | * by General Software. It is known as the Resident Flash Disk (RFD), see: | 7 | * by General Software. It is known as the Resident Flash Disk (RFD), see: |
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c index 81c4ecdc11f5..5cd189793332 100644 --- a/drivers/mtd/ssfdc.c +++ b/drivers/mtd/ssfdc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Linux driver for SSFDC Flash Translation Layer (Read only) | 2 | * Linux driver for SSFDC Flash Translation Layer (Read only) |
3 | * (c) 2005 Eptar srl | 3 | * © 2005 Eptar srl |
4 | * Author: Claudio Lanconelli <lanconelli.claudio@eptar.com> | 4 | * Author: Claudio Lanconelli <lanconelli.claudio@eptar.com> |
5 | * | 5 | * |
6 | * Based on NTFL and MTDBLOCK_RO drivers | 6 | * Based on NTFL and MTDBLOCK_RO drivers |
diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c index 6bc1b8276c62..00b937e38c1d 100644 --- a/drivers/mtd/tests/mtd_pagetest.c +++ b/drivers/mtd/tests/mtd_pagetest.c | |||
@@ -310,7 +310,7 @@ static int crosstest(void) | |||
310 | static int erasecrosstest(void) | 310 | static int erasecrosstest(void) |
311 | { | 311 | { |
312 | size_t read = 0, written = 0; | 312 | size_t read = 0, written = 0; |
313 | int err = 0, i, ebnum, ok = 1, ebnum2; | 313 | int err = 0, i, ebnum, ebnum2; |
314 | loff_t addr0; | 314 | loff_t addr0; |
315 | char *readbuf = twopages; | 315 | char *readbuf = twopages; |
316 | 316 | ||
@@ -357,8 +357,7 @@ static int erasecrosstest(void) | |||
357 | if (memcmp(writebuf, readbuf, pgsize)) { | 357 | if (memcmp(writebuf, readbuf, pgsize)) { |
358 | printk(PRINT_PREF "verify failed!\n"); | 358 | printk(PRINT_PREF "verify failed!\n"); |
359 | errcnt += 1; | 359 | errcnt += 1; |
360 | ok = 0; | 360 | return -1; |
361 | return err; | ||
362 | } | 361 | } |
363 | 362 | ||
364 | printk(PRINT_PREF "erasing block %d\n", ebnum); | 363 | printk(PRINT_PREF "erasing block %d\n", ebnum); |
@@ -396,10 +395,10 @@ static int erasecrosstest(void) | |||
396 | if (memcmp(writebuf, readbuf, pgsize)) { | 395 | if (memcmp(writebuf, readbuf, pgsize)) { |
397 | printk(PRINT_PREF "verify failed!\n"); | 396 | printk(PRINT_PREF "verify failed!\n"); |
398 | errcnt += 1; | 397 | errcnt += 1; |
399 | ok = 0; | 398 | return -1; |
400 | } | 399 | } |
401 | 400 | ||
402 | if (ok && !err) | 401 | if (!err) |
403 | printk(PRINT_PREF "erasecrosstest ok\n"); | 402 | printk(PRINT_PREF "erasecrosstest ok\n"); |
404 | return err; | 403 | return err; |
405 | } | 404 | } |
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 066fd5b09fda..ad19585d960b 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
@@ -3198,17 +3198,17 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
3198 | } | 3198 | } |
3199 | } | 3199 | } |
3200 | 3200 | ||
3201 | err = pci_request_regions(pdev, DRV_NAME); | 3201 | err = pci_enable_device(pdev); |
3202 | if (err) { | 3202 | if (err) { |
3203 | /* Just info, some other driver may have claimed the device. */ | 3203 | dev_err(&pdev->dev, "cannot enable PCI device\n"); |
3204 | dev_info(&pdev->dev, "cannot obtain PCI resources\n"); | 3204 | goto out; |
3205 | return err; | ||
3206 | } | 3205 | } |
3207 | 3206 | ||
3208 | err = pci_enable_device(pdev); | 3207 | err = pci_request_regions(pdev, DRV_NAME); |
3209 | if (err) { | 3208 | if (err) { |
3210 | dev_err(&pdev->dev, "cannot enable PCI device\n"); | 3209 | /* Just info, some other driver may have claimed the device. */ |
3211 | goto out_release_regions; | 3210 | dev_info(&pdev->dev, "cannot obtain PCI resources\n"); |
3211 | goto out_disable_device; | ||
3212 | } | 3212 | } |
3213 | 3213 | ||
3214 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { | 3214 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { |
@@ -3217,11 +3217,11 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
3217 | if (err) { | 3217 | if (err) { |
3218 | dev_err(&pdev->dev, "unable to obtain 64-bit DMA for " | 3218 | dev_err(&pdev->dev, "unable to obtain 64-bit DMA for " |
3219 | "coherent allocations\n"); | 3219 | "coherent allocations\n"); |
3220 | goto out_disable_device; | 3220 | goto out_release_regions; |
3221 | } | 3221 | } |
3222 | } else if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) { | 3222 | } else if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) { |
3223 | dev_err(&pdev->dev, "no usable DMA configuration\n"); | 3223 | dev_err(&pdev->dev, "no usable DMA configuration\n"); |
3224 | goto out_disable_device; | 3224 | goto out_release_regions; |
3225 | } | 3225 | } |
3226 | 3226 | ||
3227 | pci_set_master(pdev); | 3227 | pci_set_master(pdev); |
@@ -3234,7 +3234,7 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
3234 | adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); | 3234 | adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); |
3235 | if (!adapter) { | 3235 | if (!adapter) { |
3236 | err = -ENOMEM; | 3236 | err = -ENOMEM; |
3237 | goto out_disable_device; | 3237 | goto out_release_regions; |
3238 | } | 3238 | } |
3239 | 3239 | ||
3240 | adapter->nofail_skb = | 3240 | adapter->nofail_skb = |
@@ -3370,11 +3370,12 @@ out_free_dev: | |||
3370 | out_free_adapter: | 3370 | out_free_adapter: |
3371 | kfree(adapter); | 3371 | kfree(adapter); |
3372 | 3372 | ||
3373 | out_disable_device: | ||
3374 | pci_disable_device(pdev); | ||
3375 | out_release_regions: | 3373 | out_release_regions: |
3376 | pci_release_regions(pdev); | 3374 | pci_release_regions(pdev); |
3375 | out_disable_device: | ||
3376 | pci_disable_device(pdev); | ||
3377 | pci_set_drvdata(pdev, NULL); | 3377 | pci_set_drvdata(pdev, NULL); |
3378 | out: | ||
3378 | return err; | 3379 | return err; |
3379 | } | 3380 | } |
3380 | 3381 | ||
diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c index a16563219ac9..7b6d07f50c71 100644 --- a/drivers/net/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/cxgb4vf/cxgb4vf_main.c | |||
@@ -2462,23 +2462,24 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev, | |||
2462 | version_printed = 1; | 2462 | version_printed = 1; |
2463 | } | 2463 | } |
2464 | 2464 | ||
2465 | |||
2465 | /* | 2466 | /* |
2466 | * Reserve PCI resources for the device. If we can't get them some | 2467 | * Initialize generic PCI device state. |
2467 | * other driver may have already claimed the device ... | ||
2468 | */ | 2468 | */ |
2469 | err = pci_request_regions(pdev, KBUILD_MODNAME); | 2469 | err = pci_enable_device(pdev); |
2470 | if (err) { | 2470 | if (err) { |
2471 | dev_err(&pdev->dev, "cannot obtain PCI resources\n"); | 2471 | dev_err(&pdev->dev, "cannot enable PCI device\n"); |
2472 | return err; | 2472 | return err; |
2473 | } | 2473 | } |
2474 | 2474 | ||
2475 | /* | 2475 | /* |
2476 | * Initialize generic PCI device state. | 2476 | * Reserve PCI resources for the device. If we can't get them some |
2477 | * other driver may have already claimed the device ... | ||
2477 | */ | 2478 | */ |
2478 | err = pci_enable_device(pdev); | 2479 | err = pci_request_regions(pdev, KBUILD_MODNAME); |
2479 | if (err) { | 2480 | if (err) { |
2480 | dev_err(&pdev->dev, "cannot enable PCI device\n"); | 2481 | dev_err(&pdev->dev, "cannot obtain PCI resources\n"); |
2481 | goto err_release_regions; | 2482 | goto err_disable_device; |
2482 | } | 2483 | } |
2483 | 2484 | ||
2484 | /* | 2485 | /* |
@@ -2491,14 +2492,14 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev, | |||
2491 | if (err) { | 2492 | if (err) { |
2492 | dev_err(&pdev->dev, "unable to obtain 64-bit DMA for" | 2493 | dev_err(&pdev->dev, "unable to obtain 64-bit DMA for" |
2493 | " coherent allocations\n"); | 2494 | " coherent allocations\n"); |
2494 | goto err_disable_device; | 2495 | goto err_release_regions; |
2495 | } | 2496 | } |
2496 | pci_using_dac = 1; | 2497 | pci_using_dac = 1; |
2497 | } else { | 2498 | } else { |
2498 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | 2499 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
2499 | if (err != 0) { | 2500 | if (err != 0) { |
2500 | dev_err(&pdev->dev, "no usable DMA configuration\n"); | 2501 | dev_err(&pdev->dev, "no usable DMA configuration\n"); |
2501 | goto err_disable_device; | 2502 | goto err_release_regions; |
2502 | } | 2503 | } |
2503 | pci_using_dac = 0; | 2504 | pci_using_dac = 0; |
2504 | } | 2505 | } |
@@ -2514,7 +2515,7 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev, | |||
2514 | adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); | 2515 | adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); |
2515 | if (!adapter) { | 2516 | if (!adapter) { |
2516 | err = -ENOMEM; | 2517 | err = -ENOMEM; |
2517 | goto err_disable_device; | 2518 | goto err_release_regions; |
2518 | } | 2519 | } |
2519 | pci_set_drvdata(pdev, adapter); | 2520 | pci_set_drvdata(pdev, adapter); |
2520 | adapter->pdev = pdev; | 2521 | adapter->pdev = pdev; |
@@ -2750,13 +2751,13 @@ err_free_adapter: | |||
2750 | kfree(adapter); | 2751 | kfree(adapter); |
2751 | pci_set_drvdata(pdev, NULL); | 2752 | pci_set_drvdata(pdev, NULL); |
2752 | 2753 | ||
2753 | err_disable_device: | ||
2754 | pci_disable_device(pdev); | ||
2755 | pci_clear_master(pdev); | ||
2756 | |||
2757 | err_release_regions: | 2754 | err_release_regions: |
2758 | pci_release_regions(pdev); | 2755 | pci_release_regions(pdev); |
2759 | pci_set_drvdata(pdev, NULL); | 2756 | pci_set_drvdata(pdev, NULL); |
2757 | pci_clear_master(pdev); | ||
2758 | |||
2759 | err_disable_device: | ||
2760 | pci_disable_device(pdev); | ||
2760 | 2761 | ||
2761 | err_out: | 2762 | err_out: |
2762 | return err; | 2763 | return err; |
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index d0824e322068..7fbd052ddb0a 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c | |||
@@ -2944,8 +2944,8 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev) | |||
2944 | release_mem_region(res->start, res->end - res->start + 1); | 2944 | release_mem_region(res->start, res->end - res->start + 1); |
2945 | 2945 | ||
2946 | unregister_netdev(ndev); | 2946 | unregister_netdev(ndev); |
2947 | free_netdev(ndev); | ||
2948 | iounmap(priv->remap_addr); | 2947 | iounmap(priv->remap_addr); |
2948 | free_netdev(ndev); | ||
2949 | 2949 | ||
2950 | clk_disable(emac_clk); | 2950 | clk_disable(emac_clk); |
2951 | clk_put(emac_clk); | 2951 | clk_put(emac_clk); |
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index b194bad29ace..8e2eab4e7c75 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
@@ -1779,6 +1779,7 @@ static int e100_tx_clean(struct nic *nic) | |||
1779 | for (cb = nic->cb_to_clean; | 1779 | for (cb = nic->cb_to_clean; |
1780 | cb->status & cpu_to_le16(cb_complete); | 1780 | cb->status & cpu_to_le16(cb_complete); |
1781 | cb = nic->cb_to_clean = cb->next) { | 1781 | cb = nic->cb_to_clean = cb->next) { |
1782 | rmb(); /* read skb after status */ | ||
1782 | netif_printk(nic, tx_done, KERN_DEBUG, nic->netdev, | 1783 | netif_printk(nic, tx_done, KERN_DEBUG, nic->netdev, |
1783 | "cb[%d]->status = 0x%04X\n", | 1784 | "cb[%d]->status = 0x%04X\n", |
1784 | (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), | 1785 | (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), |
@@ -1927,6 +1928,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
1927 | 1928 | ||
1928 | netif_printk(nic, rx_status, KERN_DEBUG, nic->netdev, | 1929 | netif_printk(nic, rx_status, KERN_DEBUG, nic->netdev, |
1929 | "status=0x%04X\n", rfd_status); | 1930 | "status=0x%04X\n", rfd_status); |
1931 | rmb(); /* read size after status bit */ | ||
1930 | 1932 | ||
1931 | /* If data isn't ready, nothing to indicate */ | 1933 | /* If data isn't ready, nothing to indicate */ |
1932 | if (unlikely(!(rfd_status & cb_complete))) { | 1934 | if (unlikely(!(rfd_status & cb_complete))) { |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 02833af8a0b1..5cc39ed289c6 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -3454,6 +3454,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, | |||
3454 | while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && | 3454 | while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && |
3455 | (count < tx_ring->count)) { | 3455 | (count < tx_ring->count)) { |
3456 | bool cleaned = false; | 3456 | bool cleaned = false; |
3457 | rmb(); /* read buffer_info after eop_desc */ | ||
3457 | for ( ; !cleaned; count++) { | 3458 | for ( ; !cleaned; count++) { |
3458 | tx_desc = E1000_TX_DESC(*tx_ring, i); | 3459 | tx_desc = E1000_TX_DESC(*tx_ring, i); |
3459 | buffer_info = &tx_ring->buffer_info[i]; | 3460 | buffer_info = &tx_ring->buffer_info[i]; |
@@ -3643,6 +3644,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, | |||
3643 | if (*work_done >= work_to_do) | 3644 | if (*work_done >= work_to_do) |
3644 | break; | 3645 | break; |
3645 | (*work_done)++; | 3646 | (*work_done)++; |
3647 | rmb(); /* read descriptor and rx_buffer_info after status DD */ | ||
3646 | 3648 | ||
3647 | status = rx_desc->status; | 3649 | status = rx_desc->status; |
3648 | skb = buffer_info->skb; | 3650 | skb = buffer_info->skb; |
@@ -3849,6 +3851,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, | |||
3849 | if (*work_done >= work_to_do) | 3851 | if (*work_done >= work_to_do) |
3850 | break; | 3852 | break; |
3851 | (*work_done)++; | 3853 | (*work_done)++; |
3854 | rmb(); /* read descriptor and rx_buffer_info after status DD */ | ||
3852 | 3855 | ||
3853 | status = rx_desc->status; | 3856 | status = rx_desc->status; |
3854 | skb = buffer_info->skb; | 3857 | skb = buffer_info->skb; |
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 521c6ee1f32a..2b8ef44bd2b1 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -781,6 +781,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, | |||
781 | if (*work_done >= work_to_do) | 781 | if (*work_done >= work_to_do) |
782 | break; | 782 | break; |
783 | (*work_done)++; | 783 | (*work_done)++; |
784 | rmb(); /* read descriptor and rx_buffer_info after status DD */ | ||
784 | 785 | ||
785 | status = rx_desc->status; | 786 | status = rx_desc->status; |
786 | skb = buffer_info->skb; | 787 | skb = buffer_info->skb; |
@@ -991,6 +992,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) | |||
991 | while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && | 992 | while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && |
992 | (count < tx_ring->count)) { | 993 | (count < tx_ring->count)) { |
993 | bool cleaned = false; | 994 | bool cleaned = false; |
995 | rmb(); /* read buffer_info after eop_desc */ | ||
994 | for (; !cleaned; count++) { | 996 | for (; !cleaned; count++) { |
995 | tx_desc = E1000_TX_DESC(*tx_ring, i); | 997 | tx_desc = E1000_TX_DESC(*tx_ring, i); |
996 | buffer_info = &tx_ring->buffer_info[i]; | 998 | buffer_info = &tx_ring->buffer_info[i]; |
@@ -1087,6 +1089,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, | |||
1087 | break; | 1089 | break; |
1088 | (*work_done)++; | 1090 | (*work_done)++; |
1089 | skb = buffer_info->skb; | 1091 | skb = buffer_info->skb; |
1092 | rmb(); /* read descriptor and rx_buffer_info after status DD */ | ||
1090 | 1093 | ||
1091 | /* in the packet split case this is header only */ | 1094 | /* in the packet split case this is header only */ |
1092 | prefetch(skb->data - NET_IP_ALIGN); | 1095 | prefetch(skb->data - NET_IP_ALIGN); |
@@ -1286,6 +1289,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, | |||
1286 | if (*work_done >= work_to_do) | 1289 | if (*work_done >= work_to_do) |
1287 | break; | 1290 | break; |
1288 | (*work_done)++; | 1291 | (*work_done)++; |
1292 | rmb(); /* read descriptor and rx_buffer_info after status DD */ | ||
1289 | 1293 | ||
1290 | status = rx_desc->status; | 1294 | status = rx_desc->status; |
1291 | skb = buffer_info->skb; | 1295 | skb = buffer_info->skb; |
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 77a7f87d498e..9aab85366d21 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c | |||
@@ -1087,10 +1087,7 @@ static int enic_set_port_profile(struct enic *enic, u8 *mac) | |||
1087 | { | 1087 | { |
1088 | struct vic_provinfo *vp; | 1088 | struct vic_provinfo *vp; |
1089 | u8 oui[3] = VIC_PROVINFO_CISCO_OUI; | 1089 | u8 oui[3] = VIC_PROVINFO_CISCO_OUI; |
1090 | u8 *uuid; | ||
1091 | char uuid_str[38]; | 1090 | char uuid_str[38]; |
1092 | static char *uuid_fmt = "%02X%02X%02X%02X-%02X%02X-%02X%02X-" | ||
1093 | "%02X%02X-%02X%02X%02X%02X%0X%02X"; | ||
1094 | int err; | 1091 | int err; |
1095 | 1092 | ||
1096 | err = enic_vnic_dev_deinit(enic); | 1093 | err = enic_vnic_dev_deinit(enic); |
@@ -1121,24 +1118,14 @@ static int enic_set_port_profile(struct enic *enic, u8 *mac) | |||
1121 | ETH_ALEN, mac); | 1118 | ETH_ALEN, mac); |
1122 | 1119 | ||
1123 | if (enic->pp.set & ENIC_SET_INSTANCE) { | 1120 | if (enic->pp.set & ENIC_SET_INSTANCE) { |
1124 | uuid = enic->pp.instance_uuid; | 1121 | sprintf(uuid_str, "%pUB", enic->pp.instance_uuid); |
1125 | sprintf(uuid_str, uuid_fmt, | ||
1126 | uuid[0], uuid[1], uuid[2], uuid[3], | ||
1127 | uuid[4], uuid[5], uuid[6], uuid[7], | ||
1128 | uuid[8], uuid[9], uuid[10], uuid[11], | ||
1129 | uuid[12], uuid[13], uuid[14], uuid[15]); | ||
1130 | vic_provinfo_add_tlv(vp, | 1122 | vic_provinfo_add_tlv(vp, |
1131 | VIC_LINUX_PROV_TLV_CLIENT_UUID_STR, | 1123 | VIC_LINUX_PROV_TLV_CLIENT_UUID_STR, |
1132 | sizeof(uuid_str), uuid_str); | 1124 | sizeof(uuid_str), uuid_str); |
1133 | } | 1125 | } |
1134 | 1126 | ||
1135 | if (enic->pp.set & ENIC_SET_HOST) { | 1127 | if (enic->pp.set & ENIC_SET_HOST) { |
1136 | uuid = enic->pp.host_uuid; | 1128 | sprintf(uuid_str, "%pUB", enic->pp.host_uuid); |
1137 | sprintf(uuid_str, uuid_fmt, | ||
1138 | uuid[0], uuid[1], uuid[2], uuid[3], | ||
1139 | uuid[4], uuid[5], uuid[6], uuid[7], | ||
1140 | uuid[8], uuid[9], uuid[10], uuid[11], | ||
1141 | uuid[12], uuid[13], uuid[14], uuid[15]); | ||
1142 | vic_provinfo_add_tlv(vp, | 1129 | vic_provinfo_add_tlv(vp, |
1143 | VIC_LINUX_PROV_TLV_HOST_UUID_STR, | 1130 | VIC_LINUX_PROV_TLV_HOST_UUID_STR, |
1144 | sizeof(uuid_str), uuid_str); | 1131 | sizeof(uuid_str), uuid_str); |
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index df5dcd23e4fc..9b4e5895f5f9 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
@@ -5353,6 +5353,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) | |||
5353 | 5353 | ||
5354 | while ((eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD)) && | 5354 | while ((eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD)) && |
5355 | (count < tx_ring->count)) { | 5355 | (count < tx_ring->count)) { |
5356 | rmb(); /* read buffer_info after eop_desc status */ | ||
5356 | for (cleaned = false; !cleaned; count++) { | 5357 | for (cleaned = false; !cleaned; count++) { |
5357 | tx_desc = E1000_TX_DESC_ADV(*tx_ring, i); | 5358 | tx_desc = E1000_TX_DESC_ADV(*tx_ring, i); |
5358 | buffer_info = &tx_ring->buffer_info[i]; | 5359 | buffer_info = &tx_ring->buffer_info[i]; |
@@ -5558,6 +5559,7 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector, | |||
5558 | if (*work_done >= budget) | 5559 | if (*work_done >= budget) |
5559 | break; | 5560 | break; |
5560 | (*work_done)++; | 5561 | (*work_done)++; |
5562 | rmb(); /* read descriptor and rx_buffer_info after status DD */ | ||
5561 | 5563 | ||
5562 | skb = buffer_info->skb; | 5564 | skb = buffer_info->skb; |
5563 | prefetch(skb->data - NET_IP_ALIGN); | 5565 | prefetch(skb->data - NET_IP_ALIGN); |
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index ec808fa8dc21..c539f7c9c3e0 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c | |||
@@ -248,6 +248,7 @@ static bool igbvf_clean_rx_irq(struct igbvf_adapter *adapter, | |||
248 | if (*work_done >= work_to_do) | 248 | if (*work_done >= work_to_do) |
249 | break; | 249 | break; |
250 | (*work_done)++; | 250 | (*work_done)++; |
251 | rmb(); /* read descriptor and rx_buffer_info after status DD */ | ||
251 | 252 | ||
252 | buffer_info = &rx_ring->buffer_info[i]; | 253 | buffer_info = &rx_ring->buffer_info[i]; |
253 | 254 | ||
@@ -780,6 +781,7 @@ static bool igbvf_clean_tx_irq(struct igbvf_ring *tx_ring) | |||
780 | 781 | ||
781 | while ((eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD)) && | 782 | while ((eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD)) && |
782 | (count < tx_ring->count)) { | 783 | (count < tx_ring->count)) { |
784 | rmb(); /* read buffer_info after eop_desc status */ | ||
783 | for (cleaned = false; !cleaned; count++) { | 785 | for (cleaned = false; !cleaned; count++) { |
784 | tx_desc = IGBVF_TX_DESC_ADV(*tx_ring, i); | 786 | tx_desc = IGBVF_TX_DESC_ADV(*tx_ring, i); |
785 | buffer_info = &tx_ring->buffer_info[i]; | 787 | buffer_info = &tx_ring->buffer_info[i]; |
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index c6b75c83100c..45fc89b9ba64 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c | |||
@@ -1816,6 +1816,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter) | |||
1816 | 1816 | ||
1817 | while (eop_desc->status & IXGB_TX_DESC_STATUS_DD) { | 1817 | while (eop_desc->status & IXGB_TX_DESC_STATUS_DD) { |
1818 | 1818 | ||
1819 | rmb(); /* read buffer_info after eop_desc */ | ||
1819 | for (cleaned = false; !cleaned; ) { | 1820 | for (cleaned = false; !cleaned; ) { |
1820 | tx_desc = IXGB_TX_DESC(*tx_ring, i); | 1821 | tx_desc = IXGB_TX_DESC(*tx_ring, i); |
1821 | buffer_info = &tx_ring->buffer_info[i]; | 1822 | buffer_info = &tx_ring->buffer_info[i]; |
@@ -1976,6 +1977,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter, int *work_done, int work_to_do) | |||
1976 | break; | 1977 | break; |
1977 | 1978 | ||
1978 | (*work_done)++; | 1979 | (*work_done)++; |
1980 | rmb(); /* read descriptor and rx_buffer_info after status DD */ | ||
1979 | status = rx_desc->status; | 1981 | status = rx_desc->status; |
1980 | skb = buffer_info->skb; | 1982 | skb = buffer_info->skb; |
1981 | buffer_info->skb = NULL; | 1983 | buffer_info->skb = NULL; |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 7d6a415bcf88..e32af434cc9d 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -748,6 +748,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, | |||
748 | while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && | 748 | while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && |
749 | (count < tx_ring->work_limit)) { | 749 | (count < tx_ring->work_limit)) { |
750 | bool cleaned = false; | 750 | bool cleaned = false; |
751 | rmb(); /* read buffer_info after eop_desc */ | ||
751 | for ( ; !cleaned; count++) { | 752 | for ( ; !cleaned; count++) { |
752 | struct sk_buff *skb; | 753 | struct sk_buff *skb; |
753 | tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); | 754 | tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); |
@@ -6155,9 +6156,11 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb) | |||
6155 | txq &= (adapter->ring_feature[RING_F_FCOE].indices - 1); | 6156 | txq &= (adapter->ring_feature[RING_F_FCOE].indices - 1); |
6156 | txq += adapter->ring_feature[RING_F_FCOE].mask; | 6157 | txq += adapter->ring_feature[RING_F_FCOE].mask; |
6157 | return txq; | 6158 | return txq; |
6159 | #ifdef CONFIG_IXGBE_DCB | ||
6158 | } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | 6160 | } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { |
6159 | txq = adapter->fcoe.up; | 6161 | txq = adapter->fcoe.up; |
6160 | return txq; | 6162 | return txq; |
6163 | #endif | ||
6161 | } | 6164 | } |
6162 | } | 6165 | } |
6163 | #endif | 6166 | #endif |
@@ -6216,10 +6219,14 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, | |||
6216 | if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED && | 6219 | if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED && |
6217 | (skb->protocol == htons(ETH_P_FCOE) || | 6220 | (skb->protocol == htons(ETH_P_FCOE) || |
6218 | skb->protocol == htons(ETH_P_FIP))) { | 6221 | skb->protocol == htons(ETH_P_FIP))) { |
6219 | tx_flags &= ~(IXGBE_TX_FLAGS_VLAN_PRIO_MASK | 6222 | #ifdef CONFIG_IXGBE_DCB |
6220 | << IXGBE_TX_FLAGS_VLAN_SHIFT); | 6223 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { |
6221 | tx_flags |= ((adapter->fcoe.up << 13) | 6224 | tx_flags &= ~(IXGBE_TX_FLAGS_VLAN_PRIO_MASK |
6222 | << IXGBE_TX_FLAGS_VLAN_SHIFT); | 6225 | << IXGBE_TX_FLAGS_VLAN_SHIFT); |
6226 | tx_flags |= ((adapter->fcoe.up << 13) | ||
6227 | << IXGBE_TX_FLAGS_VLAN_SHIFT); | ||
6228 | } | ||
6229 | #endif | ||
6223 | /* flag for FCoE offloads */ | 6230 | /* flag for FCoE offloads */ |
6224 | if (skb->protocol == htons(ETH_P_FCOE)) | 6231 | if (skb->protocol == htons(ETH_P_FCOE)) |
6225 | tx_flags |= IXGBE_TX_FLAGS_FCOE; | 6232 | tx_flags |= IXGBE_TX_FLAGS_FCOE; |
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 3e291ccc629d..918c00359b0a 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c | |||
@@ -231,6 +231,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter, | |||
231 | while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && | 231 | while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && |
232 | (count < tx_ring->work_limit)) { | 232 | (count < tx_ring->work_limit)) { |
233 | bool cleaned = false; | 233 | bool cleaned = false; |
234 | rmb(); /* read buffer_info after eop_desc */ | ||
234 | for ( ; !cleaned; count++) { | 235 | for ( ; !cleaned; count++) { |
235 | struct sk_buff *skb; | 236 | struct sk_buff *skb; |
236 | tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); | 237 | tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); |
@@ -518,6 +519,7 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, | |||
518 | break; | 519 | break; |
519 | (*work_done)++; | 520 | (*work_done)++; |
520 | 521 | ||
522 | rmb(); /* read descriptor and rx_buffer_info after status DD */ | ||
521 | if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { | 523 | if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { |
522 | hdr_info = le16_to_cpu(ixgbevf_get_hdr_info(rx_desc)); | 524 | hdr_info = le16_to_cpu(ixgbevf_get_hdr_info(rx_desc)); |
523 | len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >> | 525 | len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >> |
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 6ce6ce1df6d2..fd86e18604e6 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -2001,27 +2001,26 @@ static void netxen_tx_timeout_task(struct work_struct *work) | |||
2001 | if (++adapter->tx_timeo_cnt >= NX_MAX_TX_TIMEOUTS) | 2001 | if (++adapter->tx_timeo_cnt >= NX_MAX_TX_TIMEOUTS) |
2002 | goto request_reset; | 2002 | goto request_reset; |
2003 | 2003 | ||
2004 | rtnl_lock(); | ||
2004 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | 2005 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { |
2005 | /* try to scrub interrupt */ | 2006 | /* try to scrub interrupt */ |
2006 | netxen_napi_disable(adapter); | 2007 | netxen_napi_disable(adapter); |
2007 | 2008 | ||
2008 | adapter->netdev->trans_start = jiffies; | ||
2009 | |||
2010 | netxen_napi_enable(adapter); | 2009 | netxen_napi_enable(adapter); |
2011 | 2010 | ||
2012 | netif_wake_queue(adapter->netdev); | 2011 | netif_wake_queue(adapter->netdev); |
2013 | 2012 | ||
2014 | clear_bit(__NX_RESETTING, &adapter->state); | 2013 | clear_bit(__NX_RESETTING, &adapter->state); |
2015 | return; | ||
2016 | } else { | 2014 | } else { |
2017 | clear_bit(__NX_RESETTING, &adapter->state); | 2015 | clear_bit(__NX_RESETTING, &adapter->state); |
2018 | if (!netxen_nic_reset_context(adapter)) { | 2016 | if (netxen_nic_reset_context(adapter)) { |
2019 | adapter->netdev->trans_start = jiffies; | 2017 | rtnl_unlock(); |
2020 | return; | 2018 | goto request_reset; |
2021 | } | 2019 | } |
2022 | |||
2023 | /* context reset failed, fall through for fw reset */ | ||
2024 | } | 2020 | } |
2021 | adapter->netdev->trans_start = jiffies; | ||
2022 | rtnl_unlock(); | ||
2023 | return; | ||
2025 | 2024 | ||
2026 | request_reset: | 2025 | request_reset: |
2027 | adapter->need_fw_reset = 1; | 2026 | adapter->need_fw_reset = 1; |
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 6c2e8fa0ca31..af50a530daee 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c | |||
@@ -108,9 +108,9 @@ static void ppp_async_process(unsigned long arg); | |||
108 | static void async_lcp_peek(struct asyncppp *ap, unsigned char *data, | 108 | static void async_lcp_peek(struct asyncppp *ap, unsigned char *data, |
109 | int len, int inbound); | 109 | int len, int inbound); |
110 | 110 | ||
111 | static struct ppp_channel_ops async_ops = { | 111 | static const struct ppp_channel_ops async_ops = { |
112 | ppp_async_send, | 112 | .start_xmit = ppp_async_send, |
113 | ppp_async_ioctl | 113 | .ioctl = ppp_async_ioctl, |
114 | }; | 114 | }; |
115 | 115 | ||
116 | /* | 116 | /* |
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 52938da1e542..4c95ec3fb8d4 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c | |||
@@ -97,9 +97,9 @@ static void ppp_sync_flush_output(struct syncppp *ap); | |||
97 | static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf, | 97 | static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf, |
98 | char *flags, int count); | 98 | char *flags, int count); |
99 | 99 | ||
100 | static struct ppp_channel_ops sync_ops = { | 100 | static const struct ppp_channel_ops sync_ops = { |
101 | ppp_sync_send, | 101 | .start_xmit = ppp_sync_send, |
102 | ppp_sync_ioctl | 102 | .ioctl = ppp_sync_ioctl, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | /* | 105 | /* |
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 344ef330e123..c07de359dc07 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c | |||
@@ -92,7 +92,7 @@ | |||
92 | static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb); | 92 | static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb); |
93 | 93 | ||
94 | static const struct proto_ops pppoe_ops; | 94 | static const struct proto_ops pppoe_ops; |
95 | static struct ppp_channel_ops pppoe_chan_ops; | 95 | static const struct ppp_channel_ops pppoe_chan_ops; |
96 | 96 | ||
97 | /* per-net private data for this module */ | 97 | /* per-net private data for this module */ |
98 | static int pppoe_net_id __read_mostly; | 98 | static int pppoe_net_id __read_mostly; |
@@ -963,7 +963,7 @@ static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
963 | return __pppoe_xmit(sk, skb); | 963 | return __pppoe_xmit(sk, skb); |
964 | } | 964 | } |
965 | 965 | ||
966 | static struct ppp_channel_ops pppoe_chan_ops = { | 966 | static const struct ppp_channel_ops pppoe_chan_ops = { |
967 | .start_xmit = pppoe_xmit, | 967 | .start_xmit = pppoe_xmit, |
968 | }; | 968 | }; |
969 | 969 | ||
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 3b03794ac3f5..7f62e2dea28f 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
@@ -1457,7 +1457,6 @@ int usbnet_resume (struct usb_interface *intf) | |||
1457 | spin_lock_irq(&dev->txq.lock); | 1457 | spin_lock_irq(&dev->txq.lock); |
1458 | while ((res = usb_get_from_anchor(&dev->deferred))) { | 1458 | while ((res = usb_get_from_anchor(&dev->deferred))) { |
1459 | 1459 | ||
1460 | printk(KERN_INFO"%s has delayed data\n", __func__); | ||
1461 | skb = (struct sk_buff *)res->context; | 1460 | skb = (struct sk_buff *)res->context; |
1462 | retval = usb_submit_urb(res, GFP_ATOMIC); | 1461 | retval = usb_submit_urb(res, GFP_ATOMIC); |
1463 | if (retval < 0) { | 1462 | if (retval < 0) { |
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 42dffd3e5795..fd69095ef6e3 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c | |||
@@ -2763,12 +2763,12 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi | |||
2763 | 2763 | ||
2764 | vptr->dev = dev; | 2764 | vptr->dev = dev; |
2765 | 2765 | ||
2766 | dev->irq = pdev->irq; | ||
2767 | |||
2768 | ret = pci_enable_device(pdev); | 2766 | ret = pci_enable_device(pdev); |
2769 | if (ret < 0) | 2767 | if (ret < 0) |
2770 | goto err_free_dev; | 2768 | goto err_free_dev; |
2771 | 2769 | ||
2770 | dev->irq = pdev->irq; | ||
2771 | |||
2772 | ret = velocity_get_pci_info(vptr, pdev); | 2772 | ret = velocity_get_pci_info(vptr, pdev); |
2773 | if (ret < 0) { | 2773 | if (ret < 0) { |
2774 | /* error message already printed */ | 2774 | /* error message already printed */ |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index bb6b67f6b0cc..4598e9d2608f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -705,6 +705,19 @@ static int virtnet_close(struct net_device *dev) | |||
705 | return 0; | 705 | return 0; |
706 | } | 706 | } |
707 | 707 | ||
708 | static void virtnet_get_drvinfo(struct net_device *dev, | ||
709 | struct ethtool_drvinfo *drvinfo) | ||
710 | { | ||
711 | struct virtnet_info *vi = netdev_priv(dev); | ||
712 | struct virtio_device *vdev = vi->vdev; | ||
713 | |||
714 | strncpy(drvinfo->driver, KBUILD_MODNAME, ARRAY_SIZE(drvinfo->driver)); | ||
715 | strncpy(drvinfo->version, "N/A", ARRAY_SIZE(drvinfo->version)); | ||
716 | strncpy(drvinfo->fw_version, "N/A", ARRAY_SIZE(drvinfo->fw_version)); | ||
717 | strncpy(drvinfo->bus_info, dev_name(&vdev->dev), | ||
718 | ARRAY_SIZE(drvinfo->bus_info)); | ||
719 | } | ||
720 | |||
708 | static int virtnet_set_tx_csum(struct net_device *dev, u32 data) | 721 | static int virtnet_set_tx_csum(struct net_device *dev, u32 data) |
709 | { | 722 | { |
710 | struct virtnet_info *vi = netdev_priv(dev); | 723 | struct virtnet_info *vi = netdev_priv(dev); |
@@ -817,6 +830,7 @@ static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) | |||
817 | } | 830 | } |
818 | 831 | ||
819 | static const struct ethtool_ops virtnet_ethtool_ops = { | 832 | static const struct ethtool_ops virtnet_ethtool_ops = { |
833 | .get_drvinfo = virtnet_get_drvinfo, | ||
820 | .set_tx_csum = virtnet_set_tx_csum, | 834 | .set_tx_csum = virtnet_set_tx_csum, |
821 | .set_sg = ethtool_op_set_sg, | 835 | .set_sg = ethtool_op_set_sg, |
822 | .set_tso = ethtool_op_set_tso, | 836 | .set_tso = ethtool_op_set_tso, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index dabafb874c36..fe7418aefc4a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
@@ -63,6 +63,7 @@ static bool ar9002_hw_per_calibration(struct ath_hw *ah, | |||
63 | u8 rxchainmask, | 63 | u8 rxchainmask, |
64 | struct ath9k_cal_list *currCal) | 64 | struct ath9k_cal_list *currCal) |
65 | { | 65 | { |
66 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
66 | bool iscaldone = false; | 67 | bool iscaldone = false; |
67 | 68 | ||
68 | if (currCal->calState == CAL_RUNNING) { | 69 | if (currCal->calState == CAL_RUNNING) { |
@@ -81,14 +82,14 @@ static bool ar9002_hw_per_calibration(struct ath_hw *ah, | |||
81 | } | 82 | } |
82 | 83 | ||
83 | currCal->calData->calPostProc(ah, numChains); | 84 | currCal->calData->calPostProc(ah, numChains); |
84 | ichan->CalValid |= currCal->calData->calType; | 85 | caldata->CalValid |= currCal->calData->calType; |
85 | currCal->calState = CAL_DONE; | 86 | currCal->calState = CAL_DONE; |
86 | iscaldone = true; | 87 | iscaldone = true; |
87 | } else { | 88 | } else { |
88 | ar9002_hw_setup_calibration(ah, currCal); | 89 | ar9002_hw_setup_calibration(ah, currCal); |
89 | } | 90 | } |
90 | } | 91 | } |
91 | } else if (!(ichan->CalValid & currCal->calData->calType)) { | 92 | } else if (!(caldata->CalValid & currCal->calData->calType)) { |
92 | ath9k_hw_reset_calibration(ah, currCal); | 93 | ath9k_hw_reset_calibration(ah, currCal); |
93 | } | 94 | } |
94 | 95 | ||
@@ -686,8 +687,13 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, | |||
686 | { | 687 | { |
687 | bool iscaldone = true; | 688 | bool iscaldone = true; |
688 | struct ath9k_cal_list *currCal = ah->cal_list_curr; | 689 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
690 | bool nfcal, nfcal_pending = false; | ||
689 | 691 | ||
690 | if (currCal && | 692 | nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF); |
693 | if (ah->caldata) | ||
694 | nfcal_pending = ah->caldata->nfcal_pending; | ||
695 | |||
696 | if (currCal && !nfcal && | ||
691 | (currCal->calState == CAL_RUNNING || | 697 | (currCal->calState == CAL_RUNNING || |
692 | currCal->calState == CAL_WAITING)) { | 698 | currCal->calState == CAL_WAITING)) { |
693 | iscaldone = ar9002_hw_per_calibration(ah, chan, | 699 | iscaldone = ar9002_hw_per_calibration(ah, chan, |
@@ -703,7 +709,7 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, | |||
703 | } | 709 | } |
704 | 710 | ||
705 | /* Do NF cal only at longer intervals */ | 711 | /* Do NF cal only at longer intervals */ |
706 | if (longcal) { | 712 | if (longcal || nfcal_pending) { |
707 | /* Do periodic PAOffset Cal */ | 713 | /* Do periodic PAOffset Cal */ |
708 | ar9002_hw_pa_cal(ah, false); | 714 | ar9002_hw_pa_cal(ah, false); |
709 | ar9002_hw_olc_temp_compensation(ah); | 715 | ar9002_hw_olc_temp_compensation(ah); |
@@ -712,16 +718,18 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, | |||
712 | * Get the value from the previous NF cal and update | 718 | * Get the value from the previous NF cal and update |
713 | * history buffer. | 719 | * history buffer. |
714 | */ | 720 | */ |
715 | ath9k_hw_getnf(ah, chan); | 721 | if (ath9k_hw_getnf(ah, chan)) { |
716 | 722 | /* | |
717 | /* | 723 | * Load the NF from history buffer of the current |
718 | * Load the NF from history buffer of the current channel. | 724 | * channel. |
719 | * NF is slow time-variant, so it is OK to use a historical | 725 | * NF is slow time-variant, so it is OK to use a |
720 | * value. | 726 | * historical value. |
721 | */ | 727 | */ |
722 | ath9k_hw_loadnf(ah, ah->curchan); | 728 | ath9k_hw_loadnf(ah, ah->curchan); |
729 | } | ||
723 | 730 | ||
724 | ath9k_hw_start_nfcal(ah); | 731 | if (longcal) |
732 | ath9k_hw_start_nfcal(ah, false); | ||
725 | } | 733 | } |
726 | 734 | ||
727 | return iscaldone; | 735 | return iscaldone; |
@@ -869,8 +877,10 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
869 | ar9002_hw_pa_cal(ah, true); | 877 | ar9002_hw_pa_cal(ah, true); |
870 | 878 | ||
871 | /* Do NF Calibration after DC offset and other calibrations */ | 879 | /* Do NF Calibration after DC offset and other calibrations */ |
872 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | 880 | ath9k_hw_start_nfcal(ah, true); |
873 | REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); | 881 | |
882 | if (ah->caldata) | ||
883 | ah->caldata->nfcal_pending = true; | ||
874 | 884 | ||
875 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | 885 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
876 | 886 | ||
@@ -901,7 +911,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
901 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); | 911 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); |
902 | } | 912 | } |
903 | 913 | ||
904 | chan->CalValid = 0; | 914 | if (ah->caldata) |
915 | ah->caldata->CalValid = 0; | ||
905 | 916 | ||
906 | return true; | 917 | return true; |
907 | } | 918 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 5a0650399136..4674ea8c9c99 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -68,6 +68,7 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah, | |||
68 | u8 rxchainmask, | 68 | u8 rxchainmask, |
69 | struct ath9k_cal_list *currCal) | 69 | struct ath9k_cal_list *currCal) |
70 | { | 70 | { |
71 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
71 | /* Cal is assumed not done until explicitly set below */ | 72 | /* Cal is assumed not done until explicitly set below */ |
72 | bool iscaldone = false; | 73 | bool iscaldone = false; |
73 | 74 | ||
@@ -95,7 +96,7 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah, | |||
95 | currCal->calData->calPostProc(ah, numChains); | 96 | currCal->calData->calPostProc(ah, numChains); |
96 | 97 | ||
97 | /* Calibration has finished. */ | 98 | /* Calibration has finished. */ |
98 | ichan->CalValid |= currCal->calData->calType; | 99 | caldata->CalValid |= currCal->calData->calType; |
99 | currCal->calState = CAL_DONE; | 100 | currCal->calState = CAL_DONE; |
100 | iscaldone = true; | 101 | iscaldone = true; |
101 | } else { | 102 | } else { |
@@ -106,7 +107,7 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah, | |||
106 | ar9003_hw_setup_calibration(ah, currCal); | 107 | ar9003_hw_setup_calibration(ah, currCal); |
107 | } | 108 | } |
108 | } | 109 | } |
109 | } else if (!(ichan->CalValid & currCal->calData->calType)) { | 110 | } else if (!(caldata->CalValid & currCal->calData->calType)) { |
110 | /* If current cal is marked invalid in channel, kick it off */ | 111 | /* If current cal is marked invalid in channel, kick it off */ |
111 | ath9k_hw_reset_calibration(ah, currCal); | 112 | ath9k_hw_reset_calibration(ah, currCal); |
112 | } | 113 | } |
@@ -149,6 +150,12 @@ static bool ar9003_hw_calibrate(struct ath_hw *ah, | |||
149 | /* Do NF cal only at longer intervals */ | 150 | /* Do NF cal only at longer intervals */ |
150 | if (longcal) { | 151 | if (longcal) { |
151 | /* | 152 | /* |
153 | * Get the value from the previous NF cal and update | ||
154 | * history buffer. | ||
155 | */ | ||
156 | ath9k_hw_getnf(ah, chan); | ||
157 | |||
158 | /* | ||
152 | * Load the NF from history buffer of the current channel. | 159 | * Load the NF from history buffer of the current channel. |
153 | * NF is slow time-variant, so it is OK to use a historical | 160 | * NF is slow time-variant, so it is OK to use a historical |
154 | * value. | 161 | * value. |
@@ -156,7 +163,7 @@ static bool ar9003_hw_calibrate(struct ath_hw *ah, | |||
156 | ath9k_hw_loadnf(ah, ah->curchan); | 163 | ath9k_hw_loadnf(ah, ah->curchan); |
157 | 164 | ||
158 | /* start NF calibration, without updating BB NF register */ | 165 | /* start NF calibration, without updating BB NF register */ |
159 | ath9k_hw_start_nfcal(ah); | 166 | ath9k_hw_start_nfcal(ah, false); |
160 | } | 167 | } |
161 | 168 | ||
162 | return iscaldone; | 169 | return iscaldone; |
@@ -762,6 +769,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
762 | /* Revert chainmasks to their original values before NF cal */ | 769 | /* Revert chainmasks to their original values before NF cal */ |
763 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); | 770 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); |
764 | 771 | ||
772 | ath9k_hw_start_nfcal(ah, true); | ||
773 | |||
765 | /* Initialize list pointers */ | 774 | /* Initialize list pointers */ |
766 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | 775 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
767 | 776 | ||
@@ -785,7 +794,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
785 | if (ah->cal_list_curr) | 794 | if (ah->cal_list_curr) |
786 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); | 795 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); |
787 | 796 | ||
788 | chan->CalValid = 0; | 797 | if (ah->caldata) |
798 | ah->caldata->CalValid = 0; | ||
789 | 799 | ||
790 | return true; | 800 | return true; |
791 | } | 801 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index ace8d2678b18..b883b174385b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -41,6 +41,20 @@ | |||
41 | #define LE16(x) __constant_cpu_to_le16(x) | 41 | #define LE16(x) __constant_cpu_to_le16(x) |
42 | #define LE32(x) __constant_cpu_to_le32(x) | 42 | #define LE32(x) __constant_cpu_to_le32(x) |
43 | 43 | ||
44 | /* Local defines to distinguish between extension and control CTL's */ | ||
45 | #define EXT_ADDITIVE (0x8000) | ||
46 | #define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) | ||
47 | #define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) | ||
48 | #define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) | ||
49 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ | ||
50 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */ | ||
51 | #define PWRINCR_3_TO_1_CHAIN 9 /* 10*log(3)*2 */ | ||
52 | #define PWRINCR_3_TO_2_CHAIN 3 /* floor(10*log(3/2)*2) */ | ||
53 | #define PWRINCR_2_TO_1_CHAIN 6 /* 10*log(2)*2 */ | ||
54 | |||
55 | #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */ | ||
56 | #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ | ||
57 | |||
44 | static const struct ar9300_eeprom ar9300_default = { | 58 | static const struct ar9300_eeprom ar9300_default = { |
45 | .eepromVersion = 2, | 59 | .eepromVersion = 2, |
46 | .templateVersion = 2, | 60 | .templateVersion = 2, |
@@ -609,6 +623,14 @@ static const struct ar9300_eeprom ar9300_default = { | |||
609 | } | 623 | } |
610 | }; | 624 | }; |
611 | 625 | ||
626 | static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) | ||
627 | { | ||
628 | if (fbin == AR9300_BCHAN_UNUSED) | ||
629 | return fbin; | ||
630 | |||
631 | return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); | ||
632 | } | ||
633 | |||
612 | static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah) | 634 | static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah) |
613 | { | 635 | { |
614 | return 0; | 636 | return 0; |
@@ -1417,9 +1439,9 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
1417 | #undef POW_SM | 1439 | #undef POW_SM |
1418 | } | 1440 | } |
1419 | 1441 | ||
1420 | static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq) | 1442 | static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq, |
1443 | u8 *targetPowerValT2) | ||
1421 | { | 1444 | { |
1422 | u8 targetPowerValT2[ar9300RateSize]; | ||
1423 | /* XXX: hard code for now, need to get from eeprom struct */ | 1445 | /* XXX: hard code for now, need to get from eeprom struct */ |
1424 | u8 ht40PowerIncForPdadc = 0; | 1446 | u8 ht40PowerIncForPdadc = 0; |
1425 | bool is2GHz = false; | 1447 | bool is2GHz = false; |
@@ -1553,9 +1575,6 @@ static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq) | |||
1553 | "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); | 1575 | "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); |
1554 | i++; | 1576 | i++; |
1555 | } | 1577 | } |
1556 | |||
1557 | /* Write target power array to registers */ | ||
1558 | ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); | ||
1559 | } | 1578 | } |
1560 | 1579 | ||
1561 | static int ar9003_hw_cal_pier_get(struct ath_hw *ah, | 1580 | static int ar9003_hw_cal_pier_get(struct ath_hw *ah, |
@@ -1799,14 +1818,369 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
1799 | return 0; | 1818 | return 0; |
1800 | } | 1819 | } |
1801 | 1820 | ||
1821 | static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep, | ||
1822 | int idx, | ||
1823 | int edge, | ||
1824 | bool is2GHz) | ||
1825 | { | ||
1826 | struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G; | ||
1827 | struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G; | ||
1828 | |||
1829 | if (is2GHz) | ||
1830 | return ctl_2g[idx].ctlEdges[edge].tPower; | ||
1831 | else | ||
1832 | return ctl_5g[idx].ctlEdges[edge].tPower; | ||
1833 | } | ||
1834 | |||
1835 | static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep, | ||
1836 | int idx, | ||
1837 | unsigned int edge, | ||
1838 | u16 freq, | ||
1839 | bool is2GHz) | ||
1840 | { | ||
1841 | struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G; | ||
1842 | struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G; | ||
1843 | |||
1844 | u8 *ctl_freqbin = is2GHz ? | ||
1845 | &eep->ctl_freqbin_2G[idx][0] : | ||
1846 | &eep->ctl_freqbin_5G[idx][0]; | ||
1847 | |||
1848 | if (is2GHz) { | ||
1849 | if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq && | ||
1850 | ctl_2g[idx].ctlEdges[edge - 1].flag) | ||
1851 | return ctl_2g[idx].ctlEdges[edge - 1].tPower; | ||
1852 | } else { | ||
1853 | if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq && | ||
1854 | ctl_5g[idx].ctlEdges[edge - 1].flag) | ||
1855 | return ctl_5g[idx].ctlEdges[edge - 1].tPower; | ||
1856 | } | ||
1857 | |||
1858 | return AR9300_MAX_RATE_POWER; | ||
1859 | } | ||
1860 | |||
1861 | /* | ||
1862 | * Find the maximum conformance test limit for the given channel and CTL info | ||
1863 | */ | ||
1864 | static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep, | ||
1865 | u16 freq, int idx, bool is2GHz) | ||
1866 | { | ||
1867 | u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER; | ||
1868 | u8 *ctl_freqbin = is2GHz ? | ||
1869 | &eep->ctl_freqbin_2G[idx][0] : | ||
1870 | &eep->ctl_freqbin_5G[idx][0]; | ||
1871 | u16 num_edges = is2GHz ? | ||
1872 | AR9300_NUM_BAND_EDGES_2G : AR9300_NUM_BAND_EDGES_5G; | ||
1873 | unsigned int edge; | ||
1874 | |||
1875 | /* Get the edge power */ | ||
1876 | for (edge = 0; | ||
1877 | (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED); | ||
1878 | edge++) { | ||
1879 | /* | ||
1880 | * If there's an exact channel match or an inband flag set | ||
1881 | * on the lower channel use the given rdEdgePower | ||
1882 | */ | ||
1883 | if (freq == ath9k_hw_fbin2freq(ctl_freqbin[edge], is2GHz)) { | ||
1884 | twiceMaxEdgePower = | ||
1885 | ar9003_hw_get_direct_edge_power(eep, idx, | ||
1886 | edge, is2GHz); | ||
1887 | break; | ||
1888 | } else if ((edge > 0) && | ||
1889 | (freq < ath9k_hw_fbin2freq(ctl_freqbin[edge], | ||
1890 | is2GHz))) { | ||
1891 | twiceMaxEdgePower = | ||
1892 | ar9003_hw_get_indirect_edge_power(eep, idx, | ||
1893 | edge, freq, | ||
1894 | is2GHz); | ||
1895 | /* | ||
1896 | * Leave loop - no more affecting edges possible in | ||
1897 | * this monotonic increasing list | ||
1898 | */ | ||
1899 | break; | ||
1900 | } | ||
1901 | } | ||
1902 | return twiceMaxEdgePower; | ||
1903 | } | ||
1904 | |||
1905 | static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, | ||
1906 | struct ath9k_channel *chan, | ||
1907 | u8 *pPwrArray, u16 cfgCtl, | ||
1908 | u8 twiceAntennaReduction, | ||
1909 | u8 twiceMaxRegulatoryPower, | ||
1910 | u16 powerLimit) | ||
1911 | { | ||
1912 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
1913 | struct ath_common *common = ath9k_hw_common(ah); | ||
1914 | struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep; | ||
1915 | u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER; | ||
1916 | static const u16 tpScaleReductionTable[5] = { | ||
1917 | 0, 3, 6, 9, AR9300_MAX_RATE_POWER | ||
1918 | }; | ||
1919 | int i; | ||
1920 | int16_t twiceLargestAntenna; | ||
1921 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | ||
1922 | u16 ctlModesFor11a[] = { | ||
1923 | CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 | ||
1924 | }; | ||
1925 | u16 ctlModesFor11g[] = { | ||
1926 | CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, | ||
1927 | CTL_11G_EXT, CTL_2GHT40 | ||
1928 | }; | ||
1929 | u16 numCtlModes, *pCtlMode, ctlMode, freq; | ||
1930 | struct chan_centers centers; | ||
1931 | u8 *ctlIndex; | ||
1932 | u8 ctlNum; | ||
1933 | u16 twiceMinEdgePower; | ||
1934 | bool is2ghz = IS_CHAN_2GHZ(chan); | ||
1935 | |||
1936 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
1937 | |||
1938 | /* Compute TxPower reduction due to Antenna Gain */ | ||
1939 | if (is2ghz) | ||
1940 | twiceLargestAntenna = pEepData->modalHeader2G.antennaGain; | ||
1941 | else | ||
1942 | twiceLargestAntenna = pEepData->modalHeader5G.antennaGain; | ||
1943 | |||
1944 | twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) - | ||
1945 | twiceLargestAntenna, 0); | ||
1946 | |||
1947 | /* | ||
1948 | * scaledPower is the minimum of the user input power level | ||
1949 | * and the regulatory allowed power level | ||
1950 | */ | ||
1951 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | ||
1952 | |||
1953 | if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) { | ||
1954 | maxRegAllowedPower -= | ||
1955 | (tpScaleReductionTable[(regulatory->tp_scale)] * 2); | ||
1956 | } | ||
1957 | |||
1958 | scaledPower = min(powerLimit, maxRegAllowedPower); | ||
1959 | |||
1960 | /* | ||
1961 | * Reduce scaled Power by number of chains active to get | ||
1962 | * to per chain tx power level | ||
1963 | */ | ||
1964 | switch (ar5416_get_ntxchains(ah->txchainmask)) { | ||
1965 | case 1: | ||
1966 | break; | ||
1967 | case 2: | ||
1968 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
1969 | break; | ||
1970 | case 3: | ||
1971 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
1972 | break; | ||
1973 | } | ||
1974 | |||
1975 | scaledPower = max((u16)0, scaledPower); | ||
1976 | |||
1977 | /* | ||
1978 | * Get target powers from EEPROM - our baseline for TX Power | ||
1979 | */ | ||
1980 | if (is2ghz) { | ||
1981 | /* Setup for CTL modes */ | ||
1982 | /* CTL_11B, CTL_11G, CTL_2GHT20 */ | ||
1983 | numCtlModes = | ||
1984 | ARRAY_SIZE(ctlModesFor11g) - | ||
1985 | SUB_NUM_CTL_MODES_AT_2G_40; | ||
1986 | pCtlMode = ctlModesFor11g; | ||
1987 | if (IS_CHAN_HT40(chan)) | ||
1988 | /* All 2G CTL's */ | ||
1989 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | ||
1990 | } else { | ||
1991 | /* Setup for CTL modes */ | ||
1992 | /* CTL_11A, CTL_5GHT20 */ | ||
1993 | numCtlModes = ARRAY_SIZE(ctlModesFor11a) - | ||
1994 | SUB_NUM_CTL_MODES_AT_5G_40; | ||
1995 | pCtlMode = ctlModesFor11a; | ||
1996 | if (IS_CHAN_HT40(chan)) | ||
1997 | /* All 5G CTL's */ | ||
1998 | numCtlModes = ARRAY_SIZE(ctlModesFor11a); | ||
1999 | } | ||
2000 | |||
2001 | /* | ||
2002 | * For MIMO, need to apply regulatory caps individually across | ||
2003 | * dynamically running modes: CCK, OFDM, HT20, HT40 | ||
2004 | * | ||
2005 | * The outer loop walks through each possible applicable runtime mode. | ||
2006 | * The inner loop walks through each ctlIndex entry in EEPROM. | ||
2007 | * The ctl value is encoded as [7:4] == test group, [3:0] == test mode. | ||
2008 | */ | ||
2009 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | ||
2010 | bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || | ||
2011 | (pCtlMode[ctlMode] == CTL_2GHT40); | ||
2012 | if (isHt40CtlMode) | ||
2013 | freq = centers.synth_center; | ||
2014 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | ||
2015 | freq = centers.ext_center; | ||
2016 | else | ||
2017 | freq = centers.ctl_center; | ||
2018 | |||
2019 | ath_print(common, ATH_DBG_REGULATORY, | ||
2020 | "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " | ||
2021 | "EXT_ADDITIVE %d\n", | ||
2022 | ctlMode, numCtlModes, isHt40CtlMode, | ||
2023 | (pCtlMode[ctlMode] & EXT_ADDITIVE)); | ||
2024 | |||
2025 | /* walk through each CTL index stored in EEPROM */ | ||
2026 | if (is2ghz) { | ||
2027 | ctlIndex = pEepData->ctlIndex_2G; | ||
2028 | ctlNum = AR9300_NUM_CTLS_2G; | ||
2029 | } else { | ||
2030 | ctlIndex = pEepData->ctlIndex_5G; | ||
2031 | ctlNum = AR9300_NUM_CTLS_5G; | ||
2032 | } | ||
2033 | |||
2034 | for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) { | ||
2035 | ath_print(common, ATH_DBG_REGULATORY, | ||
2036 | "LOOP-Ctlidx %d: cfgCtl 0x%2.2x " | ||
2037 | "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " | ||
2038 | "chan %dn", | ||
2039 | i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i], | ||
2040 | chan->channel); | ||
2041 | |||
2042 | /* | ||
2043 | * compare test group from regulatory | ||
2044 | * channel list with test mode from pCtlMode | ||
2045 | * list | ||
2046 | */ | ||
2047 | if ((((cfgCtl & ~CTL_MODE_M) | | ||
2048 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
2049 | ctlIndex[i]) || | ||
2050 | (((cfgCtl & ~CTL_MODE_M) | | ||
2051 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
2052 | ((ctlIndex[i] & CTL_MODE_M) | | ||
2053 | SD_NO_CTL))) { | ||
2054 | twiceMinEdgePower = | ||
2055 | ar9003_hw_get_max_edge_power(pEepData, | ||
2056 | freq, i, | ||
2057 | is2ghz); | ||
2058 | |||
2059 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) | ||
2060 | /* | ||
2061 | * Find the minimum of all CTL | ||
2062 | * edge powers that apply to | ||
2063 | * this channel | ||
2064 | */ | ||
2065 | twiceMaxEdgePower = | ||
2066 | min(twiceMaxEdgePower, | ||
2067 | twiceMinEdgePower); | ||
2068 | else { | ||
2069 | /* specific */ | ||
2070 | twiceMaxEdgePower = | ||
2071 | twiceMinEdgePower; | ||
2072 | break; | ||
2073 | } | ||
2074 | } | ||
2075 | } | ||
2076 | |||
2077 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); | ||
2078 | |||
2079 | ath_print(common, ATH_DBG_REGULATORY, | ||
2080 | "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d " | ||
2081 | "sP %d minCtlPwr %d\n", | ||
2082 | ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, | ||
2083 | scaledPower, minCtlPower); | ||
2084 | |||
2085 | /* Apply ctl mode to correct target power set */ | ||
2086 | switch (pCtlMode[ctlMode]) { | ||
2087 | case CTL_11B: | ||
2088 | for (i = ALL_TARGET_LEGACY_1L_5L; | ||
2089 | i <= ALL_TARGET_LEGACY_11S; i++) | ||
2090 | pPwrArray[i] = | ||
2091 | (u8)min((u16)pPwrArray[i], | ||
2092 | minCtlPower); | ||
2093 | break; | ||
2094 | case CTL_11A: | ||
2095 | case CTL_11G: | ||
2096 | for (i = ALL_TARGET_LEGACY_6_24; | ||
2097 | i <= ALL_TARGET_LEGACY_54; i++) | ||
2098 | pPwrArray[i] = | ||
2099 | (u8)min((u16)pPwrArray[i], | ||
2100 | minCtlPower); | ||
2101 | break; | ||
2102 | case CTL_5GHT20: | ||
2103 | case CTL_2GHT20: | ||
2104 | for (i = ALL_TARGET_HT20_0_8_16; | ||
2105 | i <= ALL_TARGET_HT20_21; i++) | ||
2106 | pPwrArray[i] = | ||
2107 | (u8)min((u16)pPwrArray[i], | ||
2108 | minCtlPower); | ||
2109 | pPwrArray[ALL_TARGET_HT20_22] = | ||
2110 | (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22], | ||
2111 | minCtlPower); | ||
2112 | pPwrArray[ALL_TARGET_HT20_23] = | ||
2113 | (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23], | ||
2114 | minCtlPower); | ||
2115 | break; | ||
2116 | case CTL_5GHT40: | ||
2117 | case CTL_2GHT40: | ||
2118 | for (i = ALL_TARGET_HT40_0_8_16; | ||
2119 | i <= ALL_TARGET_HT40_23; i++) | ||
2120 | pPwrArray[i] = | ||
2121 | (u8)min((u16)pPwrArray[i], | ||
2122 | minCtlPower); | ||
2123 | break; | ||
2124 | default: | ||
2125 | break; | ||
2126 | } | ||
2127 | } /* end ctl mode checking */ | ||
2128 | } | ||
2129 | |||
1802 | static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, | 2130 | static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, |
1803 | struct ath9k_channel *chan, u16 cfgCtl, | 2131 | struct ath9k_channel *chan, u16 cfgCtl, |
1804 | u8 twiceAntennaReduction, | 2132 | u8 twiceAntennaReduction, |
1805 | u8 twiceMaxRegulatoryPower, | 2133 | u8 twiceMaxRegulatoryPower, |
1806 | u8 powerLimit) | 2134 | u8 powerLimit) |
1807 | { | 2135 | { |
1808 | ah->txpower_limit = powerLimit; | 2136 | struct ath_common *common = ath9k_hw_common(ah); |
1809 | ar9003_hw_set_target_power_eeprom(ah, chan->channel); | 2137 | u8 targetPowerValT2[ar9300RateSize]; |
2138 | unsigned int i = 0; | ||
2139 | |||
2140 | ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2); | ||
2141 | ar9003_hw_set_power_per_rate_table(ah, chan, | ||
2142 | targetPowerValT2, cfgCtl, | ||
2143 | twiceAntennaReduction, | ||
2144 | twiceMaxRegulatoryPower, | ||
2145 | powerLimit); | ||
2146 | |||
2147 | while (i < ar9300RateSize) { | ||
2148 | ath_print(common, ATH_DBG_EEPROM, | ||
2149 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); | ||
2150 | i++; | ||
2151 | ath_print(common, ATH_DBG_EEPROM, | ||
2152 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); | ||
2153 | i++; | ||
2154 | ath_print(common, ATH_DBG_EEPROM, | ||
2155 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); | ||
2156 | i++; | ||
2157 | ath_print(common, ATH_DBG_EEPROM, | ||
2158 | "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]); | ||
2159 | i++; | ||
2160 | } | ||
2161 | |||
2162 | /* Write target power array to registers */ | ||
2163 | ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); | ||
2164 | |||
2165 | /* | ||
2166 | * This is the TX power we send back to driver core, | ||
2167 | * and it can use to pass to userspace to display our | ||
2168 | * currently configured TX power setting. | ||
2169 | * | ||
2170 | * Since power is rate dependent, use one of the indices | ||
2171 | * from the AR9300_Rates enum to select an entry from | ||
2172 | * targetPowerValT2[] to report. Currently returns the | ||
2173 | * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps | ||
2174 | * as CCK power is less interesting (?). | ||
2175 | */ | ||
2176 | i = ALL_TARGET_LEGACY_6_24; /* legacy */ | ||
2177 | if (IS_CHAN_HT40(chan)) | ||
2178 | i = ALL_TARGET_HT40_0_8_16; /* ht40 */ | ||
2179 | else if (IS_CHAN_HT20(chan)) | ||
2180 | i = ALL_TARGET_HT20_0_8_16; /* ht20 */ | ||
2181 | |||
2182 | ah->txpower_limit = targetPowerValT2[i]; | ||
2183 | |||
1810 | ar9003_hw_calibration_apply(ah, chan->channel); | 2184 | ar9003_hw_calibration_apply(ah, chan->channel); |
1811 | } | 2185 | } |
1812 | 2186 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 49e0c865ce5c..7c38229ba670 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c | |||
@@ -577,10 +577,11 @@ static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain) | |||
577 | } | 577 | } |
578 | 578 | ||
579 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, | 579 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, |
580 | struct ath9k_channel *chan, int chain) | 580 | struct ath9k_hw_cal_data *caldata, |
581 | int chain) | ||
581 | { | 582 | { |
582 | u32 *paprd_table_val = chan->pa_table[chain]; | 583 | u32 *paprd_table_val = caldata->pa_table[chain]; |
583 | u32 small_signal_gain = chan->small_signal_gain[chain]; | 584 | u32 small_signal_gain = caldata->small_signal_gain[chain]; |
584 | u32 training_power; | 585 | u32 training_power; |
585 | u32 reg = 0; | 586 | u32 reg = 0; |
586 | int i; | 587 | int i; |
@@ -654,17 +655,17 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) | |||
654 | } | 655 | } |
655 | EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); | 656 | EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); |
656 | 657 | ||
657 | int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, | 658 | int ar9003_paprd_create_curve(struct ath_hw *ah, |
658 | int chain) | 659 | struct ath9k_hw_cal_data *caldata, int chain) |
659 | { | 660 | { |
660 | u16 *small_signal_gain = &chan->small_signal_gain[chain]; | 661 | u16 *small_signal_gain = &caldata->small_signal_gain[chain]; |
661 | u32 *pa_table = chan->pa_table[chain]; | 662 | u32 *pa_table = caldata->pa_table[chain]; |
662 | u32 *data_L, *data_U; | 663 | u32 *data_L, *data_U; |
663 | int i, status = 0; | 664 | int i, status = 0; |
664 | u32 *buf; | 665 | u32 *buf; |
665 | u32 reg; | 666 | u32 reg; |
666 | 667 | ||
667 | memset(chan->pa_table[chain], 0, sizeof(chan->pa_table[chain])); | 668 | memset(caldata->pa_table[chain], 0, sizeof(caldata->pa_table[chain])); |
668 | 669 | ||
669 | buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC); | 670 | buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC); |
670 | if (!buf) | 671 | if (!buf) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index a753a431bb13..a491854fa38a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -542,7 +542,11 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah, | |||
542 | u32 reg = INI_RA(iniArr, i, 0); | 542 | u32 reg = INI_RA(iniArr, i, 0); |
543 | u32 val = INI_RA(iniArr, i, column); | 543 | u32 val = INI_RA(iniArr, i, column); |
544 | 544 | ||
545 | REG_WRITE(ah, reg, val); | 545 | if (reg >= 0x16000 && reg < 0x17000) |
546 | ath9k_hw_analog_shift_regwrite(ah, reg, val); | ||
547 | else | ||
548 | REG_WRITE(ah, reg, val); | ||
549 | |||
546 | DO_DELAY(regWrites); | 550 | DO_DELAY(regWrites); |
547 | } | 551 | } |
548 | } | 552 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 998ae2c49ed2..07f26ee7a723 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -510,7 +510,7 @@ void ath_deinit_leds(struct ath_softc *sc); | |||
510 | #define SC_OP_BEACONS BIT(1) | 510 | #define SC_OP_BEACONS BIT(1) |
511 | #define SC_OP_RXAGGR BIT(2) | 511 | #define SC_OP_RXAGGR BIT(2) |
512 | #define SC_OP_TXAGGR BIT(3) | 512 | #define SC_OP_TXAGGR BIT(3) |
513 | #define SC_OP_FULL_RESET BIT(4) | 513 | #define SC_OP_OFFCHANNEL BIT(4) |
514 | #define SC_OP_PREAMBLE_SHORT BIT(5) | 514 | #define SC_OP_PREAMBLE_SHORT BIT(5) |
515 | #define SC_OP_PROTECT_ENABLE BIT(6) | 515 | #define SC_OP_PROTECT_ENABLE BIT(6) |
516 | #define SC_OP_RXFLUSH BIT(7) | 516 | #define SC_OP_RXFLUSH BIT(7) |
@@ -609,6 +609,7 @@ struct ath_softc { | |||
609 | struct ath_wiphy { | 609 | struct ath_wiphy { |
610 | struct ath_softc *sc; /* shared for all virtual wiphys */ | 610 | struct ath_softc *sc; /* shared for all virtual wiphys */ |
611 | struct ieee80211_hw *hw; | 611 | struct ieee80211_hw *hw; |
612 | struct ath9k_hw_cal_data caldata; | ||
612 | enum ath_wiphy_state { | 613 | enum ath_wiphy_state { |
613 | ATH_WIPHY_INACTIVE, | 614 | ATH_WIPHY_INACTIVE, |
614 | ATH_WIPHY_ACTIVE, | 615 | ATH_WIPHY_ACTIVE, |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 139289e4e933..45208690c0ec 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -22,23 +22,6 @@ | |||
22 | /* We can tune this as we go by monitoring really low values */ | 22 | /* We can tune this as we go by monitoring really low values */ |
23 | #define ATH9K_NF_TOO_LOW -60 | 23 | #define ATH9K_NF_TOO_LOW -60 |
24 | 24 | ||
25 | /* AR5416 may return very high value (like -31 dBm), in those cases the nf | ||
26 | * is incorrect and we should use the static NF value. Later we can try to | ||
27 | * find out why they are reporting these values */ | ||
28 | |||
29 | static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf) | ||
30 | { | ||
31 | if (nf > ATH9K_NF_TOO_LOW) { | ||
32 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, | ||
33 | "noise floor value detected (%d) is " | ||
34 | "lower than what we think is a " | ||
35 | "reasonable value (%d)\n", | ||
36 | nf, ATH9K_NF_TOO_LOW); | ||
37 | return false; | ||
38 | } | ||
39 | return true; | ||
40 | } | ||
41 | |||
42 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) | 25 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) |
43 | { | 26 | { |
44 | int16_t nfval; | 27 | int16_t nfval; |
@@ -121,6 +104,19 @@ void ath9k_hw_reset_calibration(struct ath_hw *ah, | |||
121 | ah->cal_samples = 0; | 104 | ah->cal_samples = 0; |
122 | } | 105 | } |
123 | 106 | ||
107 | static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, | ||
108 | struct ath9k_channel *chan) | ||
109 | { | ||
110 | struct ath_nf_limits *limit; | ||
111 | |||
112 | if (!chan || IS_CHAN_2GHZ(chan)) | ||
113 | limit = &ah->nf_2g; | ||
114 | else | ||
115 | limit = &ah->nf_5g; | ||
116 | |||
117 | return limit->nominal; | ||
118 | } | ||
119 | |||
124 | /* This is done for the currently configured channel */ | 120 | /* This is done for the currently configured channel */ |
125 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | 121 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) |
126 | { | 122 | { |
@@ -128,7 +124,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | |||
128 | struct ieee80211_conf *conf = &common->hw->conf; | 124 | struct ieee80211_conf *conf = &common->hw->conf; |
129 | struct ath9k_cal_list *currCal = ah->cal_list_curr; | 125 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
130 | 126 | ||
131 | if (!ah->curchan) | 127 | if (!ah->caldata) |
132 | return true; | 128 | return true; |
133 | 129 | ||
134 | if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) | 130 | if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) |
@@ -151,37 +147,55 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | |||
151 | "Resetting Cal %d state for channel %u\n", | 147 | "Resetting Cal %d state for channel %u\n", |
152 | currCal->calData->calType, conf->channel->center_freq); | 148 | currCal->calData->calType, conf->channel->center_freq); |
153 | 149 | ||
154 | ah->curchan->CalValid &= ~currCal->calData->calType; | 150 | ah->caldata->CalValid &= ~currCal->calData->calType; |
155 | currCal->calState = CAL_WAITING; | 151 | currCal->calState = CAL_WAITING; |
156 | 152 | ||
157 | return false; | 153 | return false; |
158 | } | 154 | } |
159 | EXPORT_SYMBOL(ath9k_hw_reset_calvalid); | 155 | EXPORT_SYMBOL(ath9k_hw_reset_calvalid); |
160 | 156 | ||
161 | void ath9k_hw_start_nfcal(struct ath_hw *ah) | 157 | void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update) |
162 | { | 158 | { |
159 | if (ah->caldata) | ||
160 | ah->caldata->nfcal_pending = true; | ||
161 | |||
163 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | 162 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, |
164 | AR_PHY_AGC_CONTROL_ENABLE_NF); | 163 | AR_PHY_AGC_CONTROL_ENABLE_NF); |
165 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | 164 | |
165 | if (update) | ||
166 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
167 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | ||
168 | else | ||
169 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | ||
166 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | 170 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); |
171 | |||
167 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | 172 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); |
168 | } | 173 | } |
169 | 174 | ||
170 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | 175 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) |
171 | { | 176 | { |
172 | struct ath9k_nfcal_hist *h; | 177 | struct ath9k_nfcal_hist *h = NULL; |
173 | unsigned i, j; | 178 | unsigned i, j; |
174 | int32_t val; | 179 | int32_t val; |
175 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; | 180 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; |
176 | struct ath_common *common = ath9k_hw_common(ah); | 181 | struct ath_common *common = ath9k_hw_common(ah); |
182 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); | ||
177 | 183 | ||
178 | h = ah->nfCalHist; | 184 | if (ah->caldata) |
185 | h = ah->caldata->nfCalHist; | ||
179 | 186 | ||
180 | for (i = 0; i < NUM_NF_READINGS; i++) { | 187 | for (i = 0; i < NUM_NF_READINGS; i++) { |
181 | if (chainmask & (1 << i)) { | 188 | if (chainmask & (1 << i)) { |
189 | s16 nfval; | ||
190 | |||
191 | if (h) | ||
192 | nfval = h[i].privNF; | ||
193 | else | ||
194 | nfval = default_nf; | ||
195 | |||
182 | val = REG_READ(ah, ah->nf_regs[i]); | 196 | val = REG_READ(ah, ah->nf_regs[i]); |
183 | val &= 0xFFFFFE00; | 197 | val &= 0xFFFFFE00; |
184 | val |= (((u32) (h[i].privNF) << 1) & 0x1ff); | 198 | val |= (((u32) nfval << 1) & 0x1ff); |
185 | REG_WRITE(ah, ah->nf_regs[i], val); | 199 | REG_WRITE(ah, ah->nf_regs[i], val); |
186 | } | 200 | } |
187 | } | 201 | } |
@@ -277,22 +291,25 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) | |||
277 | } | 291 | } |
278 | } | 292 | } |
279 | 293 | ||
280 | int16_t ath9k_hw_getnf(struct ath_hw *ah, | 294 | bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) |
281 | struct ath9k_channel *chan) | ||
282 | { | 295 | { |
283 | struct ath_common *common = ath9k_hw_common(ah); | 296 | struct ath_common *common = ath9k_hw_common(ah); |
284 | int16_t nf, nfThresh; | 297 | int16_t nf, nfThresh; |
285 | int16_t nfarray[NUM_NF_READINGS] = { 0 }; | 298 | int16_t nfarray[NUM_NF_READINGS] = { 0 }; |
286 | struct ath9k_nfcal_hist *h; | 299 | struct ath9k_nfcal_hist *h; |
287 | struct ieee80211_channel *c = chan->chan; | 300 | struct ieee80211_channel *c = chan->chan; |
301 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
302 | |||
303 | if (!caldata) | ||
304 | return false; | ||
288 | 305 | ||
289 | chan->channelFlags &= (~CHANNEL_CW_INT); | 306 | chan->channelFlags &= (~CHANNEL_CW_INT); |
290 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { | 307 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { |
291 | ath_print(common, ATH_DBG_CALIBRATE, | 308 | ath_print(common, ATH_DBG_CALIBRATE, |
292 | "NF did not complete in calibration window\n"); | 309 | "NF did not complete in calibration window\n"); |
293 | nf = 0; | 310 | nf = 0; |
294 | chan->rawNoiseFloor = nf; | 311 | caldata->rawNoiseFloor = nf; |
295 | return chan->rawNoiseFloor; | 312 | return false; |
296 | } else { | 313 | } else { |
297 | ath9k_hw_do_getnf(ah, nfarray); | 314 | ath9k_hw_do_getnf(ah, nfarray); |
298 | ath9k_hw_nf_sanitize(ah, nfarray); | 315 | ath9k_hw_nf_sanitize(ah, nfarray); |
@@ -307,47 +324,40 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah, | |||
307 | } | 324 | } |
308 | } | 325 | } |
309 | 326 | ||
310 | h = ah->nfCalHist; | 327 | h = caldata->nfCalHist; |
311 | 328 | caldata->nfcal_pending = false; | |
312 | ath9k_hw_update_nfcal_hist_buffer(h, nfarray); | 329 | ath9k_hw_update_nfcal_hist_buffer(h, nfarray); |
313 | chan->rawNoiseFloor = h[0].privNF; | 330 | caldata->rawNoiseFloor = h[0].privNF; |
314 | 331 | return true; | |
315 | return chan->rawNoiseFloor; | ||
316 | } | 332 | } |
317 | 333 | ||
318 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) | 334 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, |
335 | struct ath9k_channel *chan) | ||
319 | { | 336 | { |
320 | struct ath_nf_limits *limit; | 337 | struct ath9k_nfcal_hist *h; |
338 | s16 default_nf; | ||
321 | int i, j; | 339 | int i, j; |
322 | 340 | ||
323 | if (!ah->curchan || IS_CHAN_2GHZ(ah->curchan)) | 341 | if (!ah->caldata) |
324 | limit = &ah->nf_2g; | 342 | return; |
325 | else | ||
326 | limit = &ah->nf_5g; | ||
327 | 343 | ||
344 | h = ah->caldata->nfCalHist; | ||
345 | default_nf = ath9k_hw_get_default_nf(ah, chan); | ||
328 | for (i = 0; i < NUM_NF_READINGS; i++) { | 346 | for (i = 0; i < NUM_NF_READINGS; i++) { |
329 | ah->nfCalHist[i].currIndex = 0; | 347 | h[i].currIndex = 0; |
330 | ah->nfCalHist[i].privNF = limit->nominal; | 348 | h[i].privNF = default_nf; |
331 | ah->nfCalHist[i].invalidNFcount = | 349 | h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH; |
332 | AR_PHY_CCA_FILTERWINDOW_LENGTH; | ||
333 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { | 350 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { |
334 | ah->nfCalHist[i].nfCalBuffer[j] = limit->nominal; | 351 | h[i].nfCalBuffer[j] = default_nf; |
335 | } | 352 | } |
336 | } | 353 | } |
337 | } | 354 | } |
338 | 355 | ||
339 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | 356 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) |
340 | { | 357 | { |
341 | s16 nf; | 358 | if (!ah->caldata || !ah->caldata->rawNoiseFloor) |
342 | 359 | return ath9k_hw_get_default_nf(ah, chan); | |
343 | if (chan->rawNoiseFloor == 0) | ||
344 | nf = -96; | ||
345 | else | ||
346 | nf = chan->rawNoiseFloor; | ||
347 | |||
348 | if (!ath9k_hw_nf_in_range(ah, nf)) | ||
349 | nf = ATH_DEFAULT_NOISE_FLOOR; | ||
350 | 360 | ||
351 | return nf; | 361 | return ah->caldata->rawNoiseFloor; |
352 | } | 362 | } |
353 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); | 363 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); |
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index cd60d09cdda7..0a304b3eeeb6 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
@@ -108,11 +108,11 @@ struct ath9k_pacal_info{ | |||
108 | }; | 108 | }; |
109 | 109 | ||
110 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah); | 110 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah); |
111 | void ath9k_hw_start_nfcal(struct ath_hw *ah); | 111 | void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update); |
112 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); | 112 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); |
113 | int16_t ath9k_hw_getnf(struct ath_hw *ah, | 113 | bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); |
114 | struct ath9k_channel *chan); | 114 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, |
115 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); | 115 | struct ath9k_channel *chan); |
116 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); | 116 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); |
117 | void ath9k_hw_reset_calibration(struct ath_hw *ah, | 117 | void ath9k_hw_reset_calibration(struct ath_hw *ah, |
118 | struct ath9k_cal_list *currCal); | 118 | struct ath9k_cal_list *currCal); |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 3756400e6bf9..43b9e21bc562 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -353,6 +353,8 @@ struct ath9k_htc_priv { | |||
353 | u16 seq_no; | 353 | u16 seq_no; |
354 | u32 bmiss_cnt; | 354 | u32 bmiss_cnt; |
355 | 355 | ||
356 | struct ath9k_hw_cal_data caldata[38]; | ||
357 | |||
356 | spinlock_t beacon_lock; | 358 | spinlock_t beacon_lock; |
357 | 359 | ||
358 | bool tx_queues_stop; | 360 | bool tx_queues_stop; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index cf9bcc67ade2..ebed9d1691a5 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -125,6 +125,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
125 | struct ieee80211_conf *conf = &common->hw->conf; | 125 | struct ieee80211_conf *conf = &common->hw->conf; |
126 | bool fastcc = true; | 126 | bool fastcc = true; |
127 | struct ieee80211_channel *channel = hw->conf.channel; | 127 | struct ieee80211_channel *channel = hw->conf.channel; |
128 | struct ath9k_hw_cal_data *caldata; | ||
128 | enum htc_phymode mode; | 129 | enum htc_phymode mode; |
129 | __be16 htc_mode; | 130 | __be16 htc_mode; |
130 | u8 cmd_rsp; | 131 | u8 cmd_rsp; |
@@ -149,7 +150,8 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
149 | priv->ah->curchan->channel, | 150 | priv->ah->curchan->channel, |
150 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf)); | 151 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf)); |
151 | 152 | ||
152 | ret = ath9k_hw_reset(ah, hchan, fastcc); | 153 | caldata = &priv->caldata[channel->hw_value]; |
154 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); | ||
153 | if (ret) { | 155 | if (ret) { |
154 | ath_print(common, ATH_DBG_FATAL, | 156 | ath_print(common, ATH_DBG_FATAL, |
155 | "Unable to reset channel (%u Mhz) " | 157 | "Unable to reset channel (%u Mhz) " |
@@ -1028,7 +1030,7 @@ static void ath9k_htc_radio_enable(struct ieee80211_hw *hw) | |||
1028 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | 1030 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); |
1029 | 1031 | ||
1030 | /* Reset the HW */ | 1032 | /* Reset the HW */ |
1031 | ret = ath9k_hw_reset(ah, ah->curchan, false); | 1033 | ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
1032 | if (ret) { | 1034 | if (ret) { |
1033 | ath_print(common, ATH_DBG_FATAL, | 1035 | ath_print(common, ATH_DBG_FATAL, |
1034 | "Unable to reset hardware; reset status %d " | 1036 | "Unable to reset hardware; reset status %d " |
@@ -1091,7 +1093,7 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw) | |||
1091 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | 1093 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); |
1092 | 1094 | ||
1093 | /* Reset the HW */ | 1095 | /* Reset the HW */ |
1094 | ret = ath9k_hw_reset(ah, ah->curchan, false); | 1096 | ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
1095 | if (ret) { | 1097 | if (ret) { |
1096 | ath_print(common, ATH_DBG_FATAL, | 1098 | ath_print(common, ATH_DBG_FATAL, |
1097 | "Unable to reset hardware; reset status %d " | 1099 | "Unable to reset hardware; reset status %d " |
@@ -1179,7 +1181,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1179 | ath9k_hw_configpcipowersave(ah, 0, 0); | 1181 | ath9k_hw_configpcipowersave(ah, 0, 0); |
1180 | 1182 | ||
1181 | ath9k_hw_htc_resetinit(ah); | 1183 | ath9k_hw_htc_resetinit(ah); |
1182 | ret = ath9k_hw_reset(ah, init_channel, false); | 1184 | ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); |
1183 | if (ret) { | 1185 | if (ret) { |
1184 | ath_print(common, ATH_DBG_FATAL, | 1186 | ath_print(common, ATH_DBG_FATAL, |
1185 | "Unable to reset hardware; reset status %d " | 1187 | "Unable to reset hardware; reset status %d " |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8d291ccf5c88..3384ca164562 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -610,7 +610,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
610 | else | 610 | else |
611 | ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); | 611 | ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); |
612 | 612 | ||
613 | ath9k_init_nfcal_hist_buffer(ah); | ||
614 | ah->bb_watchdog_timeout_ms = 25; | 613 | ah->bb_watchdog_timeout_ms = 25; |
615 | 614 | ||
616 | common->state = ATH_HW_INITIALIZED; | 615 | common->state = ATH_HW_INITIALIZED; |
@@ -1183,9 +1182,6 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1183 | 1182 | ||
1184 | ath9k_hw_spur_mitigate_freq(ah, chan); | 1183 | ath9k_hw_spur_mitigate_freq(ah, chan); |
1185 | 1184 | ||
1186 | if (!chan->oneTimeCalsDone) | ||
1187 | chan->oneTimeCalsDone = true; | ||
1188 | |||
1189 | return true; | 1185 | return true; |
1190 | } | 1186 | } |
1191 | 1187 | ||
@@ -1218,7 +1214,7 @@ bool ath9k_hw_check_alive(struct ath_hw *ah) | |||
1218 | EXPORT_SYMBOL(ath9k_hw_check_alive); | 1214 | EXPORT_SYMBOL(ath9k_hw_check_alive); |
1219 | 1215 | ||
1220 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 1216 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
1221 | bool bChannelChange) | 1217 | struct ath9k_hw_cal_data *caldata, bool bChannelChange) |
1222 | { | 1218 | { |
1223 | struct ath_common *common = ath9k_hw_common(ah); | 1219 | struct ath_common *common = ath9k_hw_common(ah); |
1224 | u32 saveLedState; | 1220 | u32 saveLedState; |
@@ -1243,9 +1239,19 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1243 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | 1239 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) |
1244 | return -EIO; | 1240 | return -EIO; |
1245 | 1241 | ||
1246 | if (curchan && !ah->chip_fullsleep) | 1242 | if (curchan && !ah->chip_fullsleep && ah->caldata) |
1247 | ath9k_hw_getnf(ah, curchan); | 1243 | ath9k_hw_getnf(ah, curchan); |
1248 | 1244 | ||
1245 | ah->caldata = caldata; | ||
1246 | if (caldata && | ||
1247 | (chan->channel != caldata->channel || | ||
1248 | (chan->channelFlags & ~CHANNEL_CW_INT) != | ||
1249 | (caldata->channelFlags & ~CHANNEL_CW_INT))) { | ||
1250 | /* Operating channel changed, reset channel calibration data */ | ||
1251 | memset(caldata, 0, sizeof(*caldata)); | ||
1252 | ath9k_init_nfcal_hist_buffer(ah, chan); | ||
1253 | } | ||
1254 | |||
1249 | if (bChannelChange && | 1255 | if (bChannelChange && |
1250 | (ah->chip_fullsleep != true) && | 1256 | (ah->chip_fullsleep != true) && |
1251 | (ah->curchan != NULL) && | 1257 | (ah->curchan != NULL) && |
@@ -1256,7 +1262,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1256 | 1262 | ||
1257 | if (ath9k_hw_channel_change(ah, chan)) { | 1263 | if (ath9k_hw_channel_change(ah, chan)) { |
1258 | ath9k_hw_loadnf(ah, ah->curchan); | 1264 | ath9k_hw_loadnf(ah, ah->curchan); |
1259 | ath9k_hw_start_nfcal(ah); | 1265 | ath9k_hw_start_nfcal(ah, true); |
1260 | return 0; | 1266 | return 0; |
1261 | } | 1267 | } |
1262 | } | 1268 | } |
@@ -1461,11 +1467,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1461 | if (ah->btcoex_hw.enabled) | 1467 | if (ah->btcoex_hw.enabled) |
1462 | ath9k_hw_btcoex_enable(ah); | 1468 | ath9k_hw_btcoex_enable(ah); |
1463 | 1469 | ||
1464 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 1470 | if (AR_SREV_9300_20_OR_LATER(ah)) |
1465 | ath9k_hw_loadnf(ah, curchan); | ||
1466 | ath9k_hw_start_nfcal(ah); | ||
1467 | ar9003_hw_bb_watchdog_config(ah); | 1471 | ar9003_hw_bb_watchdog_config(ah); |
1468 | } | ||
1469 | 1472 | ||
1470 | return 0; | 1473 | return 0; |
1471 | } | 1474 | } |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 2d30efc0b94f..399f7c1283cd 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -346,19 +346,25 @@ enum ath9k_int { | |||
346 | CHANNEL_HT40PLUS | \ | 346 | CHANNEL_HT40PLUS | \ |
347 | CHANNEL_HT40MINUS) | 347 | CHANNEL_HT40MINUS) |
348 | 348 | ||
349 | struct ath9k_channel { | 349 | struct ath9k_hw_cal_data { |
350 | struct ieee80211_channel *chan; | ||
351 | u16 channel; | 350 | u16 channel; |
352 | u32 channelFlags; | 351 | u32 channelFlags; |
353 | u32 chanmode; | ||
354 | int32_t CalValid; | 352 | int32_t CalValid; |
355 | bool oneTimeCalsDone; | ||
356 | int8_t iCoff; | 353 | int8_t iCoff; |
357 | int8_t qCoff; | 354 | int8_t qCoff; |
358 | int16_t rawNoiseFloor; | 355 | int16_t rawNoiseFloor; |
359 | bool paprd_done; | 356 | bool paprd_done; |
357 | bool nfcal_pending; | ||
360 | u16 small_signal_gain[AR9300_MAX_CHAINS]; | 358 | u16 small_signal_gain[AR9300_MAX_CHAINS]; |
361 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; | 359 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; |
360 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | ||
361 | }; | ||
362 | |||
363 | struct ath9k_channel { | ||
364 | struct ieee80211_channel *chan; | ||
365 | u16 channel; | ||
366 | u32 channelFlags; | ||
367 | u32 chanmode; | ||
362 | }; | 368 | }; |
363 | 369 | ||
364 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ | 370 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ |
@@ -669,7 +675,7 @@ struct ath_hw { | |||
669 | enum nl80211_iftype opmode; | 675 | enum nl80211_iftype opmode; |
670 | enum ath9k_power_mode power_mode; | 676 | enum ath9k_power_mode power_mode; |
671 | 677 | ||
672 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | 678 | struct ath9k_hw_cal_data *caldata; |
673 | struct ath9k_pacal_info pacal_info; | 679 | struct ath9k_pacal_info pacal_info; |
674 | struct ar5416Stats stats; | 680 | struct ar5416Stats stats; |
675 | struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; | 681 | struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; |
@@ -863,7 +869,7 @@ const char *ath9k_hw_probe(u16 vendorid, u16 devid); | |||
863 | void ath9k_hw_deinit(struct ath_hw *ah); | 869 | void ath9k_hw_deinit(struct ath_hw *ah); |
864 | int ath9k_hw_init(struct ath_hw *ah); | 870 | int ath9k_hw_init(struct ath_hw *ah); |
865 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 871 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
866 | bool bChannelChange); | 872 | struct ath9k_hw_cal_data *caldata, bool bChannelChange); |
867 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); | 873 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); |
868 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); | 874 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); |
869 | 875 | ||
@@ -958,9 +964,10 @@ void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); | |||
958 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); | 964 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); |
959 | void ar9003_paprd_enable(struct ath_hw *ah, bool val); | 965 | void ar9003_paprd_enable(struct ath_hw *ah, bool val); |
960 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, | 966 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, |
961 | struct ath9k_channel *chan, int chain); | 967 | struct ath9k_hw_cal_data *caldata, |
962 | int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, | 968 | int chain); |
963 | int chain); | 969 | int ar9003_paprd_create_curve(struct ath_hw *ah, |
970 | struct ath9k_hw_cal_data *caldata, int chain); | ||
964 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); | 971 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); |
965 | int ar9003_paprd_init_table(struct ath_hw *ah); | 972 | int ar9003_paprd_init_table(struct ath_hw *ah); |
966 | bool ar9003_paprd_is_done(struct ath_hw *ah); | 973 | bool ar9003_paprd_is_done(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 0429dda0961f..3caa32316e7b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -154,6 +154,27 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
154 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 154 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
155 | } | 155 | } |
156 | 156 | ||
157 | static void ath_start_ani(struct ath_common *common) | ||
158 | { | ||
159 | struct ath_hw *ah = common->ah; | ||
160 | unsigned long timestamp = jiffies_to_msecs(jiffies); | ||
161 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
162 | |||
163 | if (!(sc->sc_flags & SC_OP_ANI_RUN)) | ||
164 | return; | ||
165 | |||
166 | if (sc->sc_flags & SC_OP_OFFCHANNEL) | ||
167 | return; | ||
168 | |||
169 | common->ani.longcal_timer = timestamp; | ||
170 | common->ani.shortcal_timer = timestamp; | ||
171 | common->ani.checkani_timer = timestamp; | ||
172 | |||
173 | mod_timer(&common->ani.timer, | ||
174 | jiffies + | ||
175 | msecs_to_jiffies((u32)ah->config.ani_poll_interval)); | ||
176 | } | ||
177 | |||
157 | /* | 178 | /* |
158 | * Set/change channels. If the channel is really being changed, it's done | 179 | * Set/change channels. If the channel is really being changed, it's done |
159 | * by reseting the chip. To accomplish this we must first cleanup any pending | 180 | * by reseting the chip. To accomplish this we must first cleanup any pending |
@@ -162,16 +183,23 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
162 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | 183 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, |
163 | struct ath9k_channel *hchan) | 184 | struct ath9k_channel *hchan) |
164 | { | 185 | { |
186 | struct ath_wiphy *aphy = hw->priv; | ||
165 | struct ath_hw *ah = sc->sc_ah; | 187 | struct ath_hw *ah = sc->sc_ah; |
166 | struct ath_common *common = ath9k_hw_common(ah); | 188 | struct ath_common *common = ath9k_hw_common(ah); |
167 | struct ieee80211_conf *conf = &common->hw->conf; | 189 | struct ieee80211_conf *conf = &common->hw->conf; |
168 | bool fastcc = true, stopped; | 190 | bool fastcc = true, stopped; |
169 | struct ieee80211_channel *channel = hw->conf.channel; | 191 | struct ieee80211_channel *channel = hw->conf.channel; |
192 | struct ath9k_hw_cal_data *caldata = NULL; | ||
170 | int r; | 193 | int r; |
171 | 194 | ||
172 | if (sc->sc_flags & SC_OP_INVALID) | 195 | if (sc->sc_flags & SC_OP_INVALID) |
173 | return -EIO; | 196 | return -EIO; |
174 | 197 | ||
198 | del_timer_sync(&common->ani.timer); | ||
199 | cancel_work_sync(&sc->paprd_work); | ||
200 | cancel_work_sync(&sc->hw_check_work); | ||
201 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
202 | |||
175 | ath9k_ps_wakeup(sc); | 203 | ath9k_ps_wakeup(sc); |
176 | 204 | ||
177 | /* | 205 | /* |
@@ -191,9 +219,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
191 | * to flush data frames already in queue because of | 219 | * to flush data frames already in queue because of |
192 | * changing channel. */ | 220 | * changing channel. */ |
193 | 221 | ||
194 | if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) | 222 | if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL)) |
195 | fastcc = false; | 223 | fastcc = false; |
196 | 224 | ||
225 | if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) | ||
226 | caldata = &aphy->caldata; | ||
227 | |||
197 | ath_print(common, ATH_DBG_CONFIG, | 228 | ath_print(common, ATH_DBG_CONFIG, |
198 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n", | 229 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n", |
199 | sc->sc_ah->curchan->channel, | 230 | sc->sc_ah->curchan->channel, |
@@ -201,7 +232,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
201 | 232 | ||
202 | spin_lock_bh(&sc->sc_resetlock); | 233 | spin_lock_bh(&sc->sc_resetlock); |
203 | 234 | ||
204 | r = ath9k_hw_reset(ah, hchan, fastcc); | 235 | r = ath9k_hw_reset(ah, hchan, caldata, fastcc); |
205 | if (r) { | 236 | if (r) { |
206 | ath_print(common, ATH_DBG_FATAL, | 237 | ath_print(common, ATH_DBG_FATAL, |
207 | "Unable to reset channel (%u MHz), " | 238 | "Unable to reset channel (%u MHz), " |
@@ -212,8 +243,6 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
212 | } | 243 | } |
213 | spin_unlock_bh(&sc->sc_resetlock); | 244 | spin_unlock_bh(&sc->sc_resetlock); |
214 | 245 | ||
215 | sc->sc_flags &= ~SC_OP_FULL_RESET; | ||
216 | |||
217 | if (ath_startrecv(sc) != 0) { | 246 | if (ath_startrecv(sc) != 0) { |
218 | ath_print(common, ATH_DBG_FATAL, | 247 | ath_print(common, ATH_DBG_FATAL, |
219 | "Unable to restart recv logic\n"); | 248 | "Unable to restart recv logic\n"); |
@@ -225,6 +254,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
225 | ath_update_txpow(sc); | 254 | ath_update_txpow(sc); |
226 | ath9k_hw_set_interrupts(ah, ah->imask); | 255 | ath9k_hw_set_interrupts(ah, ah->imask); |
227 | 256 | ||
257 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) { | ||
258 | ath_start_ani(common); | ||
259 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | ||
260 | ath_beacon_config(sc, NULL); | ||
261 | } | ||
262 | |||
228 | ps_restore: | 263 | ps_restore: |
229 | ath9k_ps_restore(sc); | 264 | ath9k_ps_restore(sc); |
230 | return r; | 265 | return r; |
@@ -233,17 +268,19 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
233 | static void ath_paprd_activate(struct ath_softc *sc) | 268 | static void ath_paprd_activate(struct ath_softc *sc) |
234 | { | 269 | { |
235 | struct ath_hw *ah = sc->sc_ah; | 270 | struct ath_hw *ah = sc->sc_ah; |
271 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
236 | int chain; | 272 | int chain; |
237 | 273 | ||
238 | if (!ah->curchan->paprd_done) | 274 | if (!caldata || !caldata->paprd_done) |
239 | return; | 275 | return; |
240 | 276 | ||
241 | ath9k_ps_wakeup(sc); | 277 | ath9k_ps_wakeup(sc); |
278 | ar9003_paprd_enable(ah, false); | ||
242 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | 279 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
243 | if (!(ah->caps.tx_chainmask & BIT(chain))) | 280 | if (!(ah->caps.tx_chainmask & BIT(chain))) |
244 | continue; | 281 | continue; |
245 | 282 | ||
246 | ar9003_paprd_populate_single_table(ah, ah->curchan, chain); | 283 | ar9003_paprd_populate_single_table(ah, caldata, chain); |
247 | } | 284 | } |
248 | 285 | ||
249 | ar9003_paprd_enable(ah, true); | 286 | ar9003_paprd_enable(ah, true); |
@@ -261,6 +298,7 @@ void ath_paprd_calibrate(struct work_struct *work) | |||
261 | int band = hw->conf.channel->band; | 298 | int band = hw->conf.channel->band; |
262 | struct ieee80211_supported_band *sband = &sc->sbands[band]; | 299 | struct ieee80211_supported_band *sband = &sc->sbands[band]; |
263 | struct ath_tx_control txctl; | 300 | struct ath_tx_control txctl; |
301 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
264 | int qnum, ftype; | 302 | int qnum, ftype; |
265 | int chain_ok = 0; | 303 | int chain_ok = 0; |
266 | int chain; | 304 | int chain; |
@@ -268,6 +306,9 @@ void ath_paprd_calibrate(struct work_struct *work) | |||
268 | int time_left; | 306 | int time_left; |
269 | int i; | 307 | int i; |
270 | 308 | ||
309 | if (!caldata) | ||
310 | return; | ||
311 | |||
271 | skb = alloc_skb(len, GFP_KERNEL); | 312 | skb = alloc_skb(len, GFP_KERNEL); |
272 | if (!skb) | 313 | if (!skb) |
273 | return; | 314 | return; |
@@ -322,7 +363,7 @@ void ath_paprd_calibrate(struct work_struct *work) | |||
322 | if (!ar9003_paprd_is_done(ah)) | 363 | if (!ar9003_paprd_is_done(ah)) |
323 | break; | 364 | break; |
324 | 365 | ||
325 | if (ar9003_paprd_create_curve(ah, ah->curchan, chain) != 0) | 366 | if (ar9003_paprd_create_curve(ah, caldata, chain) != 0) |
326 | break; | 367 | break; |
327 | 368 | ||
328 | chain_ok = 1; | 369 | chain_ok = 1; |
@@ -330,7 +371,7 @@ void ath_paprd_calibrate(struct work_struct *work) | |||
330 | kfree_skb(skb); | 371 | kfree_skb(skb); |
331 | 372 | ||
332 | if (chain_ok) { | 373 | if (chain_ok) { |
333 | ah->curchan->paprd_done = true; | 374 | caldata->paprd_done = true; |
334 | ath_paprd_activate(sc); | 375 | ath_paprd_activate(sc); |
335 | } | 376 | } |
336 | 377 | ||
@@ -439,33 +480,14 @@ set_timer: | |||
439 | cal_interval = min(cal_interval, (u32)short_cal_interval); | 480 | cal_interval = min(cal_interval, (u32)short_cal_interval); |
440 | 481 | ||
441 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); | 482 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); |
442 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && | 483 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { |
443 | !(sc->sc_flags & SC_OP_SCANNING)) { | 484 | if (!ah->caldata->paprd_done) |
444 | if (!sc->sc_ah->curchan->paprd_done) | ||
445 | ieee80211_queue_work(sc->hw, &sc->paprd_work); | 485 | ieee80211_queue_work(sc->hw, &sc->paprd_work); |
446 | else | 486 | else |
447 | ath_paprd_activate(sc); | 487 | ath_paprd_activate(sc); |
448 | } | 488 | } |
449 | } | 489 | } |
450 | 490 | ||
451 | static void ath_start_ani(struct ath_common *common) | ||
452 | { | ||
453 | struct ath_hw *ah = common->ah; | ||
454 | unsigned long timestamp = jiffies_to_msecs(jiffies); | ||
455 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
456 | |||
457 | if (!(sc->sc_flags & SC_OP_ANI_RUN)) | ||
458 | return; | ||
459 | |||
460 | common->ani.longcal_timer = timestamp; | ||
461 | common->ani.shortcal_timer = timestamp; | ||
462 | common->ani.checkani_timer = timestamp; | ||
463 | |||
464 | mod_timer(&common->ani.timer, | ||
465 | jiffies + | ||
466 | msecs_to_jiffies((u32)ah->config.ani_poll_interval)); | ||
467 | } | ||
468 | |||
469 | /* | 491 | /* |
470 | * Update tx/rx chainmask. For legacy association, | 492 | * Update tx/rx chainmask. For legacy association, |
471 | * hard code chainmask to 1x1, for 11n association, use | 493 | * hard code chainmask to 1x1, for 11n association, use |
@@ -477,7 +499,7 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht) | |||
477 | struct ath_hw *ah = sc->sc_ah; | 499 | struct ath_hw *ah = sc->sc_ah; |
478 | struct ath_common *common = ath9k_hw_common(ah); | 500 | struct ath_common *common = ath9k_hw_common(ah); |
479 | 501 | ||
480 | if ((sc->sc_flags & SC_OP_SCANNING) || is_ht || | 502 | if ((sc->sc_flags & SC_OP_OFFCHANNEL) || is_ht || |
481 | (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) { | 503 | (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) { |
482 | common->tx_chainmask = ah->caps.tx_chainmask; | 504 | common->tx_chainmask = ah->caps.tx_chainmask; |
483 | common->rx_chainmask = ah->caps.rx_chainmask; | 505 | common->rx_chainmask = ah->caps.rx_chainmask; |
@@ -817,7 +839,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
817 | ah->curchan = ath_get_curchannel(sc, sc->hw); | 839 | ah->curchan = ath_get_curchannel(sc, sc->hw); |
818 | 840 | ||
819 | spin_lock_bh(&sc->sc_resetlock); | 841 | spin_lock_bh(&sc->sc_resetlock); |
820 | r = ath9k_hw_reset(ah, ah->curchan, false); | 842 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
821 | if (r) { | 843 | if (r) { |
822 | ath_print(common, ATH_DBG_FATAL, | 844 | ath_print(common, ATH_DBG_FATAL, |
823 | "Unable to reset channel (%u MHz), " | 845 | "Unable to reset channel (%u MHz), " |
@@ -877,7 +899,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
877 | ah->curchan = ath_get_curchannel(sc, hw); | 899 | ah->curchan = ath_get_curchannel(sc, hw); |
878 | 900 | ||
879 | spin_lock_bh(&sc->sc_resetlock); | 901 | spin_lock_bh(&sc->sc_resetlock); |
880 | r = ath9k_hw_reset(ah, ah->curchan, false); | 902 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
881 | if (r) { | 903 | if (r) { |
882 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | 904 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
883 | "Unable to reset channel (%u MHz), " | 905 | "Unable to reset channel (%u MHz), " |
@@ -910,7 +932,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
910 | ath_flushrecv(sc); | 932 | ath_flushrecv(sc); |
911 | 933 | ||
912 | spin_lock_bh(&sc->sc_resetlock); | 934 | spin_lock_bh(&sc->sc_resetlock); |
913 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); | 935 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); |
914 | if (r) | 936 | if (r) |
915 | ath_print(common, ATH_DBG_FATAL, | 937 | ath_print(common, ATH_DBG_FATAL, |
916 | "Unable to reset hardware; reset status %d\n", r); | 938 | "Unable to reset hardware; reset status %d\n", r); |
@@ -1085,7 +1107,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1085 | * and then setup of the interrupt mask. | 1107 | * and then setup of the interrupt mask. |
1086 | */ | 1108 | */ |
1087 | spin_lock_bh(&sc->sc_resetlock); | 1109 | spin_lock_bh(&sc->sc_resetlock); |
1088 | r = ath9k_hw_reset(ah, init_channel, false); | 1110 | r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); |
1089 | if (r) { | 1111 | if (r) { |
1090 | ath_print(common, ATH_DBG_FATAL, | 1112 | ath_print(common, ATH_DBG_FATAL, |
1091 | "Unable to reset hardware; reset status %d " | 1113 | "Unable to reset hardware; reset status %d " |
@@ -1579,6 +1601,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1579 | 1601 | ||
1580 | aphy->chan_idx = pos; | 1602 | aphy->chan_idx = pos; |
1581 | aphy->chan_is_ht = conf_is_ht(conf); | 1603 | aphy->chan_is_ht = conf_is_ht(conf); |
1604 | if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) | ||
1605 | sc->sc_flags |= SC_OP_OFFCHANNEL; | ||
1606 | else | ||
1607 | sc->sc_flags &= ~SC_OP_OFFCHANNEL; | ||
1582 | 1608 | ||
1583 | if (aphy->state == ATH_WIPHY_SCAN || | 1609 | if (aphy->state == ATH_WIPHY_SCAN || |
1584 | aphy->state == ATH_WIPHY_ACTIVE) | 1610 | aphy->state == ATH_WIPHY_ACTIVE) |
@@ -1990,7 +2016,6 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
1990 | { | 2016 | { |
1991 | struct ath_wiphy *aphy = hw->priv; | 2017 | struct ath_wiphy *aphy = hw->priv; |
1992 | struct ath_softc *sc = aphy->sc; | 2018 | struct ath_softc *sc = aphy->sc; |
1993 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1994 | 2019 | ||
1995 | mutex_lock(&sc->mutex); | 2020 | mutex_lock(&sc->mutex); |
1996 | if (ath9k_wiphy_scanning(sc)) { | 2021 | if (ath9k_wiphy_scanning(sc)) { |
@@ -2008,10 +2033,6 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
2008 | aphy->state = ATH_WIPHY_SCAN; | 2033 | aphy->state = ATH_WIPHY_SCAN; |
2009 | ath9k_wiphy_pause_all_forced(sc, aphy); | 2034 | ath9k_wiphy_pause_all_forced(sc, aphy); |
2010 | sc->sc_flags |= SC_OP_SCANNING; | 2035 | sc->sc_flags |= SC_OP_SCANNING; |
2011 | del_timer_sync(&common->ani.timer); | ||
2012 | cancel_work_sync(&sc->paprd_work); | ||
2013 | cancel_work_sync(&sc->hw_check_work); | ||
2014 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
2015 | mutex_unlock(&sc->mutex); | 2036 | mutex_unlock(&sc->mutex); |
2016 | } | 2037 | } |
2017 | 2038 | ||
@@ -2023,15 +2044,10 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | |||
2023 | { | 2044 | { |
2024 | struct ath_wiphy *aphy = hw->priv; | 2045 | struct ath_wiphy *aphy = hw->priv; |
2025 | struct ath_softc *sc = aphy->sc; | 2046 | struct ath_softc *sc = aphy->sc; |
2026 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2027 | 2047 | ||
2028 | mutex_lock(&sc->mutex); | 2048 | mutex_lock(&sc->mutex); |
2029 | aphy->state = ATH_WIPHY_ACTIVE; | 2049 | aphy->state = ATH_WIPHY_ACTIVE; |
2030 | sc->sc_flags &= ~SC_OP_SCANNING; | 2050 | sc->sc_flags &= ~SC_OP_SCANNING; |
2031 | sc->sc_flags |= SC_OP_FULL_RESET; | ||
2032 | ath_start_ani(common); | ||
2033 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | ||
2034 | ath_beacon_config(sc, NULL); | ||
2035 | mutex_unlock(&sc->mutex); | 2051 | mutex_unlock(&sc->mutex); |
2036 | } | 2052 | } |
2037 | 2053 | ||
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index da0cfe90c38a..a3fc987ebab0 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -1140,6 +1140,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1140 | if (flush) | 1140 | if (flush) |
1141 | goto requeue; | 1141 | goto requeue; |
1142 | 1142 | ||
1143 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | ||
1144 | rxs, &decrypt_error); | ||
1145 | if (retval) | ||
1146 | goto requeue; | ||
1147 | |||
1143 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; | 1148 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; |
1144 | if (rs.rs_tstamp > tsf_lower && | 1149 | if (rs.rs_tstamp > tsf_lower && |
1145 | unlikely(rs.rs_tstamp - tsf_lower > 0x10000000)) | 1150 | unlikely(rs.rs_tstamp - tsf_lower > 0x10000000)) |
@@ -1149,11 +1154,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1149 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) | 1154 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) |
1150 | rxs->mactime += 0x100000000ULL; | 1155 | rxs->mactime += 0x100000000ULL; |
1151 | 1156 | ||
1152 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | ||
1153 | rxs, &decrypt_error); | ||
1154 | if (retval) | ||
1155 | goto requeue; | ||
1156 | |||
1157 | /* Ensure we always have an skb to requeue once we are done | 1157 | /* Ensure we always have an skb to requeue once we are done |
1158 | * processing the current buffer's skb */ | 1158 | * processing the current buffer's skb */ |
1159 | requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC); | 1159 | requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC); |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 501b72821b4d..4dda14e36227 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -120,26 +120,14 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) | |||
120 | list_add_tail(&ac->list, &txq->axq_acq); | 120 | list_add_tail(&ac->list, &txq->axq_acq); |
121 | } | 121 | } |
122 | 122 | ||
123 | static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | ||
124 | { | ||
125 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; | ||
126 | |||
127 | spin_lock_bh(&txq->axq_lock); | ||
128 | tid->paused++; | ||
129 | spin_unlock_bh(&txq->axq_lock); | ||
130 | } | ||
131 | |||
132 | static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | 123 | static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) |
133 | { | 124 | { |
134 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; | 125 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; |
135 | 126 | ||
136 | BUG_ON(tid->paused <= 0); | 127 | WARN_ON(!tid->paused); |
137 | spin_lock_bh(&txq->axq_lock); | ||
138 | |||
139 | tid->paused--; | ||
140 | 128 | ||
141 | if (tid->paused > 0) | 129 | spin_lock_bh(&txq->axq_lock); |
142 | goto unlock; | 130 | tid->paused = false; |
143 | 131 | ||
144 | if (list_empty(&tid->buf_q)) | 132 | if (list_empty(&tid->buf_q)) |
145 | goto unlock; | 133 | goto unlock; |
@@ -157,15 +145,10 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
157 | struct list_head bf_head; | 145 | struct list_head bf_head; |
158 | INIT_LIST_HEAD(&bf_head); | 146 | INIT_LIST_HEAD(&bf_head); |
159 | 147 | ||
160 | BUG_ON(tid->paused <= 0); | 148 | WARN_ON(!tid->paused); |
161 | spin_lock_bh(&txq->axq_lock); | ||
162 | 149 | ||
163 | tid->paused--; | 150 | spin_lock_bh(&txq->axq_lock); |
164 | 151 | tid->paused = false; | |
165 | if (tid->paused > 0) { | ||
166 | spin_unlock_bh(&txq->axq_lock); | ||
167 | return; | ||
168 | } | ||
169 | 152 | ||
170 | while (!list_empty(&tid->buf_q)) { | 153 | while (!list_empty(&tid->buf_q)) { |
171 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | 154 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); |
@@ -811,7 +794,7 @@ void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
811 | an = (struct ath_node *)sta->drv_priv; | 794 | an = (struct ath_node *)sta->drv_priv; |
812 | txtid = ATH_AN_2_TID(an, tid); | 795 | txtid = ATH_AN_2_TID(an, tid); |
813 | txtid->state |= AGGR_ADDBA_PROGRESS; | 796 | txtid->state |= AGGR_ADDBA_PROGRESS; |
814 | ath_tx_pause_tid(sc, txtid); | 797 | txtid->paused = true; |
815 | *ssn = txtid->seq_start; | 798 | *ssn = txtid->seq_start; |
816 | } | 799 | } |
817 | 800 | ||
@@ -835,10 +818,9 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
835 | return; | 818 | return; |
836 | } | 819 | } |
837 | 820 | ||
838 | ath_tx_pause_tid(sc, txtid); | ||
839 | |||
840 | /* drop all software retried frames and mark this TID */ | 821 | /* drop all software retried frames and mark this TID */ |
841 | spin_lock_bh(&txq->axq_lock); | 822 | spin_lock_bh(&txq->axq_lock); |
823 | txtid->paused = true; | ||
842 | while (!list_empty(&txtid->buf_q)) { | 824 | while (!list_empty(&txtid->buf_q)) { |
843 | bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); | 825 | bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); |
844 | if (!bf_isretried(bf)) { | 826 | if (!bf_isretried(bf)) { |
@@ -1181,7 +1163,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) | |||
1181 | "Failed to stop TX DMA. Resetting hardware!\n"); | 1163 | "Failed to stop TX DMA. Resetting hardware!\n"); |
1182 | 1164 | ||
1183 | spin_lock_bh(&sc->sc_resetlock); | 1165 | spin_lock_bh(&sc->sc_resetlock); |
1184 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); | 1166 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); |
1185 | if (r) | 1167 | if (r) |
1186 | ath_print(common, ATH_DBG_FATAL, | 1168 | ath_print(common, ATH_DBG_FATAL, |
1187 | "Unable to reset hardware; reset status %d\n", | 1169 | "Unable to reset hardware; reset status %d\n", |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index c24c5efeae1f..16bbfa3189a5 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -1924,6 +1924,10 @@ static int ipw2100_net_init(struct net_device *dev) | |||
1924 | bg_band->channels = | 1924 | bg_band->channels = |
1925 | kzalloc(geo->bg_channels * | 1925 | kzalloc(geo->bg_channels * |
1926 | sizeof(struct ieee80211_channel), GFP_KERNEL); | 1926 | sizeof(struct ieee80211_channel), GFP_KERNEL); |
1927 | if (!bg_band->channels) { | ||
1928 | ipw2100_down(priv); | ||
1929 | return -ENOMEM; | ||
1930 | } | ||
1927 | /* translate geo->bg to bg_band.channels */ | 1931 | /* translate geo->bg to bg_band.channels */ |
1928 | for (i = 0; i < geo->bg_channels; i++) { | 1932 | for (i = 0; i < geo->bg_channels; i++) { |
1929 | bg_band->channels[i].band = IEEE80211_BAND_2GHZ; | 1933 | bg_band->channels[i].band = IEEE80211_BAND_2GHZ; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index f052c6d09b37..d706b8afbe5a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | |||
@@ -980,7 +980,7 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file, | |||
980 | le32_to_cpu(bt->lo_priority_tx_req_cnt), | 980 | le32_to_cpu(bt->lo_priority_tx_req_cnt), |
981 | accum_bt->lo_priority_tx_req_cnt); | 981 | accum_bt->lo_priority_tx_req_cnt); |
982 | pos += scnprintf(buf + pos, bufsz - pos, | 982 | pos += scnprintf(buf + pos, bufsz - pos, |
983 | "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n", | 983 | "lo_priority_tx_denied_cnt:\t%u\t\t\t%u\n", |
984 | le32_to_cpu(bt->lo_priority_tx_denied_cnt), | 984 | le32_to_cpu(bt->lo_priority_tx_denied_cnt), |
985 | accum_bt->lo_priority_tx_denied_cnt); | 985 | accum_bt->lo_priority_tx_denied_cnt); |
986 | pos += scnprintf(buf + pos, bufsz - pos, | 986 | pos += scnprintf(buf + pos, bufsz - pos, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index a1b6d202d57c..9dd9e64c2b0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -1429,7 +1429,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, | |||
1429 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | 1429 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, |
1430 | int sta_id, int tid, int freed) | 1430 | int sta_id, int tid, int freed) |
1431 | { | 1431 | { |
1432 | WARN_ON(!spin_is_locked(&priv->sta_lock)); | 1432 | lockdep_assert_held(&priv->sta_lock); |
1433 | 1433 | ||
1434 | if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) | 1434 | if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) |
1435 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | 1435 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 35c86d22b14b..23e5c42e7d7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -300,8 +300,9 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | |||
300 | struct ieee80211_sta *sta) | 300 | struct ieee80211_sta *sta) |
301 | { | 301 | { |
302 | int ret = -EAGAIN; | 302 | int ret = -EAGAIN; |
303 | u32 load = rs_tl_get_load(lq_data, tid); | ||
303 | 304 | ||
304 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { | 305 | if (load > IWL_AGG_LOAD_THRESHOLD) { |
305 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", | 306 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", |
306 | sta->addr, tid); | 307 | sta->addr, tid); |
307 | ret = ieee80211_start_tx_ba_session(sta, tid); | 308 | ret = ieee80211_start_tx_ba_session(sta, tid); |
@@ -311,12 +312,14 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | |||
311 | * this might be cause by reloading firmware | 312 | * this might be cause by reloading firmware |
312 | * stop the tx ba session here | 313 | * stop the tx ba session here |
313 | */ | 314 | */ |
314 | IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", | 315 | IWL_ERR(priv, "Fail start Tx agg on tid: %d\n", |
315 | tid); | 316 | tid); |
316 | ieee80211_stop_tx_ba_session(sta, tid); | 317 | ieee80211_stop_tx_ba_session(sta, tid); |
317 | } | 318 | } |
318 | } else | 319 | } else { |
319 | IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid); | 320 | IWL_ERR(priv, "Aggregation not enabled for tid %d " |
321 | "because load = %u\n", tid, load); | ||
322 | } | ||
320 | return ret; | 323 | return ret; |
321 | } | 324 | } |
322 | 325 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 55a1b31fd09a..d04502d54df3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -1117,7 +1117,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
1117 | u8 *addr = priv->stations[sta_id].sta.sta.addr; | 1117 | u8 *addr = priv->stations[sta_id].sta.sta.addr; |
1118 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; | 1118 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; |
1119 | 1119 | ||
1120 | WARN_ON(!spin_is_locked(&priv->sta_lock)); | 1120 | lockdep_assert_held(&priv->sta_lock); |
1121 | 1121 | ||
1122 | switch (priv->stations[sta_id].tid[tid].agg.state) { | 1122 | switch (priv->stations[sta_id].tid[tid].agg.state) { |
1123 | case IWL_EMPTYING_HW_QUEUE_DELBA: | 1123 | case IWL_EMPTYING_HW_QUEUE_DELBA: |
@@ -1331,7 +1331,14 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1331 | tid = ba_resp->tid; | 1331 | tid = ba_resp->tid; |
1332 | agg = &priv->stations[sta_id].tid[tid].agg; | 1332 | agg = &priv->stations[sta_id].tid[tid].agg; |
1333 | if (unlikely(agg->txq_id != scd_flow)) { | 1333 | if (unlikely(agg->txq_id != scd_flow)) { |
1334 | IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n", | 1334 | /* |
1335 | * FIXME: this is a uCode bug which need to be addressed, | ||
1336 | * log the information and return for now! | ||
1337 | * since it is possible happen very often and in order | ||
1338 | * not to fill the syslog, don't enable the logging by default | ||
1339 | */ | ||
1340 | IWL_DEBUG_TX_REPLY(priv, | ||
1341 | "BA scd_flow %d does not match txq_id %d\n", | ||
1335 | scd_flow, agg->txq_id); | 1342 | scd_flow, agg->txq_id); |
1336 | return; | 1343 | return; |
1337 | } | 1344 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8024d44ce4bb..8ccb6d205b6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -2000,6 +2000,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2000 | struct ieee80211_vif *vif) | 2000 | struct ieee80211_vif *vif) |
2001 | { | 2001 | { |
2002 | struct iwl_priv *priv = hw->priv; | 2002 | struct iwl_priv *priv = hw->priv; |
2003 | bool scan_completed = false; | ||
2003 | 2004 | ||
2004 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 2005 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
2005 | 2006 | ||
@@ -2013,7 +2014,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2013 | if (priv->vif == vif) { | 2014 | if (priv->vif == vif) { |
2014 | priv->vif = NULL; | 2015 | priv->vif = NULL; |
2015 | if (priv->scan_vif == vif) { | 2016 | if (priv->scan_vif == vif) { |
2016 | ieee80211_scan_completed(priv->hw, true); | 2017 | scan_completed = true; |
2017 | priv->scan_vif = NULL; | 2018 | priv->scan_vif = NULL; |
2018 | priv->scan_request = NULL; | 2019 | priv->scan_request = NULL; |
2019 | } | 2020 | } |
@@ -2021,6 +2022,9 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2021 | } | 2022 | } |
2022 | mutex_unlock(&priv->mutex); | 2023 | mutex_unlock(&priv->mutex); |
2023 | 2024 | ||
2025 | if (scan_completed) | ||
2026 | ieee80211_scan_completed(priv->hw, true); | ||
2027 | |||
2024 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2028 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2025 | 2029 | ||
2026 | } | 2030 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 5c2bcef5df0c..0b961a353ff6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -71,7 +71,7 @@ do { \ | |||
71 | #define IWL_DEBUG(__priv, level, fmt, args...) | 71 | #define IWL_DEBUG(__priv, level, fmt, args...) |
72 | #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) | 72 | #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) |
73 | static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, | 73 | static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, |
74 | void *p, u32 len) | 74 | const void *p, u32 len) |
75 | {} | 75 | {} |
76 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 76 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
77 | 77 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index ae7319bb3a99..4cf864c664ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -193,7 +193,7 @@ TRACE_EVENT(iwlwifi_dev_tx, | |||
193 | __entry->framelen = buf0_len + buf1_len; | 193 | __entry->framelen = buf0_len + buf1_len; |
194 | memcpy(__get_dynamic_array(tfd), tfd, tfdlen); | 194 | memcpy(__get_dynamic_array(tfd), tfd, tfdlen); |
195 | memcpy(__get_dynamic_array(buf0), buf0, buf0_len); | 195 | memcpy(__get_dynamic_array(buf0), buf0, buf0_len); |
196 | memcpy(__get_dynamic_array(buf1), buf1, buf0_len); | 196 | memcpy(__get_dynamic_array(buf1), buf1, buf1_len); |
197 | ), | 197 | ), |
198 | TP_printk("[%p] TX %.2x (%zu bytes)", | 198 | TP_printk("[%p] TX %.2x (%zu bytes)", |
199 | __entry->priv, | 199 | __entry->priv, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index b0c6b0473901..a4b3663a262f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -298,7 +298,7 @@ EXPORT_SYMBOL(iwl_init_scan_params); | |||
298 | 298 | ||
299 | static int iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif) | 299 | static int iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif) |
300 | { | 300 | { |
301 | WARN_ON(!mutex_is_locked(&priv->mutex)); | 301 | lockdep_assert_held(&priv->mutex); |
302 | 302 | ||
303 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); | 303 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); |
304 | set_bit(STATUS_SCANNING, &priv->status); | 304 | set_bit(STATUS_SCANNING, &priv->status); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 9511f03f07e0..7e0829be5e78 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -773,7 +773,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | |||
773 | 773 | ||
774 | int iwl_restore_default_wep_keys(struct iwl_priv *priv) | 774 | int iwl_restore_default_wep_keys(struct iwl_priv *priv) |
775 | { | 775 | { |
776 | WARN_ON(!mutex_is_locked(&priv->mutex)); | 776 | lockdep_assert_held(&priv->mutex); |
777 | 777 | ||
778 | return iwl_send_static_wepkey_cmd(priv, 0); | 778 | return iwl_send_static_wepkey_cmd(priv, 0); |
779 | } | 779 | } |
@@ -784,7 +784,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, | |||
784 | { | 784 | { |
785 | int ret; | 785 | int ret; |
786 | 786 | ||
787 | WARN_ON(!mutex_is_locked(&priv->mutex)); | 787 | lockdep_assert_held(&priv->mutex); |
788 | 788 | ||
789 | IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", | 789 | IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", |
790 | keyconf->keyidx); | 790 | keyconf->keyidx); |
@@ -808,7 +808,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, | |||
808 | { | 808 | { |
809 | int ret; | 809 | int ret; |
810 | 810 | ||
811 | WARN_ON(!mutex_is_locked(&priv->mutex)); | 811 | lockdep_assert_held(&priv->mutex); |
812 | 812 | ||
813 | if (keyconf->keylen != WEP_KEY_LEN_128 && | 813 | if (keyconf->keylen != WEP_KEY_LEN_128 && |
814 | keyconf->keylen != WEP_KEY_LEN_64) { | 814 | keyconf->keylen != WEP_KEY_LEN_64) { |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 25f902760980..8e9fbfd804b6 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -257,6 +257,29 @@ static int lbs_add_supported_rates_tlv(u8 *tlv) | |||
257 | return sizeof(rate_tlv->header) + i; | 257 | return sizeof(rate_tlv->header) + i; |
258 | } | 258 | } |
259 | 259 | ||
260 | /* Add common rates from a TLV and return the new end of the TLV */ | ||
261 | static u8 * | ||
262 | add_ie_rates(u8 *tlv, const u8 *ie, int *nrates) | ||
263 | { | ||
264 | int hw, ap, ap_max = ie[1]; | ||
265 | u8 hw_rate; | ||
266 | |||
267 | /* Advance past IE header */ | ||
268 | ie += 2; | ||
269 | |||
270 | lbs_deb_hex(LBS_DEB_ASSOC, "AP IE Rates", (u8 *) ie, ap_max); | ||
271 | |||
272 | for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) { | ||
273 | hw_rate = lbs_rates[hw].bitrate / 5; | ||
274 | for (ap = 0; ap < ap_max; ap++) { | ||
275 | if (hw_rate == (ie[ap] & 0x7f)) { | ||
276 | *tlv++ = ie[ap]; | ||
277 | *nrates = *nrates + 1; | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | return tlv; | ||
282 | } | ||
260 | 283 | ||
261 | /* | 284 | /* |
262 | * Adds a TLV with all rates the hardware *and* BSS supports. | 285 | * Adds a TLV with all rates the hardware *and* BSS supports. |
@@ -264,8 +287,11 @@ static int lbs_add_supported_rates_tlv(u8 *tlv) | |||
264 | static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss) | 287 | static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss) |
265 | { | 288 | { |
266 | struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv; | 289 | struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv; |
267 | const u8 *rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES); | 290 | const u8 *rates_eid, *ext_rates_eid; |
268 | int n; | 291 | int n = 0; |
292 | |||
293 | rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES); | ||
294 | ext_rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES); | ||
269 | 295 | ||
270 | /* | 296 | /* |
271 | * 01 00 TLV_TYPE_RATES | 297 | * 01 00 TLV_TYPE_RATES |
@@ -275,26 +301,21 @@ static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss) | |||
275 | rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); | 301 | rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); |
276 | tlv += sizeof(rate_tlv->header); | 302 | tlv += sizeof(rate_tlv->header); |
277 | 303 | ||
278 | if (!rates_eid) { | 304 | /* Add basic rates */ |
305 | if (rates_eid) { | ||
306 | tlv = add_ie_rates(tlv, rates_eid, &n); | ||
307 | |||
308 | /* Add extended rates, if any */ | ||
309 | if (ext_rates_eid) | ||
310 | tlv = add_ie_rates(tlv, ext_rates_eid, &n); | ||
311 | } else { | ||
312 | lbs_deb_assoc("assoc: bss had no basic rate IE\n"); | ||
279 | /* Fallback: add basic 802.11b rates */ | 313 | /* Fallback: add basic 802.11b rates */ |
280 | *tlv++ = 0x82; | 314 | *tlv++ = 0x82; |
281 | *tlv++ = 0x84; | 315 | *tlv++ = 0x84; |
282 | *tlv++ = 0x8b; | 316 | *tlv++ = 0x8b; |
283 | *tlv++ = 0x96; | 317 | *tlv++ = 0x96; |
284 | n = 4; | 318 | n = 4; |
285 | } else { | ||
286 | int hw, ap; | ||
287 | u8 ap_max = rates_eid[1]; | ||
288 | n = 0; | ||
289 | for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) { | ||
290 | u8 hw_rate = lbs_rates[hw].bitrate / 5; | ||
291 | for (ap = 0; ap < ap_max; ap++) { | ||
292 | if (hw_rate == (rates_eid[ap+2] & 0x7f)) { | ||
293 | *tlv++ = rates_eid[ap+2]; | ||
294 | n++; | ||
295 | } | ||
296 | } | ||
297 | } | ||
298 | } | 319 | } |
299 | 320 | ||
300 | rate_tlv->header.len = cpu_to_le16(n); | 321 | rate_tlv->header.len = cpu_to_le16(n); |
@@ -465,7 +486,15 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
465 | lbs_deb_enter(LBS_DEB_CFG80211); | 486 | lbs_deb_enter(LBS_DEB_CFG80211); |
466 | 487 | ||
467 | bsssize = get_unaligned_le16(&scanresp->bssdescriptsize); | 488 | bsssize = get_unaligned_le16(&scanresp->bssdescriptsize); |
468 | nr_sets = le16_to_cpu(resp->size); | 489 | nr_sets = le16_to_cpu(scanresp->nr_sets); |
490 | |||
491 | lbs_deb_scan("scan response: %d BSSs (%d bytes); resp size %d bytes\n", | ||
492 | nr_sets, bsssize, le16_to_cpu(resp->size)); | ||
493 | |||
494 | if (nr_sets == 0) { | ||
495 | ret = 0; | ||
496 | goto done; | ||
497 | } | ||
469 | 498 | ||
470 | /* | 499 | /* |
471 | * The general layout of the scan response is described in chapter | 500 | * The general layout of the scan response is described in chapter |
@@ -670,8 +699,13 @@ static void lbs_scan_worker(struct work_struct *work) | |||
670 | 699 | ||
671 | if (priv->scan_channel >= priv->scan_req->n_channels) { | 700 | if (priv->scan_channel >= priv->scan_req->n_channels) { |
672 | /* Mark scan done */ | 701 | /* Mark scan done */ |
673 | cfg80211_scan_done(priv->scan_req, false); | 702 | if (priv->internal_scan) |
703 | kfree(priv->scan_req); | ||
704 | else | ||
705 | cfg80211_scan_done(priv->scan_req, false); | ||
706 | |||
674 | priv->scan_req = NULL; | 707 | priv->scan_req = NULL; |
708 | priv->last_scan = jiffies; | ||
675 | } | 709 | } |
676 | 710 | ||
677 | /* Restart network */ | 711 | /* Restart network */ |
@@ -682,10 +716,33 @@ static void lbs_scan_worker(struct work_struct *work) | |||
682 | 716 | ||
683 | kfree(scan_cmd); | 717 | kfree(scan_cmd); |
684 | 718 | ||
719 | /* Wake up anything waiting on scan completion */ | ||
720 | if (priv->scan_req == NULL) { | ||
721 | lbs_deb_scan("scan: waking up waiters\n"); | ||
722 | wake_up_all(&priv->scan_q); | ||
723 | } | ||
724 | |||
685 | out_no_scan_cmd: | 725 | out_no_scan_cmd: |
686 | lbs_deb_leave(LBS_DEB_SCAN); | 726 | lbs_deb_leave(LBS_DEB_SCAN); |
687 | } | 727 | } |
688 | 728 | ||
729 | static void _internal_start_scan(struct lbs_private *priv, bool internal, | ||
730 | struct cfg80211_scan_request *request) | ||
731 | { | ||
732 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
733 | |||
734 | lbs_deb_scan("scan: ssids %d, channels %d, ie_len %zd\n", | ||
735 | request->n_ssids, request->n_channels, request->ie_len); | ||
736 | |||
737 | priv->scan_channel = 0; | ||
738 | queue_delayed_work(priv->work_thread, &priv->scan_work, | ||
739 | msecs_to_jiffies(50)); | ||
740 | |||
741 | priv->scan_req = request; | ||
742 | priv->internal_scan = internal; | ||
743 | |||
744 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
745 | } | ||
689 | 746 | ||
690 | static int lbs_cfg_scan(struct wiphy *wiphy, | 747 | static int lbs_cfg_scan(struct wiphy *wiphy, |
691 | struct net_device *dev, | 748 | struct net_device *dev, |
@@ -702,18 +759,11 @@ static int lbs_cfg_scan(struct wiphy *wiphy, | |||
702 | goto out; | 759 | goto out; |
703 | } | 760 | } |
704 | 761 | ||
705 | lbs_deb_scan("scan: ssids %d, channels %d, ie_len %zd\n", | 762 | _internal_start_scan(priv, false, request); |
706 | request->n_ssids, request->n_channels, request->ie_len); | ||
707 | |||
708 | priv->scan_channel = 0; | ||
709 | queue_delayed_work(priv->work_thread, &priv->scan_work, | ||
710 | msecs_to_jiffies(50)); | ||
711 | 763 | ||
712 | if (priv->surpriseremoved) | 764 | if (priv->surpriseremoved) |
713 | ret = -EIO; | 765 | ret = -EIO; |
714 | 766 | ||
715 | priv->scan_req = request; | ||
716 | |||
717 | out: | 767 | out: |
718 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | 768 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); |
719 | return ret; | 769 | return ret; |
@@ -1000,6 +1050,7 @@ static int lbs_associate(struct lbs_private *priv, | |||
1000 | int status; | 1050 | int status; |
1001 | int ret; | 1051 | int ret; |
1002 | u8 *pos = &(cmd->iebuf[0]); | 1052 | u8 *pos = &(cmd->iebuf[0]); |
1053 | u8 *tmp; | ||
1003 | 1054 | ||
1004 | lbs_deb_enter(LBS_DEB_CFG80211); | 1055 | lbs_deb_enter(LBS_DEB_CFG80211); |
1005 | 1056 | ||
@@ -1044,7 +1095,9 @@ static int lbs_associate(struct lbs_private *priv, | |||
1044 | pos += lbs_add_cf_param_tlv(pos); | 1095 | pos += lbs_add_cf_param_tlv(pos); |
1045 | 1096 | ||
1046 | /* add rates TLV */ | 1097 | /* add rates TLV */ |
1098 | tmp = pos + 4; /* skip Marvell IE header */ | ||
1047 | pos += lbs_add_common_rates_tlv(pos, bss); | 1099 | pos += lbs_add_common_rates_tlv(pos, bss); |
1100 | lbs_deb_hex(LBS_DEB_ASSOC, "Common Rates", tmp, pos - tmp); | ||
1048 | 1101 | ||
1049 | /* add auth type TLV */ | 1102 | /* add auth type TLV */ |
1050 | if (priv->fwrelease >= 0x09000000) | 1103 | if (priv->fwrelease >= 0x09000000) |
@@ -1124,7 +1177,62 @@ done: | |||
1124 | return ret; | 1177 | return ret; |
1125 | } | 1178 | } |
1126 | 1179 | ||
1180 | static struct cfg80211_scan_request * | ||
1181 | _new_connect_scan_req(struct wiphy *wiphy, struct cfg80211_connect_params *sme) | ||
1182 | { | ||
1183 | struct cfg80211_scan_request *creq = NULL; | ||
1184 | int i, n_channels = 0; | ||
1185 | enum ieee80211_band band; | ||
1186 | |||
1187 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
1188 | if (wiphy->bands[band]) | ||
1189 | n_channels += wiphy->bands[band]->n_channels; | ||
1190 | } | ||
1191 | |||
1192 | creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + | ||
1193 | n_channels * sizeof(void *), | ||
1194 | GFP_ATOMIC); | ||
1195 | if (!creq) | ||
1196 | return NULL; | ||
1197 | |||
1198 | /* SSIDs come after channels */ | ||
1199 | creq->ssids = (void *)&creq->channels[n_channels]; | ||
1200 | creq->n_channels = n_channels; | ||
1201 | creq->n_ssids = 1; | ||
1202 | |||
1203 | /* Scan all available channels */ | ||
1204 | i = 0; | ||
1205 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
1206 | int j; | ||
1207 | |||
1208 | if (!wiphy->bands[band]) | ||
1209 | continue; | ||
1210 | |||
1211 | for (j = 0; j < wiphy->bands[band]->n_channels; j++) { | ||
1212 | /* ignore disabled channels */ | ||
1213 | if (wiphy->bands[band]->channels[j].flags & | ||
1214 | IEEE80211_CHAN_DISABLED) | ||
1215 | continue; | ||
1216 | |||
1217 | creq->channels[i] = &wiphy->bands[band]->channels[j]; | ||
1218 | i++; | ||
1219 | } | ||
1220 | } | ||
1221 | if (i) { | ||
1222 | /* Set real number of channels specified in creq->channels[] */ | ||
1223 | creq->n_channels = i; | ||
1224 | |||
1225 | /* Scan for the SSID we're going to connect to */ | ||
1226 | memcpy(creq->ssids[0].ssid, sme->ssid, sme->ssid_len); | ||
1227 | creq->ssids[0].ssid_len = sme->ssid_len; | ||
1228 | } else { | ||
1229 | /* No channels found... */ | ||
1230 | kfree(creq); | ||
1231 | creq = NULL; | ||
1232 | } | ||
1127 | 1233 | ||
1234 | return creq; | ||
1235 | } | ||
1128 | 1236 | ||
1129 | static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, | 1237 | static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, |
1130 | struct cfg80211_connect_params *sme) | 1238 | struct cfg80211_connect_params *sme) |
@@ -1136,37 +1244,43 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1136 | 1244 | ||
1137 | lbs_deb_enter(LBS_DEB_CFG80211); | 1245 | lbs_deb_enter(LBS_DEB_CFG80211); |
1138 | 1246 | ||
1139 | if (sme->bssid) { | 1247 | if (!sme->bssid) { |
1140 | bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, | 1248 | /* Run a scan if one isn't in-progress already and if the last |
1141 | sme->ssid, sme->ssid_len, | 1249 | * scan was done more than 2 seconds ago. |
1142 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | ||
1143 | } else { | ||
1144 | /* | ||
1145 | * Here we have an impedance mismatch. The firmware command | ||
1146 | * CMD_802_11_ASSOCIATE always needs a BSSID, it cannot | ||
1147 | * connect otherwise. However, for the connect-API of | ||
1148 | * cfg80211 the bssid is purely optional. We don't get one, | ||
1149 | * except the user specifies one on the "iw" command line. | ||
1150 | * | ||
1151 | * If we don't got one, we could initiate a scan and look | ||
1152 | * for the best matching cfg80211_bss entry. | ||
1153 | * | ||
1154 | * Or, better yet, net/wireless/sme.c get's rewritten into | ||
1155 | * something more generally useful. | ||
1156 | */ | 1250 | */ |
1157 | lbs_pr_err("TODO: no BSS specified\n"); | 1251 | if (priv->scan_req == NULL && |
1158 | ret = -ENOTSUPP; | 1252 | time_after(jiffies, priv->last_scan + (2 * HZ))) { |
1159 | goto done; | 1253 | struct cfg80211_scan_request *creq; |
1160 | } | ||
1161 | 1254 | ||
1255 | creq = _new_connect_scan_req(wiphy, sme); | ||
1256 | if (!creq) { | ||
1257 | ret = -EINVAL; | ||
1258 | goto done; | ||
1259 | } | ||
1260 | |||
1261 | lbs_deb_assoc("assoc: scanning for compatible AP\n"); | ||
1262 | _internal_start_scan(priv, true, creq); | ||
1263 | } | ||
1264 | |||
1265 | /* Wait for any in-progress scan to complete */ | ||
1266 | lbs_deb_assoc("assoc: waiting for scan to complete\n"); | ||
1267 | wait_event_interruptible_timeout(priv->scan_q, | ||
1268 | (priv->scan_req == NULL), | ||
1269 | (15 * HZ)); | ||
1270 | lbs_deb_assoc("assoc: scanning competed\n"); | ||
1271 | } | ||
1162 | 1272 | ||
1273 | /* Find the BSS we want using available scan results */ | ||
1274 | bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, | ||
1275 | sme->ssid, sme->ssid_len, | ||
1276 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | ||
1163 | if (!bss) { | 1277 | if (!bss) { |
1164 | lbs_pr_err("assicate: bss %pM not in scan results\n", | 1278 | lbs_pr_err("assoc: bss %pM not in scan results\n", |
1165 | sme->bssid); | 1279 | sme->bssid); |
1166 | ret = -ENOENT; | 1280 | ret = -ENOENT; |
1167 | goto done; | 1281 | goto done; |
1168 | } | 1282 | } |
1169 | lbs_deb_assoc("trying %pM", sme->bssid); | 1283 | lbs_deb_assoc("trying %pM\n", bss->bssid); |
1170 | lbs_deb_assoc("cipher 0x%x, key index %d, key len %d\n", | 1284 | lbs_deb_assoc("cipher 0x%x, key index %d, key len %d\n", |
1171 | sme->crypto.cipher_group, | 1285 | sme->crypto.cipher_group, |
1172 | sme->key_idx, sme->key_len); | 1286 | sme->key_idx, sme->key_len); |
@@ -1229,7 +1343,7 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1229 | lbs_set_radio(priv, preamble, 1); | 1343 | lbs_set_radio(priv, preamble, 1); |
1230 | 1344 | ||
1231 | /* Do the actual association */ | 1345 | /* Do the actual association */ |
1232 | lbs_associate(priv, bss, sme); | 1346 | ret = lbs_associate(priv, bss, sme); |
1233 | 1347 | ||
1234 | done: | 1348 | done: |
1235 | if (bss) | 1349 | if (bss) |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 3c7e255e18c7..f062ed583901 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -161,6 +161,11 @@ struct lbs_private { | |||
161 | /** Scanning */ | 161 | /** Scanning */ |
162 | struct delayed_work scan_work; | 162 | struct delayed_work scan_work; |
163 | int scan_channel; | 163 | int scan_channel; |
164 | /* Queue of things waiting for scan completion */ | ||
165 | wait_queue_head_t scan_q; | ||
166 | /* Whether the scan was initiated internally and not by cfg80211 */ | ||
167 | bool internal_scan; | ||
168 | unsigned long last_scan; | ||
164 | }; | 169 | }; |
165 | 170 | ||
166 | extern struct cmd_confirm_sleep confirm_sleep; | 171 | extern struct cmd_confirm_sleep confirm_sleep; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 258967144b96..24958a86747b 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -719,6 +719,7 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
719 | priv->deep_sleep_required = 0; | 719 | priv->deep_sleep_required = 0; |
720 | priv->wakeup_dev_required = 0; | 720 | priv->wakeup_dev_required = 0; |
721 | init_waitqueue_head(&priv->ds_awake_q); | 721 | init_waitqueue_head(&priv->ds_awake_q); |
722 | init_waitqueue_head(&priv->scan_q); | ||
722 | priv->authtype_auto = 1; | 723 | priv->authtype_auto = 1; |
723 | priv->is_host_sleep_configured = 0; | 724 | priv->is_host_sleep_configured = 0; |
724 | priv->is_host_sleep_activated = 0; | 725 | priv->is_host_sleep_activated = 0; |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 822f8dc26e9c..71a101fb2e4e 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -43,6 +43,8 @@ static DEFINE_PCI_DEVICE_TABLE(p54p_table) = { | |||
43 | { PCI_DEVICE(0x1260, 0x3886) }, | 43 | { PCI_DEVICE(0x1260, 0x3886) }, |
44 | /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */ | 44 | /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */ |
45 | { PCI_DEVICE(0x1260, 0xffff) }, | 45 | { PCI_DEVICE(0x1260, 0xffff) }, |
46 | /* Standard Microsystems Corp SMC2802W Wireless PCI */ | ||
47 | { PCI_DEVICE(0x10b8, 0x2802) }, | ||
46 | { }, | 48 | { }, |
47 | }; | 49 | }; |
48 | 50 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 19b262e1ddbe..63c2cc408e15 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -240,16 +240,16 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) | |||
240 | struct rt2x00_dev *rt2x00dev; | 240 | struct rt2x00_dev *rt2x00dev; |
241 | int retval; | 241 | int retval; |
242 | 242 | ||
243 | retval = pci_request_regions(pci_dev, pci_name(pci_dev)); | 243 | retval = pci_enable_device(pci_dev); |
244 | if (retval) { | 244 | if (retval) { |
245 | ERROR_PROBE("PCI request regions failed.\n"); | 245 | ERROR_PROBE("Enable device failed.\n"); |
246 | return retval; | 246 | return retval; |
247 | } | 247 | } |
248 | 248 | ||
249 | retval = pci_enable_device(pci_dev); | 249 | retval = pci_request_regions(pci_dev, pci_name(pci_dev)); |
250 | if (retval) { | 250 | if (retval) { |
251 | ERROR_PROBE("Enable device failed.\n"); | 251 | ERROR_PROBE("PCI request regions failed.\n"); |
252 | goto exit_release_regions; | 252 | goto exit_disable_device; |
253 | } | 253 | } |
254 | 254 | ||
255 | pci_set_master(pci_dev); | 255 | pci_set_master(pci_dev); |
@@ -260,14 +260,14 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) | |||
260 | if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) { | 260 | if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) { |
261 | ERROR_PROBE("PCI DMA not supported.\n"); | 261 | ERROR_PROBE("PCI DMA not supported.\n"); |
262 | retval = -EIO; | 262 | retval = -EIO; |
263 | goto exit_disable_device; | 263 | goto exit_release_regions; |
264 | } | 264 | } |
265 | 265 | ||
266 | hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw); | 266 | hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw); |
267 | if (!hw) { | 267 | if (!hw) { |
268 | ERROR_PROBE("Failed to allocate hardware.\n"); | 268 | ERROR_PROBE("Failed to allocate hardware.\n"); |
269 | retval = -ENOMEM; | 269 | retval = -ENOMEM; |
270 | goto exit_disable_device; | 270 | goto exit_release_regions; |
271 | } | 271 | } |
272 | 272 | ||
273 | pci_set_drvdata(pci_dev, hw); | 273 | pci_set_drvdata(pci_dev, hw); |
@@ -300,13 +300,12 @@ exit_free_reg: | |||
300 | exit_free_device: | 300 | exit_free_device: |
301 | ieee80211_free_hw(hw); | 301 | ieee80211_free_hw(hw); |
302 | 302 | ||
303 | exit_disable_device: | ||
304 | if (retval != -EBUSY) | ||
305 | pci_disable_device(pci_dev); | ||
306 | |||
307 | exit_release_regions: | 303 | exit_release_regions: |
308 | pci_release_regions(pci_dev); | 304 | pci_release_regions(pci_dev); |
309 | 305 | ||
306 | exit_disable_device: | ||
307 | pci_disable_device(pci_dev); | ||
308 | |||
310 | pci_set_drvdata(pci_dev, NULL); | 309 | pci_set_drvdata(pci_dev, NULL); |
311 | 310 | ||
312 | return retval; | 311 | return retval; |
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 1d8178563d76..b50c39aaec05 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -695,6 +695,8 @@ static void rtl8180_beacon_work(struct work_struct *work) | |||
695 | 695 | ||
696 | /* grab a fresh beacon */ | 696 | /* grab a fresh beacon */ |
697 | skb = ieee80211_beacon_get(dev, vif); | 697 | skb = ieee80211_beacon_get(dev, vif); |
698 | if (!skb) | ||
699 | goto resched; | ||
698 | 700 | ||
699 | /* | 701 | /* |
700 | * update beacon timestamp w/ TSF value | 702 | * update beacon timestamp w/ TSF value |
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 96d25fb50495..4cb99c541e2a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -160,9 +160,8 @@ static void wl1271_spi_init(struct wl1271 *wl) | |||
160 | spi_message_add_tail(&t, &m); | 160 | spi_message_add_tail(&t, &m); |
161 | 161 | ||
162 | spi_sync(wl_to_spi(wl), &m); | 162 | spi_sync(wl_to_spi(wl), &m); |
163 | kfree(cmd); | ||
164 | |||
165 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); | 163 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); |
164 | kfree(cmd); | ||
166 | } | 165 | } |
167 | 166 | ||
168 | #define WL1271_BUSY_WORD_TIMEOUT 1000 | 167 | #define WL1271_BUSY_WORD_TIMEOUT 1000 |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 6a5af18faf68..b0de57947189 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -3030,6 +3030,34 @@ static void __init iommu_exit_mempool(void) | |||
3030 | 3030 | ||
3031 | } | 3031 | } |
3032 | 3032 | ||
3033 | static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev) | ||
3034 | { | ||
3035 | struct dmar_drhd_unit *drhd; | ||
3036 | u32 vtbar; | ||
3037 | int rc; | ||
3038 | |||
3039 | /* We know that this device on this chipset has its own IOMMU. | ||
3040 | * If we find it under a different IOMMU, then the BIOS is lying | ||
3041 | * to us. Hope that the IOMMU for this device is actually | ||
3042 | * disabled, and it needs no translation... | ||
3043 | */ | ||
3044 | rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar); | ||
3045 | if (rc) { | ||
3046 | /* "can't" happen */ | ||
3047 | dev_info(&pdev->dev, "failed to run vt-d quirk\n"); | ||
3048 | return; | ||
3049 | } | ||
3050 | vtbar &= 0xffff0000; | ||
3051 | |||
3052 | /* we know that the this iommu should be at offset 0xa000 from vtbar */ | ||
3053 | drhd = dmar_find_matched_drhd_unit(pdev); | ||
3054 | if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000, | ||
3055 | TAINT_FIRMWARE_WORKAROUND, | ||
3056 | "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n")) | ||
3057 | pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; | ||
3058 | } | ||
3059 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu); | ||
3060 | |||
3033 | static void __init init_no_remapping_devices(void) | 3061 | static void __init init_no_remapping_devices(void) |
3034 | { | 3062 | { |
3035 | struct dmar_drhd_unit *drhd; | 3063 | struct dmar_drhd_unit *drhd; |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index bed7b4634ccd..8d41f3ed38d7 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -1083,6 +1083,49 @@ dasd_eer_store(struct device *dev, struct device_attribute *attr, | |||
1083 | 1083 | ||
1084 | static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store); | 1084 | static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store); |
1085 | 1085 | ||
1086 | /* | ||
1087 | * expiration time for default requests | ||
1088 | */ | ||
1089 | static ssize_t | ||
1090 | dasd_expires_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
1091 | { | ||
1092 | struct dasd_device *device; | ||
1093 | int len; | ||
1094 | |||
1095 | device = dasd_device_from_cdev(to_ccwdev(dev)); | ||
1096 | if (IS_ERR(device)) | ||
1097 | return -ENODEV; | ||
1098 | len = snprintf(buf, PAGE_SIZE, "%lu\n", device->default_expires); | ||
1099 | dasd_put_device(device); | ||
1100 | return len; | ||
1101 | } | ||
1102 | |||
1103 | static ssize_t | ||
1104 | dasd_expires_store(struct device *dev, struct device_attribute *attr, | ||
1105 | const char *buf, size_t count) | ||
1106 | { | ||
1107 | struct dasd_device *device; | ||
1108 | unsigned long val; | ||
1109 | |||
1110 | device = dasd_device_from_cdev(to_ccwdev(dev)); | ||
1111 | if (IS_ERR(device)) | ||
1112 | return -ENODEV; | ||
1113 | |||
1114 | if ((strict_strtoul(buf, 10, &val) != 0) || | ||
1115 | (val > DASD_EXPIRES_MAX) || val == 0) { | ||
1116 | dasd_put_device(device); | ||
1117 | return -EINVAL; | ||
1118 | } | ||
1119 | |||
1120 | if (val) | ||
1121 | device->default_expires = val; | ||
1122 | |||
1123 | dasd_put_device(device); | ||
1124 | return count; | ||
1125 | } | ||
1126 | |||
1127 | static DEVICE_ATTR(expires, 0644, dasd_expires_show, dasd_expires_store); | ||
1128 | |||
1086 | static struct attribute * dasd_attrs[] = { | 1129 | static struct attribute * dasd_attrs[] = { |
1087 | &dev_attr_readonly.attr, | 1130 | &dev_attr_readonly.attr, |
1088 | &dev_attr_discipline.attr, | 1131 | &dev_attr_discipline.attr, |
@@ -1094,6 +1137,7 @@ static struct attribute * dasd_attrs[] = { | |||
1094 | &dev_attr_eer_enabled.attr, | 1137 | &dev_attr_eer_enabled.attr, |
1095 | &dev_attr_erplog.attr, | 1138 | &dev_attr_erplog.attr, |
1096 | &dev_attr_failfast.attr, | 1139 | &dev_attr_failfast.attr, |
1140 | &dev_attr_expires.attr, | ||
1097 | NULL, | 1141 | NULL, |
1098 | }; | 1142 | }; |
1099 | 1143 | ||
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 687f323cdc38..2b3bc3ec0541 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
@@ -43,7 +43,7 @@ MODULE_LICENSE("GPL"); | |||
43 | sizeof(struct dasd_diag_req)) / \ | 43 | sizeof(struct dasd_diag_req)) / \ |
44 | sizeof(struct dasd_diag_bio)) / 2) | 44 | sizeof(struct dasd_diag_bio)) / 2) |
45 | #define DIAG_MAX_RETRIES 32 | 45 | #define DIAG_MAX_RETRIES 32 |
46 | #define DIAG_TIMEOUT 50 * HZ | 46 | #define DIAG_TIMEOUT 50 |
47 | 47 | ||
48 | static struct dasd_discipline dasd_diag_discipline; | 48 | static struct dasd_discipline dasd_diag_discipline; |
49 | 49 | ||
@@ -360,6 +360,8 @@ dasd_diag_check_device(struct dasd_device *device) | |||
360 | goto out; | 360 | goto out; |
361 | } | 361 | } |
362 | 362 | ||
363 | device->default_expires = DIAG_TIMEOUT; | ||
364 | |||
363 | /* Figure out position of label block */ | 365 | /* Figure out position of label block */ |
364 | switch (private->rdc_data.vdev_class) { | 366 | switch (private->rdc_data.vdev_class) { |
365 | case DEV_CLASS_FBA: | 367 | case DEV_CLASS_FBA: |
@@ -563,7 +565,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev, | |||
563 | cqr->startdev = memdev; | 565 | cqr->startdev = memdev; |
564 | cqr->memdev = memdev; | 566 | cqr->memdev = memdev; |
565 | cqr->block = block; | 567 | cqr->block = block; |
566 | cqr->expires = DIAG_TIMEOUT; | 568 | cqr->expires = memdev->default_expires * HZ; |
567 | cqr->status = DASD_CQR_FILLED; | 569 | cqr->status = DASD_CQR_FILLED; |
568 | return cqr; | 570 | return cqr; |
569 | } | 571 | } |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index ab84da5592e8..66360c24bd48 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -82,6 +82,14 @@ static struct ccw_driver dasd_eckd_driver; /* see below */ | |||
82 | #define INIT_CQR_UNFORMATTED 1 | 82 | #define INIT_CQR_UNFORMATTED 1 |
83 | #define INIT_CQR_ERROR 2 | 83 | #define INIT_CQR_ERROR 2 |
84 | 84 | ||
85 | /* emergency request for reserve/release */ | ||
86 | static struct { | ||
87 | struct dasd_ccw_req cqr; | ||
88 | struct ccw1 ccw; | ||
89 | char data[32]; | ||
90 | } *dasd_reserve_req; | ||
91 | static DEFINE_MUTEX(dasd_reserve_mutex); | ||
92 | |||
85 | 93 | ||
86 | /* initial attempt at a probe function. this can be simplified once | 94 | /* initial attempt at a probe function. this can be simplified once |
87 | * the other detection code is gone */ | 95 | * the other detection code is gone */ |
@@ -1107,8 +1115,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
1107 | struct dasd_eckd_private *private; | 1115 | struct dasd_eckd_private *private; |
1108 | struct dasd_block *block; | 1116 | struct dasd_block *block; |
1109 | struct dasd_uid temp_uid; | 1117 | struct dasd_uid temp_uid; |
1110 | int is_known, rc; | 1118 | int is_known, rc, i; |
1111 | int readonly; | 1119 | int readonly; |
1120 | unsigned long value; | ||
1112 | 1121 | ||
1113 | if (!ccw_device_is_pathgroup(device->cdev)) { | 1122 | if (!ccw_device_is_pathgroup(device->cdev)) { |
1114 | dev_warn(&device->cdev->dev, | 1123 | dev_warn(&device->cdev->dev, |
@@ -1143,6 +1152,18 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
1143 | if (rc) | 1152 | if (rc) |
1144 | goto out_err1; | 1153 | goto out_err1; |
1145 | 1154 | ||
1155 | /* set default timeout */ | ||
1156 | device->default_expires = DASD_EXPIRES; | ||
1157 | if (private->gneq) { | ||
1158 | value = 1; | ||
1159 | for (i = 0; i < private->gneq->timeout.value; i++) | ||
1160 | value = 10 * value; | ||
1161 | value = value * private->gneq->timeout.number; | ||
1162 | /* do not accept useless values */ | ||
1163 | if (value != 0 && value <= DASD_EXPIRES_MAX) | ||
1164 | device->default_expires = value; | ||
1165 | } | ||
1166 | |||
1146 | /* Generate device unique id */ | 1167 | /* Generate device unique id */ |
1147 | rc = dasd_eckd_generate_uid(device); | 1168 | rc = dasd_eckd_generate_uid(device); |
1148 | if (rc) | 1169 | if (rc) |
@@ -1973,7 +1994,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( | |||
1973 | cqr->startdev = startdev; | 1994 | cqr->startdev = startdev; |
1974 | cqr->memdev = startdev; | 1995 | cqr->memdev = startdev; |
1975 | cqr->block = block; | 1996 | cqr->block = block; |
1976 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ | 1997 | cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */ |
1977 | cqr->lpm = private->path_data.ppm; | 1998 | cqr->lpm = private->path_data.ppm; |
1978 | cqr->retries = 256; | 1999 | cqr->retries = 256; |
1979 | cqr->buildclk = get_clock(); | 2000 | cqr->buildclk = get_clock(); |
@@ -2150,7 +2171,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( | |||
2150 | cqr->startdev = startdev; | 2171 | cqr->startdev = startdev; |
2151 | cqr->memdev = startdev; | 2172 | cqr->memdev = startdev; |
2152 | cqr->block = block; | 2173 | cqr->block = block; |
2153 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ | 2174 | cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */ |
2154 | cqr->lpm = private->path_data.ppm; | 2175 | cqr->lpm = private->path_data.ppm; |
2155 | cqr->retries = 256; | 2176 | cqr->retries = 256; |
2156 | cqr->buildclk = get_clock(); | 2177 | cqr->buildclk = get_clock(); |
@@ -2398,7 +2419,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | |||
2398 | cqr->startdev = startdev; | 2419 | cqr->startdev = startdev; |
2399 | cqr->memdev = startdev; | 2420 | cqr->memdev = startdev; |
2400 | cqr->block = block; | 2421 | cqr->block = block; |
2401 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ | 2422 | cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */ |
2402 | cqr->lpm = private->path_data.ppm; | 2423 | cqr->lpm = private->path_data.ppm; |
2403 | cqr->retries = 256; | 2424 | cqr->retries = 256; |
2404 | cqr->buildclk = get_clock(); | 2425 | cqr->buildclk = get_clock(); |
@@ -2645,15 +2666,23 @@ dasd_eckd_release(struct dasd_device *device) | |||
2645 | struct dasd_ccw_req *cqr; | 2666 | struct dasd_ccw_req *cqr; |
2646 | int rc; | 2667 | int rc; |
2647 | struct ccw1 *ccw; | 2668 | struct ccw1 *ccw; |
2669 | int useglobal; | ||
2648 | 2670 | ||
2649 | if (!capable(CAP_SYS_ADMIN)) | 2671 | if (!capable(CAP_SYS_ADMIN)) |
2650 | return -EACCES; | 2672 | return -EACCES; |
2651 | 2673 | ||
2674 | useglobal = 0; | ||
2652 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); | 2675 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); |
2653 | if (IS_ERR(cqr)) { | 2676 | if (IS_ERR(cqr)) { |
2654 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 2677 | mutex_lock(&dasd_reserve_mutex); |
2655 | "Could not allocate initialization request"); | 2678 | useglobal = 1; |
2656 | return PTR_ERR(cqr); | 2679 | cqr = &dasd_reserve_req->cqr; |
2680 | memset(cqr, 0, sizeof(*cqr)); | ||
2681 | memset(&dasd_reserve_req->ccw, 0, | ||
2682 | sizeof(dasd_reserve_req->ccw)); | ||
2683 | cqr->cpaddr = &dasd_reserve_req->ccw; | ||
2684 | cqr->data = &dasd_reserve_req->data; | ||
2685 | cqr->magic = DASD_ECKD_MAGIC; | ||
2657 | } | 2686 | } |
2658 | ccw = cqr->cpaddr; | 2687 | ccw = cqr->cpaddr; |
2659 | ccw->cmd_code = DASD_ECKD_CCW_RELEASE; | 2688 | ccw->cmd_code = DASD_ECKD_CCW_RELEASE; |
@@ -2671,7 +2700,10 @@ dasd_eckd_release(struct dasd_device *device) | |||
2671 | 2700 | ||
2672 | rc = dasd_sleep_on_immediatly(cqr); | 2701 | rc = dasd_sleep_on_immediatly(cqr); |
2673 | 2702 | ||
2674 | dasd_sfree_request(cqr, cqr->memdev); | 2703 | if (useglobal) |
2704 | mutex_unlock(&dasd_reserve_mutex); | ||
2705 | else | ||
2706 | dasd_sfree_request(cqr, cqr->memdev); | ||
2675 | return rc; | 2707 | return rc; |
2676 | } | 2708 | } |
2677 | 2709 | ||
@@ -2687,15 +2719,23 @@ dasd_eckd_reserve(struct dasd_device *device) | |||
2687 | struct dasd_ccw_req *cqr; | 2719 | struct dasd_ccw_req *cqr; |
2688 | int rc; | 2720 | int rc; |
2689 | struct ccw1 *ccw; | 2721 | struct ccw1 *ccw; |
2722 | int useglobal; | ||
2690 | 2723 | ||
2691 | if (!capable(CAP_SYS_ADMIN)) | 2724 | if (!capable(CAP_SYS_ADMIN)) |
2692 | return -EACCES; | 2725 | return -EACCES; |
2693 | 2726 | ||
2727 | useglobal = 0; | ||
2694 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); | 2728 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); |
2695 | if (IS_ERR(cqr)) { | 2729 | if (IS_ERR(cqr)) { |
2696 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 2730 | mutex_lock(&dasd_reserve_mutex); |
2697 | "Could not allocate initialization request"); | 2731 | useglobal = 1; |
2698 | return PTR_ERR(cqr); | 2732 | cqr = &dasd_reserve_req->cqr; |
2733 | memset(cqr, 0, sizeof(*cqr)); | ||
2734 | memset(&dasd_reserve_req->ccw, 0, | ||
2735 | sizeof(dasd_reserve_req->ccw)); | ||
2736 | cqr->cpaddr = &dasd_reserve_req->ccw; | ||
2737 | cqr->data = &dasd_reserve_req->data; | ||
2738 | cqr->magic = DASD_ECKD_MAGIC; | ||
2699 | } | 2739 | } |
2700 | ccw = cqr->cpaddr; | 2740 | ccw = cqr->cpaddr; |
2701 | ccw->cmd_code = DASD_ECKD_CCW_RESERVE; | 2741 | ccw->cmd_code = DASD_ECKD_CCW_RESERVE; |
@@ -2713,7 +2753,10 @@ dasd_eckd_reserve(struct dasd_device *device) | |||
2713 | 2753 | ||
2714 | rc = dasd_sleep_on_immediatly(cqr); | 2754 | rc = dasd_sleep_on_immediatly(cqr); |
2715 | 2755 | ||
2716 | dasd_sfree_request(cqr, cqr->memdev); | 2756 | if (useglobal) |
2757 | mutex_unlock(&dasd_reserve_mutex); | ||
2758 | else | ||
2759 | dasd_sfree_request(cqr, cqr->memdev); | ||
2717 | return rc; | 2760 | return rc; |
2718 | } | 2761 | } |
2719 | 2762 | ||
@@ -2728,15 +2771,23 @@ dasd_eckd_steal_lock(struct dasd_device *device) | |||
2728 | struct dasd_ccw_req *cqr; | 2771 | struct dasd_ccw_req *cqr; |
2729 | int rc; | 2772 | int rc; |
2730 | struct ccw1 *ccw; | 2773 | struct ccw1 *ccw; |
2774 | int useglobal; | ||
2731 | 2775 | ||
2732 | if (!capable(CAP_SYS_ADMIN)) | 2776 | if (!capable(CAP_SYS_ADMIN)) |
2733 | return -EACCES; | 2777 | return -EACCES; |
2734 | 2778 | ||
2779 | useglobal = 0; | ||
2735 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); | 2780 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); |
2736 | if (IS_ERR(cqr)) { | 2781 | if (IS_ERR(cqr)) { |
2737 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 2782 | mutex_lock(&dasd_reserve_mutex); |
2738 | "Could not allocate initialization request"); | 2783 | useglobal = 1; |
2739 | return PTR_ERR(cqr); | 2784 | cqr = &dasd_reserve_req->cqr; |
2785 | memset(cqr, 0, sizeof(*cqr)); | ||
2786 | memset(&dasd_reserve_req->ccw, 0, | ||
2787 | sizeof(dasd_reserve_req->ccw)); | ||
2788 | cqr->cpaddr = &dasd_reserve_req->ccw; | ||
2789 | cqr->data = &dasd_reserve_req->data; | ||
2790 | cqr->magic = DASD_ECKD_MAGIC; | ||
2740 | } | 2791 | } |
2741 | ccw = cqr->cpaddr; | 2792 | ccw = cqr->cpaddr; |
2742 | ccw->cmd_code = DASD_ECKD_CCW_SLCK; | 2793 | ccw->cmd_code = DASD_ECKD_CCW_SLCK; |
@@ -2754,7 +2805,10 @@ dasd_eckd_steal_lock(struct dasd_device *device) | |||
2754 | 2805 | ||
2755 | rc = dasd_sleep_on_immediatly(cqr); | 2806 | rc = dasd_sleep_on_immediatly(cqr); |
2756 | 2807 | ||
2757 | dasd_sfree_request(cqr, cqr->memdev); | 2808 | if (useglobal) |
2809 | mutex_unlock(&dasd_reserve_mutex); | ||
2810 | else | ||
2811 | dasd_sfree_request(cqr, cqr->memdev); | ||
2758 | return rc; | 2812 | return rc; |
2759 | } | 2813 | } |
2760 | 2814 | ||
@@ -3488,10 +3542,15 @@ dasd_eckd_init(void) | |||
3488 | int ret; | 3542 | int ret; |
3489 | 3543 | ||
3490 | ASCEBC(dasd_eckd_discipline.ebcname, 4); | 3544 | ASCEBC(dasd_eckd_discipline.ebcname, 4); |
3545 | dasd_reserve_req = kmalloc(sizeof(*dasd_reserve_req), | ||
3546 | GFP_KERNEL | GFP_DMA); | ||
3547 | if (!dasd_reserve_req) | ||
3548 | return -ENOMEM; | ||
3491 | ret = ccw_driver_register(&dasd_eckd_driver); | 3549 | ret = ccw_driver_register(&dasd_eckd_driver); |
3492 | if (!ret) | 3550 | if (!ret) |
3493 | wait_for_device_probe(); | 3551 | wait_for_device_probe(); |
3494 | 3552 | else | |
3553 | kfree(dasd_reserve_req); | ||
3495 | return ret; | 3554 | return ret; |
3496 | } | 3555 | } |
3497 | 3556 | ||
@@ -3499,6 +3558,7 @@ static void __exit | |||
3499 | dasd_eckd_cleanup(void) | 3558 | dasd_eckd_cleanup(void) |
3500 | { | 3559 | { |
3501 | ccw_driver_unregister(&dasd_eckd_driver); | 3560 | ccw_driver_unregister(&dasd_eckd_driver); |
3561 | kfree(dasd_reserve_req); | ||
3502 | } | 3562 | } |
3503 | 3563 | ||
3504 | module_init(dasd_eckd_init); | 3564 | module_init(dasd_eckd_init); |
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index dd6385a5af14..0eb49655a6cd 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h | |||
@@ -320,7 +320,12 @@ struct dasd_gneq { | |||
320 | __u8 identifier:2; | 320 | __u8 identifier:2; |
321 | __u8 reserved:6; | 321 | __u8 reserved:6; |
322 | } __attribute__ ((packed)) flags; | 322 | } __attribute__ ((packed)) flags; |
323 | __u8 reserved[7]; | 323 | __u8 reserved[5]; |
324 | struct { | ||
325 | __u8 value:2; | ||
326 | __u8 number:6; | ||
327 | } __attribute__ ((packed)) timeout; | ||
328 | __u8 reserved3; | ||
324 | __u16 subsystemID; | 329 | __u16 subsystemID; |
325 | __u8 reserved2[22]; | 330 | __u8 reserved2[22]; |
326 | } __attribute__ ((packed)); | 331 | } __attribute__ ((packed)); |
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index dd88803e4899..7158f9528ecc 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c | |||
@@ -701,7 +701,7 @@ int __init dasd_eer_init(void) | |||
701 | void dasd_eer_exit(void) | 701 | void dasd_eer_exit(void) |
702 | { | 702 | { |
703 | if (dasd_eer_dev) { | 703 | if (dasd_eer_dev) { |
704 | WARN_ON(misc_deregister(dasd_eer_dev) != 0); | 704 | misc_deregister(dasd_eer_dev); |
705 | kfree(dasd_eer_dev); | 705 | kfree(dasd_eer_dev); |
706 | dasd_eer_dev = NULL; | 706 | dasd_eer_dev = NULL; |
707 | } | 707 | } |
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 37282b90eecc..bec5486e0e6d 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
@@ -163,6 +163,8 @@ dasd_fba_check_characteristics(struct dasd_device *device) | |||
163 | return rc; | 163 | return rc; |
164 | } | 164 | } |
165 | 165 | ||
166 | device->default_expires = DASD_EXPIRES; | ||
167 | |||
166 | readonly = dasd_device_is_ro(device); | 168 | readonly = dasd_device_is_ro(device); |
167 | if (readonly) | 169 | if (readonly) |
168 | set_bit(DASD_FLAG_DEVICE_RO, &device->flags); | 170 | set_bit(DASD_FLAG_DEVICE_RO, &device->flags); |
@@ -370,7 +372,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev, | |||
370 | cqr->startdev = memdev; | 372 | cqr->startdev = memdev; |
371 | cqr->memdev = memdev; | 373 | cqr->memdev = memdev; |
372 | cqr->block = block; | 374 | cqr->block = block; |
373 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ | 375 | cqr->expires = memdev->default_expires * HZ; /* default 5 minutes */ |
374 | cqr->retries = 32; | 376 | cqr->retries = 32; |
375 | cqr->buildclk = get_clock(); | 377 | cqr->buildclk = get_clock(); |
376 | cqr->status = DASD_CQR_FILLED; | 378 | cqr->status = DASD_CQR_FILLED; |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 49b431d135e0..500678d7116c 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -186,7 +186,7 @@ struct dasd_ccw_req { | |||
186 | 186 | ||
187 | /* ... and how */ | 187 | /* ... and how */ |
188 | unsigned long starttime; /* jiffies time of request start */ | 188 | unsigned long starttime; /* jiffies time of request start */ |
189 | int expires; /* expiration period in jiffies */ | 189 | unsigned long expires; /* expiration period in jiffies */ |
190 | char lpm; /* logical path mask */ | 190 | char lpm; /* logical path mask */ |
191 | void *data; /* pointer to data area */ | 191 | void *data; /* pointer to data area */ |
192 | 192 | ||
@@ -224,6 +224,9 @@ struct dasd_ccw_req { | |||
224 | #define DASD_CQR_CLEARED 0x84 /* request was cleared */ | 224 | #define DASD_CQR_CLEARED 0x84 /* request was cleared */ |
225 | #define DASD_CQR_SUCCESS 0x85 /* request was successful */ | 225 | #define DASD_CQR_SUCCESS 0x85 /* request was successful */ |
226 | 226 | ||
227 | /* default expiration time*/ | ||
228 | #define DASD_EXPIRES 300 | ||
229 | #define DASD_EXPIRES_MAX 40000000 | ||
227 | 230 | ||
228 | /* per dasd_ccw_req flags */ | 231 | /* per dasd_ccw_req flags */ |
229 | #define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */ | 232 | #define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */ |
@@ -404,6 +407,9 @@ struct dasd_device { | |||
404 | 407 | ||
405 | /* hook for alias management */ | 408 | /* hook for alias management */ |
406 | struct list_head alias_list; | 409 | struct list_head alias_list; |
410 | |||
411 | /* default expiration time in s */ | ||
412 | unsigned long default_expires; | ||
407 | }; | 413 | }; |
408 | 414 | ||
409 | struct dasd_block { | 415 | struct dasd_block { |
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 2ed3f82e5c30..e021ec663ef9 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c | |||
@@ -627,7 +627,7 @@ out_iucv: | |||
627 | static void __exit mon_exit(void) | 627 | static void __exit mon_exit(void) |
628 | { | 628 | { |
629 | segment_unload(mon_dcss_name); | 629 | segment_unload(mon_dcss_name); |
630 | WARN_ON(misc_deregister(&mon_dev) != 0); | 630 | misc_deregister(&mon_dev); |
631 | device_unregister(monreader_device); | 631 | device_unregister(monreader_device); |
632 | driver_unregister(&monreader_driver); | 632 | driver_unregister(&monreader_driver); |
633 | iucv_unregister(&monreader_iucv_handler, 1); | 633 | iucv_unregister(&monreader_iucv_handler, 1); |
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index 98a49dfda1de..572a1e7fd099 100644 --- a/drivers/s390/char/monwriter.c +++ b/drivers/s390/char/monwriter.c | |||
@@ -380,7 +380,7 @@ out_driver: | |||
380 | 380 | ||
381 | static void __exit mon_exit(void) | 381 | static void __exit mon_exit(void) |
382 | { | 382 | { |
383 | WARN_ON(misc_deregister(&mon_dev) != 0); | 383 | misc_deregister(&mon_dev); |
384 | platform_device_unregister(monwriter_pdev); | 384 | platform_device_unregister(monwriter_pdev); |
385 | platform_driver_unregister(&monwriter_pdrv); | 385 | platform_driver_unregister(&monwriter_pdrv); |
386 | } | 386 | } |
diff --git a/drivers/s390/cio/ccwreq.c b/drivers/s390/cio/ccwreq.c index 7f206ed44fdf..d15f8b4d78bd 100644 --- a/drivers/s390/cio/ccwreq.c +++ b/drivers/s390/cio/ccwreq.c | |||
@@ -38,9 +38,13 @@ static u16 ccwreq_next_path(struct ccw_device *cdev) | |||
38 | { | 38 | { |
39 | struct ccw_request *req = &cdev->private->req; | 39 | struct ccw_request *req = &cdev->private->req; |
40 | 40 | ||
41 | if (!req->singlepath) { | ||
42 | req->mask = 0; | ||
43 | goto out; | ||
44 | } | ||
41 | req->retries = req->maxretries; | 45 | req->retries = req->maxretries; |
42 | req->mask = lpm_adjust(req->mask >>= 1, req->lpm); | 46 | req->mask = lpm_adjust(req->mask >>= 1, req->lpm); |
43 | 47 | out: | |
44 | return req->mask; | 48 | return req->mask; |
45 | } | 49 | } |
46 | 50 | ||
@@ -113,8 +117,12 @@ void ccw_request_start(struct ccw_device *cdev) | |||
113 | { | 117 | { |
114 | struct ccw_request *req = &cdev->private->req; | 118 | struct ccw_request *req = &cdev->private->req; |
115 | 119 | ||
116 | /* Try all paths twice to counter link flapping. */ | 120 | if (req->singlepath) { |
117 | req->mask = 0x8080; | 121 | /* Try all paths twice to counter link flapping. */ |
122 | req->mask = 0x8080; | ||
123 | } else | ||
124 | req->mask = req->lpm; | ||
125 | |||
118 | req->retries = req->maxretries; | 126 | req->retries = req->maxretries; |
119 | req->mask = lpm_adjust(req->mask, req->lpm); | 127 | req->mask = lpm_adjust(req->mask, req->lpm); |
120 | req->drc = 0; | 128 | req->drc = 0; |
@@ -182,6 +190,8 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb) | |||
182 | /* Ask the driver what to do */ | 190 | /* Ask the driver what to do */ |
183 | if (cdev->drv && cdev->drv->uc_handler) { | 191 | if (cdev->drv && cdev->drv->uc_handler) { |
184 | todo = cdev->drv->uc_handler(cdev, lcirb); | 192 | todo = cdev->drv->uc_handler(cdev, lcirb); |
193 | CIO_TRACE_EVENT(2, "uc_response"); | ||
194 | CIO_HEX_EVENT(2, &todo, sizeof(todo)); | ||
185 | switch (todo) { | 195 | switch (todo) { |
186 | case UC_TODO_RETRY: | 196 | case UC_TODO_RETRY: |
187 | return IO_STATUS_ERROR; | 197 | return IO_STATUS_ERROR; |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 407d0e9adfaf..4cbb1a6ca33c 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "chsc.h" | 29 | #include "chsc.h" |
30 | 30 | ||
31 | static void *sei_page; | 31 | static void *sei_page; |
32 | static DEFINE_SPINLOCK(siosl_lock); | ||
32 | static DEFINE_SPINLOCK(sda_lock); | 33 | static DEFINE_SPINLOCK(sda_lock); |
33 | 34 | ||
34 | /** | 35 | /** |
@@ -48,6 +49,7 @@ int chsc_error_from_response(int response) | |||
48 | case 0x0007: | 49 | case 0x0007: |
49 | case 0x0008: | 50 | case 0x0008: |
50 | case 0x000a: | 51 | case 0x000a: |
52 | case 0x0104: | ||
51 | return -EINVAL; | 53 | return -EINVAL; |
52 | case 0x0004: | 54 | case 0x0004: |
53 | return -EOPNOTSUPP; | 55 | return -EOPNOTSUPP; |
@@ -974,3 +976,49 @@ int chsc_sstpi(void *page, void *result, size_t size) | |||
974 | return (rr->response.code == 0x0001) ? 0 : -EIO; | 976 | return (rr->response.code == 0x0001) ? 0 : -EIO; |
975 | } | 977 | } |
976 | 978 | ||
979 | static struct { | ||
980 | struct chsc_header request; | ||
981 | u32 word1; | ||
982 | struct subchannel_id sid; | ||
983 | u32 word3; | ||
984 | struct chsc_header response; | ||
985 | u32 word[11]; | ||
986 | } __attribute__ ((packed)) siosl_area __attribute__ ((__aligned__(PAGE_SIZE))); | ||
987 | |||
988 | int chsc_siosl(struct subchannel_id schid) | ||
989 | { | ||
990 | unsigned long flags; | ||
991 | int ccode; | ||
992 | int rc; | ||
993 | |||
994 | spin_lock_irqsave(&siosl_lock, flags); | ||
995 | memset(&siosl_area, 0, sizeof(siosl_area)); | ||
996 | siosl_area.request.length = 0x0010; | ||
997 | siosl_area.request.code = 0x0046; | ||
998 | siosl_area.word1 = 0x80000000; | ||
999 | siosl_area.sid = schid; | ||
1000 | |||
1001 | ccode = chsc(&siosl_area); | ||
1002 | if (ccode > 0) { | ||
1003 | if (ccode == 3) | ||
1004 | rc = -ENODEV; | ||
1005 | else | ||
1006 | rc = -EBUSY; | ||
1007 | CIO_MSG_EVENT(2, "chsc: chsc failed for 0.%x.%04x (ccode=%d)\n", | ||
1008 | schid.ssid, schid.sch_no, ccode); | ||
1009 | goto out; | ||
1010 | } | ||
1011 | rc = chsc_error_from_response(siosl_area.response.code); | ||
1012 | if (rc) | ||
1013 | CIO_MSG_EVENT(2, "chsc: siosl failed for 0.%x.%04x (rc=%04x)\n", | ||
1014 | schid.ssid, schid.sch_no, | ||
1015 | siosl_area.response.code); | ||
1016 | else | ||
1017 | CIO_MSG_EVENT(4, "chsc: siosl succeeded for 0.%x.%04x\n", | ||
1018 | schid.ssid, schid.sch_no); | ||
1019 | out: | ||
1020 | spin_unlock_irqrestore(&siosl_lock, flags); | ||
1021 | |||
1022 | return rc; | ||
1023 | } | ||
1024 | EXPORT_SYMBOL_GPL(chsc_siosl); | ||
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 37aa611d4ac5..5453013f094b 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
@@ -80,4 +80,6 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp); | |||
80 | 80 | ||
81 | int chsc_error_from_response(int response); | 81 | int chsc_error_from_response(int response); |
82 | 82 | ||
83 | int chsc_siosl(struct subchannel_id schid); | ||
84 | |||
83 | #endif | 85 | #endif |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 6d229f3523a0..51bd3687d163 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "ioasm.h" | 36 | #include "ioasm.h" |
37 | #include "io_sch.h" | 37 | #include "io_sch.h" |
38 | #include "blacklist.h" | 38 | #include "blacklist.h" |
39 | #include "chsc.h" | ||
39 | 40 | ||
40 | static struct timer_list recovery_timer; | 41 | static struct timer_list recovery_timer; |
41 | static DEFINE_SPINLOCK(recovery_lock); | 42 | static DEFINE_SPINLOCK(recovery_lock); |
@@ -486,9 +487,11 @@ static int online_store_handle_offline(struct ccw_device *cdev) | |||
486 | spin_lock_irq(cdev->ccwlock); | 487 | spin_lock_irq(cdev->ccwlock); |
487 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG_EVAL); | 488 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG_EVAL); |
488 | spin_unlock_irq(cdev->ccwlock); | 489 | spin_unlock_irq(cdev->ccwlock); |
489 | } else if (cdev->online && cdev->drv && cdev->drv->set_offline) | 490 | return 0; |
491 | } | ||
492 | if (cdev->drv && cdev->drv->set_offline) | ||
490 | return ccw_device_set_offline(cdev); | 493 | return ccw_device_set_offline(cdev); |
491 | return 0; | 494 | return -EINVAL; |
492 | } | 495 | } |
493 | 496 | ||
494 | static int online_store_recog_and_online(struct ccw_device *cdev) | 497 | static int online_store_recog_and_online(struct ccw_device *cdev) |
@@ -505,8 +508,8 @@ static int online_store_recog_and_online(struct ccw_device *cdev) | |||
505 | return -EAGAIN; | 508 | return -EAGAIN; |
506 | } | 509 | } |
507 | if (cdev->drv && cdev->drv->set_online) | 510 | if (cdev->drv && cdev->drv->set_online) |
508 | ccw_device_set_online(cdev); | 511 | return ccw_device_set_online(cdev); |
509 | return 0; | 512 | return -EINVAL; |
510 | } | 513 | } |
511 | 514 | ||
512 | static int online_store_handle_online(struct ccw_device *cdev, int force) | 515 | static int online_store_handle_online(struct ccw_device *cdev, int force) |
@@ -598,6 +601,25 @@ available_show (struct device *dev, struct device_attribute *attr, char *buf) | |||
598 | } | 601 | } |
599 | } | 602 | } |
600 | 603 | ||
604 | static ssize_t | ||
605 | initiate_logging(struct device *dev, struct device_attribute *attr, | ||
606 | const char *buf, size_t count) | ||
607 | { | ||
608 | struct subchannel *sch = to_subchannel(dev); | ||
609 | int rc; | ||
610 | |||
611 | rc = chsc_siosl(sch->schid); | ||
612 | if (rc < 0) { | ||
613 | pr_warning("Logging for subchannel 0.%x.%04x failed with " | ||
614 | "errno=%d\n", | ||
615 | sch->schid.ssid, sch->schid.sch_no, rc); | ||
616 | return rc; | ||
617 | } | ||
618 | pr_notice("Logging for subchannel 0.%x.%04x was triggered\n", | ||
619 | sch->schid.ssid, sch->schid.sch_no); | ||
620 | return count; | ||
621 | } | ||
622 | |||
601 | static DEVICE_ATTR(chpids, 0444, chpids_show, NULL); | 623 | static DEVICE_ATTR(chpids, 0444, chpids_show, NULL); |
602 | static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL); | 624 | static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL); |
603 | static DEVICE_ATTR(devtype, 0444, devtype_show, NULL); | 625 | static DEVICE_ATTR(devtype, 0444, devtype_show, NULL); |
@@ -605,10 +627,12 @@ static DEVICE_ATTR(cutype, 0444, cutype_show, NULL); | |||
605 | static DEVICE_ATTR(modalias, 0444, modalias_show, NULL); | 627 | static DEVICE_ATTR(modalias, 0444, modalias_show, NULL); |
606 | static DEVICE_ATTR(online, 0644, online_show, online_store); | 628 | static DEVICE_ATTR(online, 0644, online_show, online_store); |
607 | static DEVICE_ATTR(availability, 0444, available_show, NULL); | 629 | static DEVICE_ATTR(availability, 0444, available_show, NULL); |
630 | static DEVICE_ATTR(logging, 0200, NULL, initiate_logging); | ||
608 | 631 | ||
609 | static struct attribute *io_subchannel_attrs[] = { | 632 | static struct attribute *io_subchannel_attrs[] = { |
610 | &dev_attr_chpids.attr, | 633 | &dev_attr_chpids.attr, |
611 | &dev_attr_pimpampom.attr, | 634 | &dev_attr_pimpampom.attr, |
635 | &dev_attr_logging.attr, | ||
612 | NULL, | 636 | NULL, |
613 | }; | 637 | }; |
614 | 638 | ||
@@ -2036,6 +2060,21 @@ void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo) | |||
2036 | } | 2060 | } |
2037 | } | 2061 | } |
2038 | 2062 | ||
2063 | /** | ||
2064 | * ccw_device_siosl() - initiate logging | ||
2065 | * @cdev: ccw device | ||
2066 | * | ||
2067 | * This function is used to invoke model-dependent logging within the channel | ||
2068 | * subsystem. | ||
2069 | */ | ||
2070 | int ccw_device_siosl(struct ccw_device *cdev) | ||
2071 | { | ||
2072 | struct subchannel *sch = to_subchannel(cdev->dev.parent); | ||
2073 | |||
2074 | return chsc_siosl(sch->schid); | ||
2075 | } | ||
2076 | EXPORT_SYMBOL_GPL(ccw_device_siosl); | ||
2077 | |||
2039 | MODULE_LICENSE("GPL"); | 2078 | MODULE_LICENSE("GPL"); |
2040 | EXPORT_SYMBOL(ccw_device_set_online); | 2079 | EXPORT_SYMBOL(ccw_device_set_online); |
2041 | EXPORT_SYMBOL(ccw_device_set_offline); | 2080 | EXPORT_SYMBOL(ccw_device_set_offline); |
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c index 6facb5499a65..82a5ad0d63f6 100644 --- a/drivers/s390/cio/device_pgid.c +++ b/drivers/s390/cio/device_pgid.c | |||
@@ -208,6 +208,7 @@ static void spid_start(struct ccw_device *cdev) | |||
208 | req->timeout = PGID_TIMEOUT; | 208 | req->timeout = PGID_TIMEOUT; |
209 | req->maxretries = PGID_RETRIES; | 209 | req->maxretries = PGID_RETRIES; |
210 | req->lpm = 0x80; | 210 | req->lpm = 0x80; |
211 | req->singlepath = 1; | ||
211 | req->callback = spid_callback; | 212 | req->callback = spid_callback; |
212 | spid_do(cdev); | 213 | spid_do(cdev); |
213 | } | 214 | } |
@@ -420,6 +421,7 @@ static void verify_start(struct ccw_device *cdev) | |||
420 | req->timeout = PGID_TIMEOUT; | 421 | req->timeout = PGID_TIMEOUT; |
421 | req->maxretries = PGID_RETRIES; | 422 | req->maxretries = PGID_RETRIES; |
422 | req->lpm = 0x80; | 423 | req->lpm = 0x80; |
424 | req->singlepath = 1; | ||
423 | if (cdev->private->flags.pgroup) { | 425 | if (cdev->private->flags.pgroup) { |
424 | CIO_TRACE_EVENT(4, "snid"); | 426 | CIO_TRACE_EVENT(4, "snid"); |
425 | CIO_HEX_EVENT(4, devid, sizeof(*devid)); | 427 | CIO_HEX_EVENT(4, devid, sizeof(*devid)); |
@@ -507,6 +509,7 @@ void ccw_device_disband_start(struct ccw_device *cdev) | |||
507 | req->timeout = PGID_TIMEOUT; | 509 | req->timeout = PGID_TIMEOUT; |
508 | req->maxretries = PGID_RETRIES; | 510 | req->maxretries = PGID_RETRIES; |
509 | req->lpm = sch->schib.pmcw.pam & sch->opm; | 511 | req->lpm = sch->schib.pmcw.pam & sch->opm; |
512 | req->singlepath = 1; | ||
510 | req->callback = disband_callback; | 513 | req->callback = disband_callback; |
511 | fn = SPID_FUNC_DISBAND; | 514 | fn = SPID_FUNC_DISBAND; |
512 | if (cdev->private->flags.mpath) | 515 | if (cdev->private->flags.mpath) |
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h index b9ce712a7f25..469ef93f2302 100644 --- a/drivers/s390/cio/io_sch.h +++ b/drivers/s390/cio/io_sch.h | |||
@@ -92,11 +92,12 @@ enum io_status { | |||
92 | * @filter: optional callback to adjust request status based on IRB data | 92 | * @filter: optional callback to adjust request status based on IRB data |
93 | * @callback: final callback | 93 | * @callback: final callback |
94 | * @data: user-defined pointer passed to all callbacks | 94 | * @data: user-defined pointer passed to all callbacks |
95 | * @singlepath: if set, use only one path from @lpm per start I/O | ||
96 | * @cancel: non-zero if request was cancelled | ||
97 | * @done: non-zero if request was finished | ||
95 | * @mask: current path mask | 98 | * @mask: current path mask |
96 | * @retries: current number of retries | 99 | * @retries: current number of retries |
97 | * @drc: delayed return code | 100 | * @drc: delayed return code |
98 | * @cancel: non-zero if request was cancelled | ||
99 | * @done: non-zero if request was finished | ||
100 | */ | 101 | */ |
101 | struct ccw_request { | 102 | struct ccw_request { |
102 | struct ccw1 *cp; | 103 | struct ccw1 *cp; |
@@ -108,12 +109,13 @@ struct ccw_request { | |||
108 | enum io_status); | 109 | enum io_status); |
109 | void (*callback)(struct ccw_device *, void *, int); | 110 | void (*callback)(struct ccw_device *, void *, int); |
110 | void *data; | 111 | void *data; |
112 | unsigned int singlepath:1; | ||
111 | /* These fields are used internally. */ | 113 | /* These fields are used internally. */ |
114 | unsigned int cancel:1; | ||
115 | unsigned int done:1; | ||
112 | u16 mask; | 116 | u16 mask; |
113 | u16 retries; | 117 | u16 retries; |
114 | int drc; | 118 | int drc; |
115 | int cancel:1; | ||
116 | int done:1; | ||
117 | } __attribute__((packed)); | 119 | } __attribute__((packed)); |
118 | 120 | ||
119 | /* | 121 | /* |
diff --git a/drivers/s390/net/smsgiucv_app.c b/drivers/s390/net/smsgiucv_app.c index 137688790207..4d2ea4000422 100644 --- a/drivers/s390/net/smsgiucv_app.c +++ b/drivers/s390/net/smsgiucv_app.c | |||
@@ -180,6 +180,13 @@ static int __init smsgiucv_app_init(void) | |||
180 | goto fail_put_driver; | 180 | goto fail_put_driver; |
181 | } | 181 | } |
182 | 182 | ||
183 | /* convert sender to uppercase characters */ | ||
184 | if (sender) { | ||
185 | int len = strlen(sender); | ||
186 | while (len--) | ||
187 | sender[len] = toupper(sender[len]); | ||
188 | } | ||
189 | |||
183 | /* register with the smsgiucv device driver */ | 190 | /* register with the smsgiucv device driver */ |
184 | rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); | 191 | rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); |
185 | if (rc) { | 192 | if (rc) { |
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 8681f1345056..d89aa38c5cf0 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c | |||
@@ -216,7 +216,7 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios, | |||
216 | struct ktermios *old) | 216 | struct ktermios *old) |
217 | { | 217 | { |
218 | unsigned long flags; | 218 | unsigned long flags; |
219 | unsigned int baud, quot, h_lcr; | 219 | unsigned int baud, quot, h_lcr, b; |
220 | 220 | ||
221 | /* | 221 | /* |
222 | * We don't support modem control lines. | 222 | * We don't support modem control lines. |
@@ -234,12 +234,8 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios, | |||
234 | */ | 234 | */ |
235 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); | 235 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); |
236 | quot = uart_get_divisor(port, baud); | 236 | quot = uart_get_divisor(port, baud); |
237 | 237 | b = port->uartclk / (16 * quot); | |
238 | if (port->state && port->state->port.tty) { | 238 | tty_termios_encode_baud_rate(termios, b, b); |
239 | struct tty_struct *tty = port->state->port.tty; | ||
240 | unsigned int b = port->uartclk / (16 * quot); | ||
241 | tty_encode_baud_rate(tty, b, b); | ||
242 | } | ||
243 | 239 | ||
244 | switch (termios->c_cflag & CSIZE) { | 240 | switch (termios->c_cflag & CSIZE) { |
245 | case CS5: | 241 | case CS5: |
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 30463862603b..7356a56ac458 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -78,10 +78,6 @@ struct m68k_serial *m68k_consinfo = 0; | |||
78 | 78 | ||
79 | #define M68K_CLOCK (16667000) /* FIXME: 16MHz is likely wrong */ | 79 | #define M68K_CLOCK (16667000) /* FIXME: 16MHz is likely wrong */ |
80 | 80 | ||
81 | #ifdef CONFIG_CONSOLE | ||
82 | extern wait_queue_head_t keypress_wait; | ||
83 | #endif | ||
84 | |||
85 | struct tty_driver *serial_driver; | 81 | struct tty_driver *serial_driver; |
86 | 82 | ||
87 | /* number of characters left in xmit buffer before we ask for more */ | 83 | /* number of characters left in xmit buffer before we ask for more */ |
@@ -102,19 +98,13 @@ static void change_speed(struct m68k_serial *info); | |||
102 | * Setup for console. Argument comes from the boot command line. | 98 | * Setup for console. Argument comes from the boot command line. |
103 | */ | 99 | */ |
104 | 100 | ||
105 | #if defined(CONFIG_M68EZ328ADS) || defined(CONFIG_ALMA_ANS) || defined(CONFIG_DRAGONIXVZ) | 101 | /* note: this is messy, but it works, again, perhaps defined somewhere else?*/ |
106 | #define CONSOLE_BAUD_RATE 115200 | 102 | #ifdef CONFIG_M68VZ328 |
107 | #define DEFAULT_CBAUD B115200 | 103 | #define CONSOLE_BAUD_RATE 19200 |
108 | #else | 104 | #define DEFAULT_CBAUD B19200 |
109 | /* (es) */ | ||
110 | /* note: this is messy, but it works, again, perhaps defined somewhere else?*/ | ||
111 | #ifdef CONFIG_M68VZ328 | ||
112 | #define CONSOLE_BAUD_RATE 19200 | ||
113 | #define DEFAULT_CBAUD B19200 | ||
114 | #endif | ||
115 | /* (/es) */ | ||
116 | #endif | 105 | #endif |
117 | 106 | ||
107 | |||
118 | #ifndef CONSOLE_BAUD_RATE | 108 | #ifndef CONSOLE_BAUD_RATE |
119 | #define CONSOLE_BAUD_RATE 9600 | 109 | #define CONSOLE_BAUD_RATE 9600 |
120 | #define DEFAULT_CBAUD B9600 | 110 | #define DEFAULT_CBAUD B9600 |
@@ -300,10 +290,6 @@ static void receive_chars(struct m68k_serial *info, unsigned short rx) | |||
300 | return; | 290 | return; |
301 | #endif /* CONFIG_MAGIC_SYSRQ */ | 291 | #endif /* CONFIG_MAGIC_SYSRQ */ |
302 | } | 292 | } |
303 | /* It is a 'keyboard interrupt' ;-) */ | ||
304 | #ifdef CONFIG_CONSOLE | ||
305 | wake_up(&keypress_wait); | ||
306 | #endif | ||
307 | } | 293 | } |
308 | 294 | ||
309 | if(!tty) | 295 | if(!tty) |
@@ -1243,7 +1229,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1243 | retval = -ERESTARTSYS; | 1229 | retval = -ERESTARTSYS; |
1244 | break; | 1230 | break; |
1245 | } | 1231 | } |
1232 | tty_unlock(); | ||
1246 | schedule(); | 1233 | schedule(); |
1234 | tty_lock(); | ||
1247 | } | 1235 | } |
1248 | current->state = TASK_RUNNING; | 1236 | current->state = TASK_RUNNING; |
1249 | remove_wait_queue(&info->open_wait, &wait); | 1237 | remove_wait_queue(&info->open_wait, &wait); |
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 768612f8e41e..0dff3bbddc8b 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c | |||
@@ -1705,7 +1705,6 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1705 | printk("jiff=%lu...", jiffies); | 1705 | printk("jiff=%lu...", jiffies); |
1706 | #endif | 1706 | #endif |
1707 | 1707 | ||
1708 | lock_kernel(); | ||
1709 | /* We go through the loop at least once because we can't tell | 1708 | /* We go through the loop at least once because we can't tell |
1710 | * exactly when the last character exits the shifter. There can | 1709 | * exactly when the last character exits the shifter. There can |
1711 | * be at least two characters waiting to be sent after the buffers | 1710 | * be at least two characters waiting to be sent after the buffers |
@@ -1734,7 +1733,6 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1734 | bdp--; | 1733 | bdp--; |
1735 | } while (bdp->status & BD_SC_READY); | 1734 | } while (bdp->status & BD_SC_READY); |
1736 | current->state = TASK_RUNNING; | 1735 | current->state = TASK_RUNNING; |
1737 | unlock_kernel(); | ||
1738 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 1736 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
1739 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | 1737 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); |
1740 | #endif | 1738 | #endif |
@@ -1862,7 +1860,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1862 | printk("block_til_ready blocking: ttys%d, count = %d\n", | 1860 | printk("block_til_ready blocking: ttys%d, count = %d\n", |
1863 | info->line, state->count); | 1861 | info->line, state->count); |
1864 | #endif | 1862 | #endif |
1863 | tty_unlock(); | ||
1865 | schedule(); | 1864 | schedule(); |
1865 | tty_lock(); | ||
1866 | } | 1866 | } |
1867 | current->state = TASK_RUNNING; | 1867 | current->state = TASK_RUNNING; |
1868 | remove_wait_queue(&info->open_wait, &wait); | 1868 | remove_wait_queue(&info->open_wait, &wait); |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 09ef57034c9c..24110f6f61e0 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -241,7 +241,7 @@ static const struct serial8250_config uart_config[] = { | |||
241 | .fifo_size = 128, | 241 | .fifo_size = 128, |
242 | .tx_loadsz = 128, | 242 | .tx_loadsz = 128, |
243 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | 243 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, |
244 | .flags = UART_CAP_FIFO, | 244 | .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, |
245 | }, | 245 | }, |
246 | [PORT_16654] = { | 246 | [PORT_16654] = { |
247 | .name = "ST16654", | 247 | .name = "ST16654", |
@@ -300,6 +300,13 @@ static const struct serial8250_config uart_config[] = { | |||
300 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, | 300 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, |
301 | .flags = UART_CAP_FIFO | UART_CAP_AFE, | 301 | .flags = UART_CAP_FIFO | UART_CAP_AFE, |
302 | }, | 302 | }, |
303 | [PORT_U6_16550A] = { | ||
304 | .name = "U6_16550A", | ||
305 | .fifo_size = 64, | ||
306 | .tx_loadsz = 64, | ||
307 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | ||
308 | .flags = UART_CAP_FIFO | UART_CAP_AFE, | ||
309 | }, | ||
303 | }; | 310 | }; |
304 | 311 | ||
305 | #if defined(CONFIG_MIPS_ALCHEMY) | 312 | #if defined(CONFIG_MIPS_ALCHEMY) |
@@ -1070,6 +1077,15 @@ static void autoconfig_16550a(struct uart_8250_port *up) | |||
1070 | DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); | 1077 | DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); |
1071 | } | 1078 | } |
1072 | serial_outp(up, UART_IER, iersave); | 1079 | serial_outp(up, UART_IER, iersave); |
1080 | |||
1081 | /* | ||
1082 | * We distinguish between 16550A and U6 16550A by counting | ||
1083 | * how many bytes are in the FIFO. | ||
1084 | */ | ||
1085 | if (up->port.type == PORT_16550A && size_fifo(up) == 64) { | ||
1086 | up->port.type = PORT_U6_16550A; | ||
1087 | up->capabilities |= UART_CAP_AFE; | ||
1088 | } | ||
1073 | } | 1089 | } |
1074 | 1090 | ||
1075 | /* | 1091 | /* |
@@ -2224,9 +2240,9 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int | |||
2224 | return quot; | 2240 | return quot; |
2225 | } | 2241 | } |
2226 | 2242 | ||
2227 | static void | 2243 | void |
2228 | serial8250_set_termios(struct uart_port *port, struct ktermios *termios, | 2244 | serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, |
2229 | struct ktermios *old) | 2245 | struct ktermios *old) |
2230 | { | 2246 | { |
2231 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 2247 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
2232 | unsigned char cval, fcr = 0; | 2248 | unsigned char cval, fcr = 0; |
@@ -2402,16 +2418,22 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, | |||
2402 | if (tty_termios_baud_rate(termios)) | 2418 | if (tty_termios_baud_rate(termios)) |
2403 | tty_termios_encode_baud_rate(termios, baud, baud); | 2419 | tty_termios_encode_baud_rate(termios, baud, baud); |
2404 | } | 2420 | } |
2421 | EXPORT_SYMBOL(serial8250_do_set_termios); | ||
2405 | 2422 | ||
2406 | static void | 2423 | static void |
2407 | serial8250_set_ldisc(struct uart_port *port) | 2424 | serial8250_set_termios(struct uart_port *port, struct ktermios *termios, |
2425 | struct ktermios *old) | ||
2408 | { | 2426 | { |
2409 | int line = port->line; | 2427 | if (port->set_termios) |
2410 | 2428 | port->set_termios(port, termios, old); | |
2411 | if (line >= port->state->port.tty->driver->num) | 2429 | else |
2412 | return; | 2430 | serial8250_do_set_termios(port, termios, old); |
2431 | } | ||
2413 | 2432 | ||
2414 | if (port->state->port.tty->ldisc->ops->num == N_PPS) { | 2433 | static void |
2434 | serial8250_set_ldisc(struct uart_port *port, int new) | ||
2435 | { | ||
2436 | if (new == N_PPS) { | ||
2415 | port->flags |= UPF_HARDPPS_CD; | 2437 | port->flags |= UPF_HARDPPS_CD; |
2416 | serial8250_enable_ms(port); | 2438 | serial8250_enable_ms(port); |
2417 | } else | 2439 | } else |
@@ -2987,6 +3009,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
2987 | port.type = p->type; | 3009 | port.type = p->type; |
2988 | port.serial_in = p->serial_in; | 3010 | port.serial_in = p->serial_in; |
2989 | port.serial_out = p->serial_out; | 3011 | port.serial_out = p->serial_out; |
3012 | port.set_termios = p->set_termios; | ||
2990 | port.dev = &dev->dev; | 3013 | port.dev = &dev->dev; |
2991 | port.irqflags |= irqflag; | 3014 | port.irqflags |= irqflag; |
2992 | ret = serial8250_register_port(&port); | 3015 | ret = serial8250_register_port(&port); |
@@ -3150,6 +3173,9 @@ int serial8250_register_port(struct uart_port *port) | |||
3150 | uart->port.serial_in = port->serial_in; | 3173 | uart->port.serial_in = port->serial_in; |
3151 | if (port->serial_out) | 3174 | if (port->serial_out) |
3152 | uart->port.serial_out = port->serial_out; | 3175 | uart->port.serial_out = port->serial_out; |
3176 | /* Possibly override set_termios call */ | ||
3177 | if (port->set_termios) | ||
3178 | uart->port.set_termios = port->set_termios; | ||
3153 | 3179 | ||
3154 | ret = uart_add_one_port(&serial8250_reg, &uart->port); | 3180 | ret = uart_add_one_port(&serial8250_reg, &uart->port); |
3155 | if (ret == 0) | 3181 | if (ret == 0) |
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c index f279745e9fef..b745792ec25a 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c | |||
@@ -19,9 +19,11 @@ | |||
19 | * The user can specify the device directly, e.g., | 19 | * The user can specify the device directly, e.g., |
20 | * earlycon=uart8250,io,0x3f8,9600n8 | 20 | * earlycon=uart8250,io,0x3f8,9600n8 |
21 | * earlycon=uart8250,mmio,0xff5e0000,115200n8 | 21 | * earlycon=uart8250,mmio,0xff5e0000,115200n8 |
22 | * earlycon=uart8250,mmio32,0xff5e0000,115200n8 | ||
22 | * or | 23 | * or |
23 | * console=uart8250,io,0x3f8,9600n8 | 24 | * console=uart8250,io,0x3f8,9600n8 |
24 | * console=uart8250,mmio,0xff5e0000,115200n8 | 25 | * console=uart8250,mmio,0xff5e0000,115200n8 |
26 | * console=uart8250,mmio32,0xff5e0000,115200n8 | ||
25 | */ | 27 | */ |
26 | 28 | ||
27 | #include <linux/tty.h> | 29 | #include <linux/tty.h> |
@@ -48,18 +50,31 @@ static struct early_serial8250_device early_device; | |||
48 | 50 | ||
49 | static unsigned int __init serial_in(struct uart_port *port, int offset) | 51 | static unsigned int __init serial_in(struct uart_port *port, int offset) |
50 | { | 52 | { |
51 | if (port->iotype == UPIO_MEM) | 53 | switch (port->iotype) { |
54 | case UPIO_MEM: | ||
52 | return readb(port->membase + offset); | 55 | return readb(port->membase + offset); |
53 | else | 56 | case UPIO_MEM32: |
57 | return readl(port->membase + (offset << 2)); | ||
58 | case UPIO_PORT: | ||
54 | return inb(port->iobase + offset); | 59 | return inb(port->iobase + offset); |
60 | default: | ||
61 | return 0; | ||
62 | } | ||
55 | } | 63 | } |
56 | 64 | ||
57 | static void __init serial_out(struct uart_port *port, int offset, int value) | 65 | static void __init serial_out(struct uart_port *port, int offset, int value) |
58 | { | 66 | { |
59 | if (port->iotype == UPIO_MEM) | 67 | switch (port->iotype) { |
68 | case UPIO_MEM: | ||
60 | writeb(value, port->membase + offset); | 69 | writeb(value, port->membase + offset); |
61 | else | 70 | break; |
71 | case UPIO_MEM32: | ||
72 | writel(value, port->membase + (offset << 2)); | ||
73 | break; | ||
74 | case UPIO_PORT: | ||
62 | outb(value, port->iobase + offset); | 75 | outb(value, port->iobase + offset); |
76 | break; | ||
77 | } | ||
63 | } | 78 | } |
64 | 79 | ||
65 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) | 80 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) |
@@ -137,15 +152,21 @@ static int __init parse_options(struct early_serial8250_device *device, | |||
137 | char *options) | 152 | char *options) |
138 | { | 153 | { |
139 | struct uart_port *port = &device->port; | 154 | struct uart_port *port = &device->port; |
140 | int mmio, length; | 155 | int mmio, mmio32, length; |
141 | 156 | ||
142 | if (!options) | 157 | if (!options) |
143 | return -ENODEV; | 158 | return -ENODEV; |
144 | 159 | ||
145 | port->uartclk = BASE_BAUD * 16; | 160 | port->uartclk = BASE_BAUD * 16; |
146 | if (!strncmp(options, "mmio,", 5)) { | 161 | |
147 | port->iotype = UPIO_MEM; | 162 | mmio = !strncmp(options, "mmio,", 5); |
148 | port->mapbase = simple_strtoul(options + 5, &options, 0); | 163 | mmio32 = !strncmp(options, "mmio32,", 7); |
164 | if (mmio || mmio32) { | ||
165 | port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32); | ||
166 | port->mapbase = simple_strtoul(options + (mmio ? 5 : 7), | ||
167 | &options, 0); | ||
168 | if (mmio32) | ||
169 | port->regshift = 2; | ||
149 | #ifdef CONFIG_FIX_EARLYCON_MEM | 170 | #ifdef CONFIG_FIX_EARLYCON_MEM |
150 | set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, | 171 | set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, |
151 | port->mapbase & PAGE_MASK); | 172 | port->mapbase & PAGE_MASK); |
@@ -157,11 +178,10 @@ static int __init parse_options(struct early_serial8250_device *device, | |||
157 | if (!port->membase) { | 178 | if (!port->membase) { |
158 | printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n", | 179 | printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n", |
159 | __func__, | 180 | __func__, |
160 | (unsigned long long)port->mapbase); | 181 | (unsigned long long) port->mapbase); |
161 | return -ENOMEM; | 182 | return -ENOMEM; |
162 | } | 183 | } |
163 | #endif | 184 | #endif |
164 | mmio = 1; | ||
165 | } else if (!strncmp(options, "io,", 3)) { | 185 | } else if (!strncmp(options, "io,", 3)) { |
166 | port->iotype = UPIO_PORT; | 186 | port->iotype = UPIO_PORT; |
167 | port->iobase = simple_strtoul(options + 3, &options, 0); | 187 | port->iobase = simple_strtoul(options + 3, &options, 0); |
@@ -181,11 +201,18 @@ static int __init parse_options(struct early_serial8250_device *device, | |||
181 | device->baud); | 201 | device->baud); |
182 | } | 202 | } |
183 | 203 | ||
184 | printk(KERN_INFO "Early serial console at %s 0x%llx (options '%s')\n", | 204 | if (mmio || mmio32) |
185 | mmio ? "MMIO" : "I/O port", | 205 | printk(KERN_INFO |
186 | mmio ? (unsigned long long) port->mapbase | 206 | "Early serial console at MMIO%s 0x%llu (options '%s')\n", |
187 | : (unsigned long long) port->iobase, | 207 | mmio32 ? "32" : "", |
188 | device->options); | 208 | (unsigned long long)port->mapbase, |
209 | device->options); | ||
210 | else | ||
211 | printk(KERN_INFO | ||
212 | "Early serial console at I/O port 0x%lu (options '%s')\n", | ||
213 | port->iobase, | ||
214 | device->options); | ||
215 | |||
189 | return 0; | 216 | return 0; |
190 | } | 217 | } |
191 | 218 | ||
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 746a44621d91..53be4d35a0aa 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c | |||
@@ -994,6 +994,7 @@ static int skip_tx_en_setup(struct serial_private *priv, | |||
994 | #define PCI_DEVICE_ID_TITAN_800E 0xA014 | 994 | #define PCI_DEVICE_ID_TITAN_800E 0xA014 |
995 | #define PCI_DEVICE_ID_TITAN_200EI 0xA016 | 995 | #define PCI_DEVICE_ID_TITAN_200EI 0xA016 |
996 | #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 | 996 | #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 |
997 | #define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538 | ||
997 | 998 | ||
998 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ | 999 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ |
999 | #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 | 1000 | #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 |
@@ -1542,6 +1543,8 @@ enum pci_board_num_t { | |||
1542 | pbn_b2_4_921600, | 1543 | pbn_b2_4_921600, |
1543 | pbn_b2_8_921600, | 1544 | pbn_b2_8_921600, |
1544 | 1545 | ||
1546 | pbn_b2_8_1152000, | ||
1547 | |||
1545 | pbn_b2_bt_1_115200, | 1548 | pbn_b2_bt_1_115200, |
1546 | pbn_b2_bt_2_115200, | 1549 | pbn_b2_bt_2_115200, |
1547 | pbn_b2_bt_4_115200, | 1550 | pbn_b2_bt_4_115200, |
@@ -1960,6 +1963,13 @@ static struct pciserial_board pci_boards[] __devinitdata = { | |||
1960 | .uart_offset = 8, | 1963 | .uart_offset = 8, |
1961 | }, | 1964 | }, |
1962 | 1965 | ||
1966 | [pbn_b2_8_1152000] = { | ||
1967 | .flags = FL_BASE2, | ||
1968 | .num_ports = 8, | ||
1969 | .base_baud = 1152000, | ||
1970 | .uart_offset = 8, | ||
1971 | }, | ||
1972 | |||
1963 | [pbn_b2_bt_1_115200] = { | 1973 | [pbn_b2_bt_1_115200] = { |
1964 | .flags = FL_BASE2|FL_BASE_BARS, | 1974 | .flags = FL_BASE2|FL_BASE_BARS, |
1965 | .num_ports = 1, | 1975 | .num_ports = 1, |
@@ -2875,6 +2885,9 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
2875 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952, | 2885 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952, |
2876 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 2886 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
2877 | pbn_b0_bt_2_921600 }, | 2887 | pbn_b0_bt_2_921600 }, |
2888 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958, | ||
2889 | PCI_ANY_ID , PCI_ANY_ID, 0, 0, | ||
2890 | pbn_b2_8_1152000 }, | ||
2878 | 2891 | ||
2879 | /* | 2892 | /* |
2880 | * Oxford Semiconductor Inc. Tornado PCI express device range. | 2893 | * Oxford Semiconductor Inc. Tornado PCI express device range. |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index e437ce8c1748..a22e60c06f48 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -542,6 +542,7 @@ config SERIAL_S5PV210 | |||
542 | help | 542 | help |
543 | Serial port support for Samsung's S5P Family of SoC's | 543 | Serial port support for Samsung's S5P Family of SoC's |
544 | 544 | ||
545 | |||
545 | config SERIAL_MAX3100 | 546 | config SERIAL_MAX3100 |
546 | tristate "MAX3100 support" | 547 | tristate "MAX3100 support" |
547 | depends on SPI | 548 | depends on SPI |
@@ -549,6 +550,22 @@ config SERIAL_MAX3100 | |||
549 | help | 550 | help |
550 | MAX3100 chip support | 551 | MAX3100 chip support |
551 | 552 | ||
553 | config SERIAL_MAX3107 | ||
554 | tristate "MAX3107 support" | ||
555 | depends on SPI | ||
556 | select SERIAL_CORE | ||
557 | help | ||
558 | MAX3107 chip support | ||
559 | |||
560 | config SERIAL_MAX3107_AAVA | ||
561 | tristate "MAX3107 AAVA platform support" | ||
562 | depends on X86_MRST && SERIAL_MAX3107 && GPIOLIB | ||
563 | select SERIAL_CORE | ||
564 | help | ||
565 | Support for the MAX3107 chip configuration found on the AAVA | ||
566 | platform. Includes the extra initialisation and GPIO support | ||
567 | neded for this device. | ||
568 | |||
552 | config SERIAL_DZ | 569 | config SERIAL_DZ |
553 | bool "DECstation DZ serial driver" | 570 | bool "DECstation DZ serial driver" |
554 | depends on MACH_DECSTATION && 32BIT | 571 | depends on MACH_DECSTATION && 32BIT |
@@ -690,6 +707,33 @@ config SERIAL_SA1100_CONSOLE | |||
690 | your boot loader (lilo or loadlin) about how to pass options to the | 707 | your boot loader (lilo or loadlin) about how to pass options to the |
691 | kernel at boot time.) | 708 | kernel at boot time.) |
692 | 709 | ||
710 | config SERIAL_MRST_MAX3110 | ||
711 | tristate "SPI UART driver for Max3110" | ||
712 | depends on SPI_DW_PCI | ||
713 | select SERIAL_CORE | ||
714 | select SERIAL_CORE_CONSOLE | ||
715 | help | ||
716 | This is the UART protocol driver for the MAX3110 device on | ||
717 | the Intel Moorestown platform. On other systems use the max3100 | ||
718 | driver. | ||
719 | |||
720 | config MRST_MAX3110_IRQ | ||
721 | boolean "Enable GPIO IRQ for Max3110 over Moorestown" | ||
722 | default n | ||
723 | depends on SERIAL_MRST_MAX3110 && GPIO_LANGWELL | ||
724 | help | ||
725 | This has to be enabled after Moorestown GPIO driver is loaded | ||
726 | |||
727 | config SERIAL_MFD_HSU | ||
728 | tristate "Medfield High Speed UART support" | ||
729 | depends on PCI | ||
730 | select SERIAL_CORE | ||
731 | |||
732 | config SERIAL_MFD_HSU_CONSOLE | ||
733 | boolean "Medfile HSU serial console support" | ||
734 | depends on SERIAL_MFD_HSU=y | ||
735 | select SERIAL_CORE_CONSOLE | ||
736 | |||
693 | config SERIAL_BFIN | 737 | config SERIAL_BFIN |
694 | tristate "Blackfin serial port support" | 738 | tristate "Blackfin serial port support" |
695 | depends on BLACKFIN | 739 | depends on BLACKFIN |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 208a85572c32..1ca4fd599ffe 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
@@ -46,6 +46,8 @@ obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o | |||
46 | obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o | 46 | obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o |
47 | obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o | 47 | obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o |
48 | obj-$(CONFIG_SERIAL_MAX3100) += max3100.o | 48 | obj-$(CONFIG_SERIAL_MAX3100) += max3100.o |
49 | obj-$(CONFIG_SERIAL_MAX3107) += max3107.o | ||
50 | obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o | ||
49 | obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o | 51 | obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o |
50 | obj-$(CONFIG_SERIAL_MUX) += mux.o | 52 | obj-$(CONFIG_SERIAL_MUX) += mux.o |
51 | obj-$(CONFIG_SERIAL_68328) += 68328serial.o | 53 | obj-$(CONFIG_SERIAL_68328) += 68328serial.o |
@@ -84,3 +86,5 @@ obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o | |||
84 | obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o | 86 | obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o |
85 | obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o | 87 | obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o |
86 | obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o | 88 | obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o |
89 | obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o | ||
90 | obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o | ||
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c index 0f1189605d21..f8d8a00554da 100644 --- a/drivers/serial/altera_uart.c +++ b/drivers/serial/altera_uart.c | |||
@@ -394,7 +394,7 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp) | |||
394 | static void altera_uart_console_putc(struct uart_port *port, const char c) | 394 | static void altera_uart_console_putc(struct uart_port *port, const char c) |
395 | { | 395 | { |
396 | while (!(readl(port->membase + ALTERA_UART_STATUS_REG) & | 396 | while (!(readl(port->membase + ALTERA_UART_STATUS_REG) & |
397 | ALTERA_UART_STATUS_TRDY_MSK)) | 397 | ALTERA_UART_STATUS_TRDY_MSK)) |
398 | cpu_relax(); | 398 | cpu_relax(); |
399 | 399 | ||
400 | writel(c, port->membase + ALTERA_UART_TXDATA_REG); | 400 | writel(c, port->membase + ALTERA_UART_TXDATA_REG); |
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index a182def7007d..3892666b5fbd 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c | |||
@@ -217,7 +217,8 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) | |||
217 | if (rs485conf->flags & SER_RS485_ENABLED) { | 217 | if (rs485conf->flags & SER_RS485_ENABLED) { |
218 | dev_dbg(port->dev, "Setting UART to RS485\n"); | 218 | dev_dbg(port->dev, "Setting UART to RS485\n"); |
219 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; | 219 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; |
220 | UART_PUT_TTGR(port, rs485conf->delay_rts_before_send); | 220 | if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND) |
221 | UART_PUT_TTGR(port, rs485conf->delay_rts_after_send); | ||
221 | mode |= ATMEL_US_USMODE_RS485; | 222 | mode |= ATMEL_US_USMODE_RS485; |
222 | } else { | 223 | } else { |
223 | dev_dbg(port->dev, "Setting UART to RS232\n"); | 224 | dev_dbg(port->dev, "Setting UART to RS232\n"); |
@@ -292,7 +293,9 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) | |||
292 | 293 | ||
293 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | 294 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { |
294 | dev_dbg(port->dev, "Setting UART to RS485\n"); | 295 | dev_dbg(port->dev, "Setting UART to RS485\n"); |
295 | UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send); | 296 | if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND) |
297 | UART_PUT_TTGR(port, | ||
298 | atmel_port->rs485.delay_rts_after_send); | ||
296 | mode |= ATMEL_US_USMODE_RS485; | 299 | mode |= ATMEL_US_USMODE_RS485; |
297 | } else { | 300 | } else { |
298 | dev_dbg(port->dev, "Setting UART to RS232\n"); | 301 | dev_dbg(port->dev, "Setting UART to RS232\n"); |
@@ -1211,7 +1214,9 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1211 | 1214 | ||
1212 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | 1215 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { |
1213 | dev_dbg(port->dev, "Setting UART to RS485\n"); | 1216 | dev_dbg(port->dev, "Setting UART to RS485\n"); |
1214 | UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send); | 1217 | if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND) |
1218 | UART_PUT_TTGR(port, | ||
1219 | atmel_port->rs485.delay_rts_after_send); | ||
1215 | mode |= ATMEL_US_USMODE_RS485; | 1220 | mode |= ATMEL_US_USMODE_RS485; |
1216 | } else { | 1221 | } else { |
1217 | dev_dbg(port->dev, "Setting UART to RS232\n"); | 1222 | dev_dbg(port->dev, "Setting UART to RS232\n"); |
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 511cbf687877..a9eff2b18eab 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
@@ -957,15 +957,12 @@ bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
957 | * Enable the IrDA function if tty->ldisc.num is N_IRDA. | 957 | * Enable the IrDA function if tty->ldisc.num is N_IRDA. |
958 | * In other cases, disable IrDA function. | 958 | * In other cases, disable IrDA function. |
959 | */ | 959 | */ |
960 | static void bfin_serial_set_ldisc(struct uart_port *port) | 960 | static void bfin_serial_set_ldisc(struct uart_port *port, int ld) |
961 | { | 961 | { |
962 | int line = port->line; | 962 | int line = port->line; |
963 | unsigned short val; | 963 | unsigned short val; |
964 | 964 | ||
965 | if (line >= port->state->port.tty->driver->num) | 965 | switch (ld) { |
966 | return; | ||
967 | |||
968 | switch (port->state->port.tty->termios->c_line) { | ||
969 | case N_IRDA: | 966 | case N_IRDA: |
970 | val = UART_GET_GCTL(&bfin_serial_ports[line]); | 967 | val = UART_GET_GCTL(&bfin_serial_ports[line]); |
971 | val |= (IREN | RPOLC); | 968 | val |= (IREN | RPOLC); |
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 31f172397af3..c856905bb3bd 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c | |||
@@ -3724,6 +3724,17 @@ rs_ioctl(struct tty_struct *tty, struct file * file, | |||
3724 | return e100_enable_rs485(tty, &rs485data); | 3724 | return e100_enable_rs485(tty, &rs485data); |
3725 | } | 3725 | } |
3726 | 3726 | ||
3727 | case TIOCGRS485: | ||
3728 | { | ||
3729 | struct serial_rs485 *rs485data = | ||
3730 | &(((struct e100_serial *)tty->driver_data)->rs485); | ||
3731 | /* This is the ioctl to get RS485 data from user-space */ | ||
3732 | if (copy_to_user((struct serial_rs485 *) arg, | ||
3733 | rs485data, | ||
3734 | sizeof(serial_rs485))) | ||
3735 | return -EFAULT; | ||
3736 | break; | ||
3737 | } | ||
3727 | 3738 | ||
3728 | case TIOCSERWRRS485: | 3739 | case TIOCSERWRRS485: |
3729 | { | 3740 | { |
@@ -3924,7 +3935,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
3924 | * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO | 3935 | * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO |
3925 | * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k) | 3936 | * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k) |
3926 | */ | 3937 | */ |
3927 | lock_kernel(); | ||
3928 | orig_jiffies = jiffies; | 3938 | orig_jiffies = jiffies; |
3929 | while (info->xmit.head != info->xmit.tail || /* More in send queue */ | 3939 | while (info->xmit.head != info->xmit.tail || /* More in send queue */ |
3930 | (*info->ostatusadr & 0x007f) || /* more in FIFO */ | 3940 | (*info->ostatusadr & 0x007f) || /* more in FIFO */ |
@@ -3941,7 +3951,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
3941 | curr_time_usec - info->last_tx_active_usec; | 3951 | curr_time_usec - info->last_tx_active_usec; |
3942 | } | 3952 | } |
3943 | set_current_state(TASK_RUNNING); | 3953 | set_current_state(TASK_RUNNING); |
3944 | unlock_kernel(); | ||
3945 | } | 3954 | } |
3946 | 3955 | ||
3947 | /* | 3956 | /* |
@@ -3981,7 +3990,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, | |||
3981 | */ | 3990 | */ |
3982 | if (tty_hung_up_p(filp) || | 3991 | if (tty_hung_up_p(filp) || |
3983 | (info->flags & ASYNC_CLOSING)) { | 3992 | (info->flags & ASYNC_CLOSING)) { |
3984 | wait_event_interruptible(info->close_wait, | 3993 | wait_event_interruptible_tty(info->close_wait, |
3985 | !(info->flags & ASYNC_CLOSING)); | 3994 | !(info->flags & ASYNC_CLOSING)); |
3986 | #ifdef SERIAL_DO_RESTART | 3995 | #ifdef SERIAL_DO_RESTART |
3987 | if (info->flags & ASYNC_HUP_NOTIFY) | 3996 | if (info->flags & ASYNC_HUP_NOTIFY) |
@@ -4057,7 +4066,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp, | |||
4057 | printk("block_til_ready blocking: ttyS%d, count = %d\n", | 4066 | printk("block_til_ready blocking: ttyS%d, count = %d\n", |
4058 | info->line, info->count); | 4067 | info->line, info->count); |
4059 | #endif | 4068 | #endif |
4069 | tty_unlock(); | ||
4060 | schedule(); | 4070 | schedule(); |
4071 | tty_lock(); | ||
4061 | } | 4072 | } |
4062 | set_current_state(TASK_RUNNING); | 4073 | set_current_state(TASK_RUNNING); |
4063 | remove_wait_queue(&info->open_wait, &wait); | 4074 | remove_wait_queue(&info->open_wait, &wait); |
@@ -4139,7 +4150,7 @@ rs_open(struct tty_struct *tty, struct file * filp) | |||
4139 | */ | 4150 | */ |
4140 | if (tty_hung_up_p(filp) || | 4151 | if (tty_hung_up_p(filp) || |
4141 | (info->flags & ASYNC_CLOSING)) { | 4152 | (info->flags & ASYNC_CLOSING)) { |
4142 | wait_event_interruptible(info->close_wait, | 4153 | wait_event_interruptible_tty(info->close_wait, |
4143 | !(info->flags & ASYNC_CLOSING)); | 4154 | !(info->flags & ASYNC_CLOSING)); |
4144 | #ifdef SERIAL_DO_RESTART | 4155 | #ifdef SERIAL_DO_RESTART |
4145 | return ((info->flags & ASYNC_HUP_NOTIFY) ? | 4156 | return ((info->flags & ASYNC_HUP_NOTIFY) ? |
@@ -4522,8 +4533,8 @@ static int __init rs_init(void) | |||
4522 | INIT_WORK(&info->work, do_softint); | 4533 | INIT_WORK(&info->work, do_softint); |
4523 | 4534 | ||
4524 | if (info->enabled) { | 4535 | if (info->enabled) { |
4525 | printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n", | 4536 | printk(KERN_INFO "%s%d at %p is a builtin UART with DMA\n", |
4526 | serial_driver->name, info->line, (unsigned int)info->ioport); | 4537 | serial_driver->name, info->line, info->ioport); |
4527 | } | 4538 | } |
4528 | } | 4539 | } |
4529 | #ifdef CONFIG_ETRAX_FAST_TIMER | 4540 | #ifdef CONFIG_ETRAX_FAST_TIMER |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index eacb588a9345..66ecc7ab6dab 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
@@ -909,13 +909,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, | |||
909 | rational_best_approximation(16 * div * baud, sport->port.uartclk, | 909 | rational_best_approximation(16 * div * baud, sport->port.uartclk, |
910 | 1 << 16, 1 << 16, &num, &denom); | 910 | 1 << 16, 1 << 16, &num, &denom); |
911 | 911 | ||
912 | if (port->state && port->state->port.tty) { | 912 | tdiv64 = sport->port.uartclk; |
913 | tdiv64 = sport->port.uartclk; | 913 | tdiv64 *= num; |
914 | tdiv64 *= num; | 914 | do_div(tdiv64, denom * 16 * div); |
915 | do_div(tdiv64, denom * 16 * div); | 915 | tty_termios_encode_baud_rate(termios, |
916 | tty_encode_baud_rate(sport->port.state->port.tty, | ||
917 | (speed_t)tdiv64, (speed_t)tdiv64); | 916 | (speed_t)tdiv64, (speed_t)tdiv64); |
918 | } | ||
919 | 917 | ||
920 | num -= 1; | 918 | num -= 1; |
921 | denom -= 1; | 919 | denom -= 1; |
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index f164ba4eba02..93de907b1208 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c | |||
@@ -954,12 +954,13 @@ ioc3_change_speed(struct uart_port *the_port, | |||
954 | struct ktermios *new_termios, struct ktermios *old_termios) | 954 | struct ktermios *new_termios, struct ktermios *old_termios) |
955 | { | 955 | { |
956 | struct ioc3_port *port = get_ioc3_port(the_port); | 956 | struct ioc3_port *port = get_ioc3_port(the_port); |
957 | unsigned int cflag; | 957 | unsigned int cflag, iflag; |
958 | int baud; | 958 | int baud; |
959 | int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; | 959 | int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; |
960 | struct uart_state *state = the_port->state; | 960 | struct uart_state *state = the_port->state; |
961 | 961 | ||
962 | cflag = new_termios->c_cflag; | 962 | cflag = new_termios->c_cflag; |
963 | iflag = new_termios->c_iflag; | ||
963 | 964 | ||
964 | switch (cflag & CSIZE) { | 965 | switch (cflag & CSIZE) { |
965 | case CS5: | 966 | case CS5: |
@@ -1000,12 +1001,12 @@ ioc3_change_speed(struct uart_port *the_port, | |||
1000 | 1001 | ||
1001 | state->port.tty->low_latency = 1; | 1002 | state->port.tty->low_latency = 1; |
1002 | 1003 | ||
1003 | if (I_IGNPAR(state->port.tty)) | 1004 | if (iflag & IGNPAR) |
1004 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR | 1005 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR |
1005 | | N_FRAMING_ERROR); | 1006 | | N_FRAMING_ERROR); |
1006 | if (I_IGNBRK(state->port.tty)) { | 1007 | if (iflag & IGNBRK) { |
1007 | the_port->ignore_status_mask &= ~N_BREAK; | 1008 | the_port->ignore_status_mask &= ~N_BREAK; |
1008 | if (I_IGNPAR(state->port.tty)) | 1009 | if (iflag & IGNPAR) |
1009 | the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; | 1010 | the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; |
1010 | } | 1011 | } |
1011 | if (!(cflag & CREAD)) { | 1012 | if (!(cflag & CREAD)) { |
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 8ad28fc64926..fcfe82653ac8 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c | |||
@@ -1685,11 +1685,12 @@ ioc4_change_speed(struct uart_port *the_port, | |||
1685 | { | 1685 | { |
1686 | struct ioc4_port *port = get_ioc4_port(the_port, 0); | 1686 | struct ioc4_port *port = get_ioc4_port(the_port, 0); |
1687 | int baud, bits; | 1687 | int baud, bits; |
1688 | unsigned cflag; | 1688 | unsigned cflag, iflag; |
1689 | int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; | 1689 | int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; |
1690 | struct uart_state *state = the_port->state; | 1690 | struct uart_state *state = the_port->state; |
1691 | 1691 | ||
1692 | cflag = new_termios->c_cflag; | 1692 | cflag = new_termios->c_cflag; |
1693 | iflag = new_termios->c_iflag; | ||
1693 | 1694 | ||
1694 | switch (cflag & CSIZE) { | 1695 | switch (cflag & CSIZE) { |
1695 | case CS5: | 1696 | case CS5: |
@@ -1741,12 +1742,12 @@ ioc4_change_speed(struct uart_port *the_port, | |||
1741 | 1742 | ||
1742 | state->port.tty->low_latency = 1; | 1743 | state->port.tty->low_latency = 1; |
1743 | 1744 | ||
1744 | if (I_IGNPAR(state->port.tty)) | 1745 | if (iflag & IGNPAR) |
1745 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR | 1746 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR |
1746 | | N_FRAMING_ERROR); | 1747 | | N_FRAMING_ERROR); |
1747 | if (I_IGNBRK(state->port.tty)) { | 1748 | if (iflag & IGNBRK) { |
1748 | the_port->ignore_status_mask &= ~N_BREAK; | 1749 | the_port->ignore_status_mask &= ~N_BREAK; |
1749 | if (I_IGNPAR(state->port.tty)) | 1750 | if (iflag & IGNPAR) |
1750 | the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; | 1751 | the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; |
1751 | } | 1752 | } |
1752 | if (!(cflag & CREAD)) { | 1753 | if (!(cflag & CREAD)) { |
diff --git a/drivers/serial/max3100.c b/drivers/serial/max3100.c index 3351c3bd59e4..beb1afa27d8d 100644 --- a/drivers/serial/max3100.c +++ b/drivers/serial/max3100.c | |||
@@ -430,17 +430,14 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios, | |||
430 | int baud = 0; | 430 | int baud = 0; |
431 | unsigned cflag; | 431 | unsigned cflag; |
432 | u32 param_new, param_mask, parity = 0; | 432 | u32 param_new, param_mask, parity = 0; |
433 | struct tty_struct *tty = s->port.state->port.tty; | ||
434 | 433 | ||
435 | dev_dbg(&s->spi->dev, "%s\n", __func__); | 434 | dev_dbg(&s->spi->dev, "%s\n", __func__); |
436 | if (!tty) | ||
437 | return; | ||
438 | 435 | ||
439 | cflag = termios->c_cflag; | 436 | cflag = termios->c_cflag; |
440 | param_new = 0; | 437 | param_new = 0; |
441 | param_mask = 0; | 438 | param_mask = 0; |
442 | 439 | ||
443 | baud = tty_get_baud_rate(tty); | 440 | baud = tty_termios_baud_rate(termios); |
444 | param_new = s->conf & MAX3100_BAUD; | 441 | param_new = s->conf & MAX3100_BAUD; |
445 | switch (baud) { | 442 | switch (baud) { |
446 | case 300: | 443 | case 300: |
@@ -485,7 +482,7 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios, | |||
485 | default: | 482 | default: |
486 | baud = s->baud; | 483 | baud = s->baud; |
487 | } | 484 | } |
488 | tty_encode_baud_rate(tty, baud, baud); | 485 | tty_termios_encode_baud_rate(termios, baud, baud); |
489 | s->baud = baud; | 486 | s->baud = baud; |
490 | param_mask |= MAX3100_BAUD; | 487 | param_mask |= MAX3100_BAUD; |
491 | 488 | ||
diff --git a/drivers/serial/max3107-aava.c b/drivers/serial/max3107-aava.c new file mode 100644 index 000000000000..a1fe304f2f52 --- /dev/null +++ b/drivers/serial/max3107-aava.c | |||
@@ -0,0 +1,344 @@ | |||
1 | /* | ||
2 | * max3107.c - spi uart protocol driver for Maxim 3107 | ||
3 | * Based on max3100.c | ||
4 | * by Christian Pellegrin <chripell@evolware.org> | ||
5 | * and max3110.c | ||
6 | * by Feng Tang <feng.tang@intel.com> | ||
7 | * | ||
8 | * Copyright (C) Aavamobile 2009 | ||
9 | * | ||
10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include <linux/delay.h> | ||
31 | #include <linux/device.h> | ||
32 | #include <linux/serial_core.h> | ||
33 | #include <linux/serial.h> | ||
34 | #include <linux/spi/spi.h> | ||
35 | #include <linux/freezer.h> | ||
36 | #include <linux/platform_device.h> | ||
37 | #include <linux/gpio.h> | ||
38 | #include <linux/sfi.h> | ||
39 | #include <asm/mrst.h> | ||
40 | #include "max3107.h" | ||
41 | |||
42 | /* GPIO direction to input function */ | ||
43 | static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset) | ||
44 | { | ||
45 | struct max3107_port *s = container_of(chip, struct max3107_port, chip); | ||
46 | u16 buf[1]; /* Buffer for SPI transfer */ | ||
47 | |||
48 | if (offset >= MAX3107_GPIO_COUNT) { | ||
49 | dev_err(&s->spi->dev, "Invalid GPIO\n"); | ||
50 | return -EINVAL; | ||
51 | } | ||
52 | |||
53 | /* Read current GPIO configuration register */ | ||
54 | buf[0] = MAX3107_GPIOCFG_REG; | ||
55 | /* Perform SPI transfer */ | ||
56 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { | ||
57 | dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n"); | ||
58 | return -EIO; | ||
59 | } | ||
60 | buf[0] &= MAX3107_SPI_RX_DATA_MASK; | ||
61 | |||
62 | /* Set GPIO to input */ | ||
63 | buf[0] &= ~(0x0001 << offset); | ||
64 | |||
65 | /* Write new GPIO configuration register value */ | ||
66 | buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); | ||
67 | /* Perform SPI transfer */ | ||
68 | if (max3107_rw(s, (u8 *)buf, NULL, 2)) { | ||
69 | dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n"); | ||
70 | return -EIO; | ||
71 | } | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | /* GPIO direction to output function */ | ||
76 | static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset, | ||
77 | int value) | ||
78 | { | ||
79 | struct max3107_port *s = container_of(chip, struct max3107_port, chip); | ||
80 | u16 buf[2]; /* Buffer for SPI transfers */ | ||
81 | |||
82 | if (offset >= MAX3107_GPIO_COUNT) { | ||
83 | dev_err(&s->spi->dev, "Invalid GPIO\n"); | ||
84 | return -EINVAL; | ||
85 | } | ||
86 | |||
87 | /* Read current GPIO configuration and data registers */ | ||
88 | buf[0] = MAX3107_GPIOCFG_REG; | ||
89 | buf[1] = MAX3107_GPIODATA_REG; | ||
90 | /* Perform SPI transfer */ | ||
91 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { | ||
92 | dev_err(&s->spi->dev, "SPI transfer gpio failed\n"); | ||
93 | return -EIO; | ||
94 | } | ||
95 | buf[0] &= MAX3107_SPI_RX_DATA_MASK; | ||
96 | buf[1] &= MAX3107_SPI_RX_DATA_MASK; | ||
97 | |||
98 | /* Set GPIO to output */ | ||
99 | buf[0] |= (0x0001 << offset); | ||
100 | /* Set value */ | ||
101 | if (value) | ||
102 | buf[1] |= (0x0001 << offset); | ||
103 | else | ||
104 | buf[1] &= ~(0x0001 << offset); | ||
105 | |||
106 | /* Write new GPIO configuration and data register values */ | ||
107 | buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); | ||
108 | buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); | ||
109 | /* Perform SPI transfer */ | ||
110 | if (max3107_rw(s, (u8 *)buf, NULL, 4)) { | ||
111 | dev_err(&s->spi->dev, | ||
112 | "SPI transfer for GPIO conf data w failed\n"); | ||
113 | return -EIO; | ||
114 | } | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | /* GPIO value query function */ | ||
119 | static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
120 | { | ||
121 | struct max3107_port *s = container_of(chip, struct max3107_port, chip); | ||
122 | u16 buf[1]; /* Buffer for SPI transfer */ | ||
123 | |||
124 | if (offset >= MAX3107_GPIO_COUNT) { | ||
125 | dev_err(&s->spi->dev, "Invalid GPIO\n"); | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | /* Read current GPIO data register */ | ||
130 | buf[0] = MAX3107_GPIODATA_REG; | ||
131 | /* Perform SPI transfer */ | ||
132 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { | ||
133 | dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n"); | ||
134 | return -EIO; | ||
135 | } | ||
136 | buf[0] &= MAX3107_SPI_RX_DATA_MASK; | ||
137 | |||
138 | /* Return value */ | ||
139 | return buf[0] & (0x0001 << offset); | ||
140 | } | ||
141 | |||
142 | /* GPIO value set function */ | ||
143 | static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
144 | { | ||
145 | struct max3107_port *s = container_of(chip, struct max3107_port, chip); | ||
146 | u16 buf[2]; /* Buffer for SPI transfers */ | ||
147 | |||
148 | if (offset >= MAX3107_GPIO_COUNT) { | ||
149 | dev_err(&s->spi->dev, "Invalid GPIO\n"); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | /* Read current GPIO configuration registers*/ | ||
154 | buf[0] = MAX3107_GPIODATA_REG; | ||
155 | buf[1] = MAX3107_GPIOCFG_REG; | ||
156 | /* Perform SPI transfer */ | ||
157 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { | ||
158 | dev_err(&s->spi->dev, | ||
159 | "SPI transfer for GPIO data and config read failed\n"); | ||
160 | return; | ||
161 | } | ||
162 | buf[0] &= MAX3107_SPI_RX_DATA_MASK; | ||
163 | buf[1] &= MAX3107_SPI_RX_DATA_MASK; | ||
164 | |||
165 | if (!(buf[1] & (0x0001 << offset))) { | ||
166 | /* Configured as input, can't set value */ | ||
167 | dev_warn(&s->spi->dev, | ||
168 | "Trying to set value for input GPIO\n"); | ||
169 | return; | ||
170 | } | ||
171 | |||
172 | /* Set value */ | ||
173 | if (value) | ||
174 | buf[0] |= (0x0001 << offset); | ||
175 | else | ||
176 | buf[0] &= ~(0x0001 << offset); | ||
177 | |||
178 | /* Write new GPIO data register value */ | ||
179 | buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); | ||
180 | /* Perform SPI transfer */ | ||
181 | if (max3107_rw(s, (u8 *)buf, NULL, 2)) | ||
182 | dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n"); | ||
183 | } | ||
184 | |||
185 | /* GPIO chip data */ | ||
186 | static struct gpio_chip max3107_gpio_chip = { | ||
187 | .owner = THIS_MODULE, | ||
188 | .direction_input = max3107_gpio_direction_in, | ||
189 | .direction_output = max3107_gpio_direction_out, | ||
190 | .get = max3107_gpio_get, | ||
191 | .set = max3107_gpio_set, | ||
192 | .can_sleep = 1, | ||
193 | .base = MAX3107_GPIO_BASE, | ||
194 | .ngpio = MAX3107_GPIO_COUNT, | ||
195 | }; | ||
196 | |||
197 | /** | ||
198 | * max3107_aava_reset - reset on AAVA systems | ||
199 | * @spi: The SPI device we are probing | ||
200 | * | ||
201 | * Reset the device ready for probing. | ||
202 | */ | ||
203 | |||
204 | static int max3107_aava_reset(struct spi_device *spi) | ||
205 | { | ||
206 | /* Reset the chip */ | ||
207 | if (gpio_request(MAX3107_RESET_GPIO, "max3107")) { | ||
208 | pr_err("Requesting RESET GPIO failed\n"); | ||
209 | return -EIO; | ||
210 | } | ||
211 | if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) { | ||
212 | pr_err("Setting RESET GPIO to 0 failed\n"); | ||
213 | gpio_free(MAX3107_RESET_GPIO); | ||
214 | return -EIO; | ||
215 | } | ||
216 | msleep(MAX3107_RESET_DELAY); | ||
217 | if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) { | ||
218 | pr_err("Setting RESET GPIO to 1 failed\n"); | ||
219 | gpio_free(MAX3107_RESET_GPIO); | ||
220 | return -EIO; | ||
221 | } | ||
222 | gpio_free(MAX3107_RESET_GPIO); | ||
223 | msleep(MAX3107_WAKEUP_DELAY); | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int max3107_aava_configure(struct max3107_port *s) | ||
228 | { | ||
229 | int retval; | ||
230 | |||
231 | /* Initialize GPIO chip data */ | ||
232 | s->chip = max3107_gpio_chip; | ||
233 | s->chip.label = s->spi->modalias; | ||
234 | s->chip.dev = &s->spi->dev; | ||
235 | |||
236 | /* Add GPIO chip */ | ||
237 | retval = gpiochip_add(&s->chip); | ||
238 | if (retval) { | ||
239 | dev_err(&s->spi->dev, "Adding GPIO chip failed\n"); | ||
240 | return retval; | ||
241 | } | ||
242 | |||
243 | /* Temporary fix for EV2 boot problems, set modem reset to 0 */ | ||
244 | max3107_gpio_direction_out(&s->chip, 3, 0); | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | #if 0 | ||
249 | /* This will get enabled once we have the board stuff merged for this | ||
250 | specific case */ | ||
251 | |||
252 | static const struct baud_table brg13_ext[] = { | ||
253 | { 300, MAX3107_BRG13_B300 }, | ||
254 | { 600, MAX3107_BRG13_B600 }, | ||
255 | { 1200, MAX3107_BRG13_B1200 }, | ||
256 | { 2400, MAX3107_BRG13_B2400 }, | ||
257 | { 4800, MAX3107_BRG13_B4800 }, | ||
258 | { 9600, MAX3107_BRG13_B9600 }, | ||
259 | { 19200, MAX3107_BRG13_B19200 }, | ||
260 | { 57600, MAX3107_BRG13_B57600 }, | ||
261 | { 115200, MAX3107_BRG13_B115200 }, | ||
262 | { 230400, MAX3107_BRG13_B230400 }, | ||
263 | { 460800, MAX3107_BRG13_B460800 }, | ||
264 | { 921600, MAX3107_BRG13_B921600 }, | ||
265 | { 0, 0 } | ||
266 | }; | ||
267 | |||
268 | static void max3107_aava_init(struct max3107_port *s) | ||
269 | { | ||
270 | /*override for AAVA SC specific*/ | ||
271 | if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) { | ||
272 | if (get_koski_build_id() <= KOSKI_EV2) | ||
273 | if (s->ext_clk) { | ||
274 | s->brg_cfg = MAX3107_BRG13_B9600; | ||
275 | s->baud_tbl = (struct baud_table *)brg13_ext; | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | #endif | ||
280 | |||
281 | static int __devexit max3107_aava_remove(struct spi_device *spi) | ||
282 | { | ||
283 | struct max3107_port *s = dev_get_drvdata(&spi->dev); | ||
284 | |||
285 | /* Remove GPIO chip */ | ||
286 | if (gpiochip_remove(&s->chip)) | ||
287 | dev_warn(&spi->dev, "Removing GPIO chip failed\n"); | ||
288 | |||
289 | /* Then do the default remove */ | ||
290 | return max3107_remove(spi); | ||
291 | } | ||
292 | |||
293 | /* Platform data */ | ||
294 | static struct max3107_plat aava_plat_data = { | ||
295 | .loopback = 0, | ||
296 | .ext_clk = 1, | ||
297 | /* .init = max3107_aava_init, */ | ||
298 | .configure = max3107_aava_configure, | ||
299 | .hw_suspend = max3107_hw_susp, | ||
300 | .polled_mode = 0, | ||
301 | .poll_time = 0, | ||
302 | }; | ||
303 | |||
304 | |||
305 | static int __devinit max3107_probe_aava(struct spi_device *spi) | ||
306 | { | ||
307 | int err = max3107_aava_reset(spi); | ||
308 | if (err < 0) | ||
309 | return err; | ||
310 | return max3107_probe(spi, &aava_plat_data); | ||
311 | } | ||
312 | |||
313 | /* Spi driver data */ | ||
314 | static struct spi_driver max3107_driver = { | ||
315 | .driver = { | ||
316 | .name = "aava-max3107", | ||
317 | .bus = &spi_bus_type, | ||
318 | .owner = THIS_MODULE, | ||
319 | }, | ||
320 | .probe = max3107_probe_aava, | ||
321 | .remove = __devexit_p(max3107_aava_remove), | ||
322 | .suspend = max3107_suspend, | ||
323 | .resume = max3107_resume, | ||
324 | }; | ||
325 | |||
326 | /* Driver init function */ | ||
327 | static int __init max3107_init(void) | ||
328 | { | ||
329 | return spi_register_driver(&max3107_driver); | ||
330 | } | ||
331 | |||
332 | /* Driver exit function */ | ||
333 | static void __exit max3107_exit(void) | ||
334 | { | ||
335 | spi_unregister_driver(&max3107_driver); | ||
336 | } | ||
337 | |||
338 | module_init(max3107_init); | ||
339 | module_exit(max3107_exit); | ||
340 | |||
341 | MODULE_DESCRIPTION("MAX3107 driver"); | ||
342 | MODULE_AUTHOR("Aavamobile"); | ||
343 | MODULE_ALIAS("aava-max3107-spi"); | ||
344 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/serial/max3107.c b/drivers/serial/max3107.c new file mode 100644 index 000000000000..67283c1a57ff --- /dev/null +++ b/drivers/serial/max3107.c | |||
@@ -0,0 +1,1197 @@ | |||
1 | /* | ||
2 | * max3107.c - spi uart protocol driver for Maxim 3107 | ||
3 | * Based on max3100.c | ||
4 | * by Christian Pellegrin <chripell@evolware.org> | ||
5 | * and max3110.c | ||
6 | * by Feng Tang <feng.tang@intel.com> | ||
7 | * | ||
8 | * Copyright (C) Aavamobile 2009 | ||
9 | * | ||
10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include <linux/delay.h> | ||
31 | #include <linux/device.h> | ||
32 | #include <linux/serial_core.h> | ||
33 | #include <linux/serial.h> | ||
34 | #include <linux/gpio.h> | ||
35 | #include <linux/spi/spi.h> | ||
36 | #include <linux/freezer.h> | ||
37 | #include "max3107.h" | ||
38 | |||
39 | static const struct baud_table brg26_ext[] = { | ||
40 | { 300, MAX3107_BRG26_B300 }, | ||
41 | { 600, MAX3107_BRG26_B600 }, | ||
42 | { 1200, MAX3107_BRG26_B1200 }, | ||
43 | { 2400, MAX3107_BRG26_B2400 }, | ||
44 | { 4800, MAX3107_BRG26_B4800 }, | ||
45 | { 9600, MAX3107_BRG26_B9600 }, | ||
46 | { 19200, MAX3107_BRG26_B19200 }, | ||
47 | { 57600, MAX3107_BRG26_B57600 }, | ||
48 | { 115200, MAX3107_BRG26_B115200 }, | ||
49 | { 230400, MAX3107_BRG26_B230400 }, | ||
50 | { 460800, MAX3107_BRG26_B460800 }, | ||
51 | { 921600, MAX3107_BRG26_B921600 }, | ||
52 | { 0, 0 } | ||
53 | }; | ||
54 | |||
55 | static const struct baud_table brg13_int[] = { | ||
56 | { 300, MAX3107_BRG13_IB300 }, | ||
57 | { 600, MAX3107_BRG13_IB600 }, | ||
58 | { 1200, MAX3107_BRG13_IB1200 }, | ||
59 | { 2400, MAX3107_BRG13_IB2400 }, | ||
60 | { 4800, MAX3107_BRG13_IB4800 }, | ||
61 | { 9600, MAX3107_BRG13_IB9600 }, | ||
62 | { 19200, MAX3107_BRG13_IB19200 }, | ||
63 | { 57600, MAX3107_BRG13_IB57600 }, | ||
64 | { 115200, MAX3107_BRG13_IB115200 }, | ||
65 | { 230400, MAX3107_BRG13_IB230400 }, | ||
66 | { 460800, MAX3107_BRG13_IB460800 }, | ||
67 | { 921600, MAX3107_BRG13_IB921600 }, | ||
68 | { 0, 0 } | ||
69 | }; | ||
70 | |||
71 | static u32 get_new_brg(int baud, struct max3107_port *s) | ||
72 | { | ||
73 | int i; | ||
74 | const struct baud_table *baud_tbl = s->baud_tbl; | ||
75 | |||
76 | for (i = 0; i < 13; i++) { | ||
77 | if (baud == baud_tbl[i].baud) | ||
78 | return baud_tbl[i].new_brg; | ||
79 | } | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | /* Perform SPI transfer for write/read of device register(s) */ | ||
85 | int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len) | ||
86 | { | ||
87 | struct spi_message spi_msg; | ||
88 | struct spi_transfer spi_xfer; | ||
89 | |||
90 | /* Initialize SPI ,message */ | ||
91 | spi_message_init(&spi_msg); | ||
92 | |||
93 | /* Initialize SPI transfer */ | ||
94 | memset(&spi_xfer, 0, sizeof spi_xfer); | ||
95 | spi_xfer.len = len; | ||
96 | spi_xfer.tx_buf = tx; | ||
97 | spi_xfer.rx_buf = rx; | ||
98 | spi_xfer.speed_hz = MAX3107_SPI_SPEED; | ||
99 | |||
100 | /* Add SPI transfer to SPI message */ | ||
101 | spi_message_add_tail(&spi_xfer, &spi_msg); | ||
102 | |||
103 | #ifdef DBG_TRACE_SPI_DATA | ||
104 | { | ||
105 | int i; | ||
106 | pr_info("tx len %d:\n", spi_xfer.len); | ||
107 | for (i = 0 ; i < spi_xfer.len && i < 32 ; i++) | ||
108 | pr_info(" %x", ((u8 *)spi_xfer.tx_buf)[i]); | ||
109 | pr_info("\n"); | ||
110 | } | ||
111 | #endif | ||
112 | |||
113 | /* Perform synchronous SPI transfer */ | ||
114 | if (spi_sync(s->spi, &spi_msg)) { | ||
115 | dev_err(&s->spi->dev, "spi_sync failure\n"); | ||
116 | return -EIO; | ||
117 | } | ||
118 | |||
119 | #ifdef DBG_TRACE_SPI_DATA | ||
120 | if (spi_xfer.rx_buf) { | ||
121 | int i; | ||
122 | pr_info("rx len %d:\n", spi_xfer.len); | ||
123 | for (i = 0 ; i < spi_xfer.len && i < 32 ; i++) | ||
124 | pr_info(" %x", ((u8 *)spi_xfer.rx_buf)[i]); | ||
125 | pr_info("\n"); | ||
126 | } | ||
127 | #endif | ||
128 | return 0; | ||
129 | } | ||
130 | EXPORT_SYMBOL_GPL(max3107_rw); | ||
131 | |||
132 | /* Puts received data to circular buffer */ | ||
133 | static void put_data_to_circ_buf(struct max3107_port *s, unsigned char *data, | ||
134 | int len) | ||
135 | { | ||
136 | struct uart_port *port = &s->port; | ||
137 | struct tty_struct *tty; | ||
138 | |||
139 | if (!port->state) | ||
140 | return; | ||
141 | |||
142 | tty = port->state->port.tty; | ||
143 | if (!tty) | ||
144 | return; | ||
145 | |||
146 | /* Insert received data */ | ||
147 | tty_insert_flip_string(tty, data, len); | ||
148 | /* Update RX counter */ | ||
149 | port->icount.rx += len; | ||
150 | } | ||
151 | |||
152 | /* Handle data receiving */ | ||
153 | static void max3107_handlerx(struct max3107_port *s, u16 rxlvl) | ||
154 | { | ||
155 | int i; | ||
156 | int j; | ||
157 | int len; /* SPI transfer buffer length */ | ||
158 | u16 *buf; | ||
159 | u8 *valid_str; | ||
160 | |||
161 | if (!s->rx_enabled) | ||
162 | /* RX is disabled */ | ||
163 | return; | ||
164 | |||
165 | if (rxlvl == 0) { | ||
166 | /* RX fifo is empty */ | ||
167 | return; | ||
168 | } else if (rxlvl >= MAX3107_RX_FIFO_SIZE) { | ||
169 | dev_warn(&s->spi->dev, "Possible RX FIFO overrun %d\n", rxlvl); | ||
170 | /* Ensure sanity of RX level */ | ||
171 | rxlvl = MAX3107_RX_FIFO_SIZE; | ||
172 | } | ||
173 | if ((s->rxbuf == 0) || (s->rxstr == 0)) { | ||
174 | dev_warn(&s->spi->dev, "Rx buffer/str isn't ready\n"); | ||
175 | return; | ||
176 | } | ||
177 | buf = s->rxbuf; | ||
178 | valid_str = s->rxstr; | ||
179 | while (rxlvl) { | ||
180 | pr_debug("rxlvl %d\n", rxlvl); | ||
181 | /* Clear buffer */ | ||
182 | memset(buf, 0, sizeof(u16) * (MAX3107_RX_FIFO_SIZE + 2)); | ||
183 | len = 0; | ||
184 | if (s->irqen_reg & MAX3107_IRQ_RXFIFO_BIT) { | ||
185 | /* First disable RX FIFO interrupt */ | ||
186 | pr_debug("Disabling RX INT\n"); | ||
187 | buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); | ||
188 | s->irqen_reg &= ~MAX3107_IRQ_RXFIFO_BIT; | ||
189 | buf[0] |= s->irqen_reg; | ||
190 | len++; | ||
191 | } | ||
192 | /* Just increase the length by amount of words in FIFO since | ||
193 | * buffer was zeroed and SPI transfer of 0x0000 means reading | ||
194 | * from RX FIFO | ||
195 | */ | ||
196 | len += rxlvl; | ||
197 | /* Append RX level query */ | ||
198 | buf[len] = MAX3107_RXFIFOLVL_REG; | ||
199 | len++; | ||
200 | |||
201 | /* Perform the SPI transfer */ | ||
202 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, len * 2)) { | ||
203 | dev_err(&s->spi->dev, "SPI transfer for RX h failed\n"); | ||
204 | return; | ||
205 | } | ||
206 | |||
207 | /* Skip RX FIFO interrupt disabling word if it was added */ | ||
208 | j = ((len - 1) - rxlvl); | ||
209 | /* Read received words */ | ||
210 | for (i = 0; i < rxlvl; i++, j++) | ||
211 | valid_str[i] = (u8)buf[j]; | ||
212 | put_data_to_circ_buf(s, valid_str, rxlvl); | ||
213 | /* Get new RX level */ | ||
214 | rxlvl = (buf[len - 1] & MAX3107_SPI_RX_DATA_MASK); | ||
215 | } | ||
216 | |||
217 | if (s->rx_enabled) { | ||
218 | /* RX still enabled, re-enable RX FIFO interrupt */ | ||
219 | pr_debug("Enabling RX INT\n"); | ||
220 | buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); | ||
221 | s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT; | ||
222 | buf[0] |= s->irqen_reg; | ||
223 | if (max3107_rw(s, (u8 *)buf, NULL, 2)) | ||
224 | dev_err(&s->spi->dev, "RX FIFO INT enabling failed\n"); | ||
225 | } | ||
226 | |||
227 | /* Push the received data to receivers */ | ||
228 | if (s->port.state->port.tty) | ||
229 | tty_flip_buffer_push(s->port.state->port.tty); | ||
230 | } | ||
231 | |||
232 | |||
233 | /* Handle data sending */ | ||
234 | static void max3107_handletx(struct max3107_port *s) | ||
235 | { | ||
236 | struct circ_buf *xmit = &s->port.state->xmit; | ||
237 | int i; | ||
238 | unsigned long flags; | ||
239 | int len; /* SPI transfer buffer length */ | ||
240 | u16 *buf; | ||
241 | |||
242 | if (!s->tx_fifo_empty) | ||
243 | /* Don't send more data before previous data is sent */ | ||
244 | return; | ||
245 | |||
246 | if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port)) | ||
247 | /* No data to send or TX is stopped */ | ||
248 | return; | ||
249 | |||
250 | if (!s->txbuf) { | ||
251 | dev_warn(&s->spi->dev, "Txbuf isn't ready\n"); | ||
252 | return; | ||
253 | } | ||
254 | buf = s->txbuf; | ||
255 | /* Get length of data pending in circular buffer */ | ||
256 | len = uart_circ_chars_pending(xmit); | ||
257 | if (len) { | ||
258 | /* Limit to size of TX FIFO */ | ||
259 | if (len > MAX3107_TX_FIFO_SIZE) | ||
260 | len = MAX3107_TX_FIFO_SIZE; | ||
261 | |||
262 | pr_debug("txlen %d\n", len); | ||
263 | |||
264 | /* Update TX counter */ | ||
265 | s->port.icount.tx += len; | ||
266 | |||
267 | /* TX FIFO will no longer be empty */ | ||
268 | s->tx_fifo_empty = 0; | ||
269 | |||
270 | i = 0; | ||
271 | if (s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT) { | ||
272 | /* First disable TX empty interrupt */ | ||
273 | pr_debug("Disabling TE INT\n"); | ||
274 | buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); | ||
275 | s->irqen_reg &= ~MAX3107_IRQ_TXEMPTY_BIT; | ||
276 | buf[i] |= s->irqen_reg; | ||
277 | i++; | ||
278 | len++; | ||
279 | } | ||
280 | /* Add data to send */ | ||
281 | spin_lock_irqsave(&s->port.lock, flags); | ||
282 | for ( ; i < len ; i++) { | ||
283 | buf[i] = (MAX3107_WRITE_BIT | MAX3107_THR_REG); | ||
284 | buf[i] |= ((u16)xmit->buf[xmit->tail] & | ||
285 | MAX3107_SPI_TX_DATA_MASK); | ||
286 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
287 | } | ||
288 | spin_unlock_irqrestore(&s->port.lock, flags); | ||
289 | if (!(s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT)) { | ||
290 | /* Enable TX empty interrupt */ | ||
291 | pr_debug("Enabling TE INT\n"); | ||
292 | buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); | ||
293 | s->irqen_reg |= MAX3107_IRQ_TXEMPTY_BIT; | ||
294 | buf[i] |= s->irqen_reg; | ||
295 | i++; | ||
296 | len++; | ||
297 | } | ||
298 | if (!s->tx_enabled) { | ||
299 | /* Enable TX */ | ||
300 | pr_debug("Enable TX\n"); | ||
301 | buf[i] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); | ||
302 | spin_lock_irqsave(&s->data_lock, flags); | ||
303 | s->mode1_reg &= ~MAX3107_MODE1_TXDIS_BIT; | ||
304 | buf[i] |= s->mode1_reg; | ||
305 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
306 | s->tx_enabled = 1; | ||
307 | i++; | ||
308 | len++; | ||
309 | } | ||
310 | |||
311 | /* Perform the SPI transfer */ | ||
312 | if (max3107_rw(s, (u8 *)buf, NULL, len*2)) { | ||
313 | dev_err(&s->spi->dev, | ||
314 | "SPI transfer TX handling failed\n"); | ||
315 | return; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | /* Indicate wake up if circular buffer is getting low on data */ | ||
320 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
321 | uart_write_wakeup(&s->port); | ||
322 | |||
323 | } | ||
324 | |||
325 | /* Handle interrupts | ||
326 | * Also reads and returns current RX FIFO level | ||
327 | */ | ||
328 | static u16 handle_interrupt(struct max3107_port *s) | ||
329 | { | ||
330 | u16 buf[4]; /* Buffer for SPI transfers */ | ||
331 | u8 irq_status; | ||
332 | u16 rx_level; | ||
333 | unsigned long flags; | ||
334 | |||
335 | /* Read IRQ status register */ | ||
336 | buf[0] = MAX3107_IRQSTS_REG; | ||
337 | /* Read status IRQ status register */ | ||
338 | buf[1] = MAX3107_STS_IRQSTS_REG; | ||
339 | /* Read LSR IRQ status register */ | ||
340 | buf[2] = MAX3107_LSR_IRQSTS_REG; | ||
341 | /* Query RX level */ | ||
342 | buf[3] = MAX3107_RXFIFOLVL_REG; | ||
343 | |||
344 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 8)) { | ||
345 | dev_err(&s->spi->dev, | ||
346 | "SPI transfer for INTR handling failed\n"); | ||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | irq_status = (u8)buf[0]; | ||
351 | pr_debug("IRQSTS %x\n", irq_status); | ||
352 | rx_level = (buf[3] & MAX3107_SPI_RX_DATA_MASK); | ||
353 | |||
354 | if (irq_status & MAX3107_IRQ_LSR_BIT) { | ||
355 | /* LSR interrupt */ | ||
356 | if (buf[2] & MAX3107_LSR_RXTO_BIT) | ||
357 | /* RX timeout interrupt, | ||
358 | * handled by normal RX handling | ||
359 | */ | ||
360 | pr_debug("RX TO INT\n"); | ||
361 | } | ||
362 | |||
363 | if (irq_status & MAX3107_IRQ_TXEMPTY_BIT) { | ||
364 | /* Tx empty interrupt, | ||
365 | * disable TX and set tx_fifo_empty flag | ||
366 | */ | ||
367 | pr_debug("TE INT, disabling TX\n"); | ||
368 | buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); | ||
369 | spin_lock_irqsave(&s->data_lock, flags); | ||
370 | s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT; | ||
371 | buf[0] |= s->mode1_reg; | ||
372 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
373 | if (max3107_rw(s, (u8 *)buf, NULL, 2)) | ||
374 | dev_err(&s->spi->dev, "SPI transfer TX dis failed\n"); | ||
375 | s->tx_enabled = 0; | ||
376 | s->tx_fifo_empty = 1; | ||
377 | } | ||
378 | |||
379 | if (irq_status & MAX3107_IRQ_RXFIFO_BIT) | ||
380 | /* RX FIFO interrupt, | ||
381 | * handled by normal RX handling | ||
382 | */ | ||
383 | pr_debug("RFIFO INT\n"); | ||
384 | |||
385 | /* Return RX level */ | ||
386 | return rx_level; | ||
387 | } | ||
388 | |||
389 | /* Trigger work thread*/ | ||
390 | static void max3107_dowork(struct max3107_port *s) | ||
391 | { | ||
392 | if (!work_pending(&s->work) && !freezing(current) && !s->suspended) | ||
393 | queue_work(s->workqueue, &s->work); | ||
394 | else | ||
395 | dev_warn(&s->spi->dev, "interrup isn't serviced normally!\n"); | ||
396 | } | ||
397 | |||
398 | /* Work thread */ | ||
399 | static void max3107_work(struct work_struct *w) | ||
400 | { | ||
401 | struct max3107_port *s = container_of(w, struct max3107_port, work); | ||
402 | u16 rxlvl = 0; | ||
403 | int len; /* SPI transfer buffer length */ | ||
404 | u16 buf[5]; /* Buffer for SPI transfers */ | ||
405 | unsigned long flags; | ||
406 | |||
407 | /* Start by reading current RX FIFO level */ | ||
408 | buf[0] = MAX3107_RXFIFOLVL_REG; | ||
409 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { | ||
410 | dev_err(&s->spi->dev, "SPI transfer RX lev failed\n"); | ||
411 | rxlvl = 0; | ||
412 | } else { | ||
413 | rxlvl = (buf[0] & MAX3107_SPI_RX_DATA_MASK); | ||
414 | } | ||
415 | |||
416 | do { | ||
417 | pr_debug("rxlvl %d\n", rxlvl); | ||
418 | |||
419 | /* Handle RX */ | ||
420 | max3107_handlerx(s, rxlvl); | ||
421 | rxlvl = 0; | ||
422 | |||
423 | if (s->handle_irq) { | ||
424 | /* Handle pending interrupts | ||
425 | * We also get new RX FIFO level since new data may | ||
426 | * have been received while pushing received data to | ||
427 | * receivers | ||
428 | */ | ||
429 | s->handle_irq = 0; | ||
430 | rxlvl = handle_interrupt(s); | ||
431 | } | ||
432 | |||
433 | /* Handle TX */ | ||
434 | max3107_handletx(s); | ||
435 | |||
436 | /* Handle configuration changes */ | ||
437 | len = 0; | ||
438 | spin_lock_irqsave(&s->data_lock, flags); | ||
439 | if (s->mode1_commit) { | ||
440 | pr_debug("mode1_commit\n"); | ||
441 | buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); | ||
442 | buf[len++] |= s->mode1_reg; | ||
443 | s->mode1_commit = 0; | ||
444 | } | ||
445 | if (s->lcr_commit) { | ||
446 | pr_debug("lcr_commit\n"); | ||
447 | buf[len] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG); | ||
448 | buf[len++] |= s->lcr_reg; | ||
449 | s->lcr_commit = 0; | ||
450 | } | ||
451 | if (s->brg_commit) { | ||
452 | pr_debug("brg_commit\n"); | ||
453 | buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG); | ||
454 | buf[len++] |= ((s->brg_cfg >> 16) & | ||
455 | MAX3107_SPI_TX_DATA_MASK); | ||
456 | buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG); | ||
457 | buf[len++] |= ((s->brg_cfg >> 8) & | ||
458 | MAX3107_SPI_TX_DATA_MASK); | ||
459 | buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG); | ||
460 | buf[len++] |= ((s->brg_cfg) & 0xff); | ||
461 | s->brg_commit = 0; | ||
462 | } | ||
463 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
464 | |||
465 | if (len > 0) { | ||
466 | if (max3107_rw(s, (u8 *)buf, NULL, len * 2)) | ||
467 | dev_err(&s->spi->dev, | ||
468 | "SPI transfer config failed\n"); | ||
469 | } | ||
470 | |||
471 | /* Reloop if interrupt handling indicated data in RX FIFO */ | ||
472 | } while (rxlvl); | ||
473 | |||
474 | } | ||
475 | |||
476 | /* Set sleep mode */ | ||
477 | static void max3107_set_sleep(struct max3107_port *s, int mode) | ||
478 | { | ||
479 | u16 buf[1]; /* Buffer for SPI transfer */ | ||
480 | unsigned long flags; | ||
481 | pr_debug("enter, mode %d\n", mode); | ||
482 | |||
483 | buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); | ||
484 | spin_lock_irqsave(&s->data_lock, flags); | ||
485 | switch (mode) { | ||
486 | case MAX3107_DISABLE_FORCED_SLEEP: | ||
487 | s->mode1_reg &= ~MAX3107_MODE1_FORCESLEEP_BIT; | ||
488 | break; | ||
489 | case MAX3107_ENABLE_FORCED_SLEEP: | ||
490 | s->mode1_reg |= MAX3107_MODE1_FORCESLEEP_BIT; | ||
491 | break; | ||
492 | case MAX3107_DISABLE_AUTOSLEEP: | ||
493 | s->mode1_reg &= ~MAX3107_MODE1_AUTOSLEEP_BIT; | ||
494 | break; | ||
495 | case MAX3107_ENABLE_AUTOSLEEP: | ||
496 | s->mode1_reg |= MAX3107_MODE1_AUTOSLEEP_BIT; | ||
497 | break; | ||
498 | default: | ||
499 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
500 | dev_warn(&s->spi->dev, "invalid sleep mode\n"); | ||
501 | return; | ||
502 | } | ||
503 | buf[0] |= s->mode1_reg; | ||
504 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
505 | |||
506 | if (max3107_rw(s, (u8 *)buf, NULL, 2)) | ||
507 | dev_err(&s->spi->dev, "SPI transfer sleep mode failed\n"); | ||
508 | |||
509 | if (mode == MAX3107_DISABLE_AUTOSLEEP || | ||
510 | mode == MAX3107_DISABLE_FORCED_SLEEP) | ||
511 | msleep(MAX3107_WAKEUP_DELAY); | ||
512 | } | ||
513 | |||
514 | /* Perform full register initialization */ | ||
515 | static void max3107_register_init(struct max3107_port *s) | ||
516 | { | ||
517 | u16 buf[11]; /* Buffer for SPI transfers */ | ||
518 | |||
519 | /* 1. Configure baud rate, 9600 as default */ | ||
520 | s->baud = 9600; | ||
521 | /* the below is default*/ | ||
522 | if (s->ext_clk) { | ||
523 | s->brg_cfg = MAX3107_BRG26_B9600; | ||
524 | s->baud_tbl = (struct baud_table *)brg26_ext; | ||
525 | } else { | ||
526 | s->brg_cfg = MAX3107_BRG13_IB9600; | ||
527 | s->baud_tbl = (struct baud_table *)brg13_int; | ||
528 | } | ||
529 | |||
530 | if (s->pdata->init) | ||
531 | s->pdata->init(s); | ||
532 | |||
533 | buf[0] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG) | ||
534 | | ((s->brg_cfg >> 16) & MAX3107_SPI_TX_DATA_MASK); | ||
535 | buf[1] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG) | ||
536 | | ((s->brg_cfg >> 8) & MAX3107_SPI_TX_DATA_MASK); | ||
537 | buf[2] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG) | ||
538 | | ((s->brg_cfg) & 0xff); | ||
539 | |||
540 | /* 2. Configure LCR register, 8N1 mode by default */ | ||
541 | s->lcr_reg = MAX3107_LCR_WORD_LEN_8; | ||
542 | buf[3] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG) | ||
543 | | s->lcr_reg; | ||
544 | |||
545 | /* 3. Configure MODE 1 register */ | ||
546 | s->mode1_reg = 0; | ||
547 | /* Enable IRQ pin */ | ||
548 | s->mode1_reg |= MAX3107_MODE1_IRQSEL_BIT; | ||
549 | /* Disable TX */ | ||
550 | s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT; | ||
551 | s->tx_enabled = 0; | ||
552 | /* RX is enabled */ | ||
553 | s->rx_enabled = 1; | ||
554 | buf[4] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG) | ||
555 | | s->mode1_reg; | ||
556 | |||
557 | /* 4. Configure MODE 2 register */ | ||
558 | buf[5] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG); | ||
559 | if (s->loopback) { | ||
560 | /* Enable loopback */ | ||
561 | buf[5] |= MAX3107_MODE2_LOOPBACK_BIT; | ||
562 | } | ||
563 | /* Reset FIFOs */ | ||
564 | buf[5] |= MAX3107_MODE2_FIFORST_BIT; | ||
565 | s->tx_fifo_empty = 1; | ||
566 | |||
567 | /* 5. Configure FIFO trigger level register */ | ||
568 | buf[6] = (MAX3107_WRITE_BIT | MAX3107_FIFOTRIGLVL_REG); | ||
569 | /* RX FIFO trigger for 16 words, TX FIFO trigger not used */ | ||
570 | buf[6] |= (MAX3107_FIFOTRIGLVL_RX(16) | MAX3107_FIFOTRIGLVL_TX(0)); | ||
571 | |||
572 | /* 6. Configure flow control levels */ | ||
573 | buf[7] = (MAX3107_WRITE_BIT | MAX3107_FLOWLVL_REG); | ||
574 | /* Flow control halt level 96, resume level 48 */ | ||
575 | buf[7] |= (MAX3107_FLOWLVL_RES(48) | MAX3107_FLOWLVL_HALT(96)); | ||
576 | |||
577 | /* 7. Configure flow control */ | ||
578 | buf[8] = (MAX3107_WRITE_BIT | MAX3107_FLOWCTRL_REG); | ||
579 | /* Enable auto CTS and auto RTS flow control */ | ||
580 | buf[8] |= (MAX3107_FLOWCTRL_AUTOCTS_BIT | MAX3107_FLOWCTRL_AUTORTS_BIT); | ||
581 | |||
582 | /* 8. Configure RX timeout register */ | ||
583 | buf[9] = (MAX3107_WRITE_BIT | MAX3107_RXTO_REG); | ||
584 | /* Timeout after 48 character intervals */ | ||
585 | buf[9] |= 0x0030; | ||
586 | |||
587 | /* 9. Configure LSR interrupt enable register */ | ||
588 | buf[10] = (MAX3107_WRITE_BIT | MAX3107_LSR_IRQEN_REG); | ||
589 | /* Enable RX timeout interrupt */ | ||
590 | buf[10] |= MAX3107_LSR_RXTO_BIT; | ||
591 | |||
592 | /* Perform SPI transfer */ | ||
593 | if (max3107_rw(s, (u8 *)buf, NULL, 22)) | ||
594 | dev_err(&s->spi->dev, "SPI transfer for init failed\n"); | ||
595 | |||
596 | /* 10. Clear IRQ status register by reading it */ | ||
597 | buf[0] = MAX3107_IRQSTS_REG; | ||
598 | |||
599 | /* 11. Configure interrupt enable register */ | ||
600 | /* Enable LSR interrupt */ | ||
601 | s->irqen_reg = MAX3107_IRQ_LSR_BIT; | ||
602 | /* Enable RX FIFO interrupt */ | ||
603 | s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT; | ||
604 | buf[1] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG) | ||
605 | | s->irqen_reg; | ||
606 | |||
607 | /* 12. Clear FIFO reset that was set in step 6 */ | ||
608 | buf[2] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG); | ||
609 | if (s->loopback) { | ||
610 | /* Keep loopback enabled */ | ||
611 | buf[2] |= MAX3107_MODE2_LOOPBACK_BIT; | ||
612 | } | ||
613 | |||
614 | /* Perform SPI transfer */ | ||
615 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 6)) | ||
616 | dev_err(&s->spi->dev, "SPI transfer for init failed\n"); | ||
617 | |||
618 | } | ||
619 | |||
620 | /* IRQ handler */ | ||
621 | static irqreturn_t max3107_irq(int irqno, void *dev_id) | ||
622 | { | ||
623 | struct max3107_port *s = dev_id; | ||
624 | |||
625 | if (irqno != s->spi->irq) { | ||
626 | /* Unexpected IRQ */ | ||
627 | return IRQ_NONE; | ||
628 | } | ||
629 | |||
630 | /* Indicate irq */ | ||
631 | s->handle_irq = 1; | ||
632 | |||
633 | /* Trigger work thread */ | ||
634 | max3107_dowork(s); | ||
635 | |||
636 | return IRQ_HANDLED; | ||
637 | } | ||
638 | |||
639 | /* HW suspension function | ||
640 | * | ||
641 | * Currently autosleep is used to decrease current consumption, alternative | ||
642 | * approach would be to set the chip to reset mode if UART is not being | ||
643 | * used but that would mess the GPIOs | ||
644 | * | ||
645 | */ | ||
646 | void max3107_hw_susp(struct max3107_port *s, int suspend) | ||
647 | { | ||
648 | pr_debug("enter, suspend %d\n", suspend); | ||
649 | |||
650 | if (suspend) { | ||
651 | /* Suspend requested, | ||
652 | * enable autosleep to decrease current consumption | ||
653 | */ | ||
654 | s->suspended = 1; | ||
655 | max3107_set_sleep(s, MAX3107_ENABLE_AUTOSLEEP); | ||
656 | } else { | ||
657 | /* Resume requested, | ||
658 | * disable autosleep | ||
659 | */ | ||
660 | s->suspended = 0; | ||
661 | max3107_set_sleep(s, MAX3107_DISABLE_AUTOSLEEP); | ||
662 | } | ||
663 | } | ||
664 | EXPORT_SYMBOL_GPL(max3107_hw_susp); | ||
665 | |||
666 | /* Modem status IRQ enabling */ | ||
667 | static void max3107_enable_ms(struct uart_port *port) | ||
668 | { | ||
669 | /* Modem status not supported */ | ||
670 | } | ||
671 | |||
672 | /* Data send function */ | ||
673 | static void max3107_start_tx(struct uart_port *port) | ||
674 | { | ||
675 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
676 | |||
677 | /* Trigger work thread for sending data */ | ||
678 | max3107_dowork(s); | ||
679 | } | ||
680 | |||
681 | /* Function for checking that there is no pending transfers */ | ||
682 | static unsigned int max3107_tx_empty(struct uart_port *port) | ||
683 | { | ||
684 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
685 | |||
686 | pr_debug("returning %d\n", | ||
687 | (s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit))); | ||
688 | return s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit); | ||
689 | } | ||
690 | |||
691 | /* Function for stopping RX */ | ||
692 | static void max3107_stop_rx(struct uart_port *port) | ||
693 | { | ||
694 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
695 | unsigned long flags; | ||
696 | |||
697 | /* Set RX disabled in MODE 1 register */ | ||
698 | spin_lock_irqsave(&s->data_lock, flags); | ||
699 | s->mode1_reg |= MAX3107_MODE1_RXDIS_BIT; | ||
700 | s->mode1_commit = 1; | ||
701 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
702 | /* Set RX disabled */ | ||
703 | s->rx_enabled = 0; | ||
704 | /* Trigger work thread for doing the actual configuration change */ | ||
705 | max3107_dowork(s); | ||
706 | } | ||
707 | |||
708 | /* Function for returning control pin states */ | ||
709 | static unsigned int max3107_get_mctrl(struct uart_port *port) | ||
710 | { | ||
711 | /* DCD and DSR are not wired and CTS/RTS is handled automatically | ||
712 | * so just indicate DSR and CAR asserted | ||
713 | */ | ||
714 | return TIOCM_DSR | TIOCM_CAR; | ||
715 | } | ||
716 | |||
717 | /* Function for setting control pin states */ | ||
718 | static void max3107_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
719 | { | ||
720 | /* DCD and DSR are not wired and CTS/RTS is hadnled automatically | ||
721 | * so do nothing | ||
722 | */ | ||
723 | } | ||
724 | |||
725 | /* Function for configuring UART parameters */ | ||
726 | static void max3107_set_termios(struct uart_port *port, | ||
727 | struct ktermios *termios, | ||
728 | struct ktermios *old) | ||
729 | { | ||
730 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
731 | struct tty_struct *tty; | ||
732 | int baud; | ||
733 | u16 new_lcr = 0; | ||
734 | u32 new_brg = 0; | ||
735 | unsigned long flags; | ||
736 | |||
737 | if (!port->state) | ||
738 | return; | ||
739 | |||
740 | tty = port->state->port.tty; | ||
741 | if (!tty) | ||
742 | return; | ||
743 | |||
744 | /* Get new LCR register values */ | ||
745 | /* Word size */ | ||
746 | if ((termios->c_cflag & CSIZE) == CS7) | ||
747 | new_lcr |= MAX3107_LCR_WORD_LEN_7; | ||
748 | else | ||
749 | new_lcr |= MAX3107_LCR_WORD_LEN_8; | ||
750 | |||
751 | /* Parity */ | ||
752 | if (termios->c_cflag & PARENB) { | ||
753 | new_lcr |= MAX3107_LCR_PARITY_BIT; | ||
754 | if (!(termios->c_cflag & PARODD)) | ||
755 | new_lcr |= MAX3107_LCR_EVENPARITY_BIT; | ||
756 | } | ||
757 | |||
758 | /* Stop bits */ | ||
759 | if (termios->c_cflag & CSTOPB) { | ||
760 | /* 2 stop bits */ | ||
761 | new_lcr |= MAX3107_LCR_STOPLEN_BIT; | ||
762 | } | ||
763 | |||
764 | /* Mask termios capabilities we don't support */ | ||
765 | termios->c_cflag &= ~CMSPAR; | ||
766 | |||
767 | /* Set status ignore mask */ | ||
768 | s->port.ignore_status_mask = 0; | ||
769 | if (termios->c_iflag & IGNPAR) | ||
770 | s->port.ignore_status_mask |= MAX3107_ALL_ERRORS; | ||
771 | |||
772 | /* Set low latency to immediately handle pushed data */ | ||
773 | s->port.state->port.tty->low_latency = 1; | ||
774 | |||
775 | /* Get new baud rate generator configuration */ | ||
776 | baud = tty_get_baud_rate(tty); | ||
777 | |||
778 | spin_lock_irqsave(&s->data_lock, flags); | ||
779 | new_brg = get_new_brg(baud, s); | ||
780 | /* if can't find the corrent config, use previous */ | ||
781 | if (!new_brg) { | ||
782 | baud = s->baud; | ||
783 | new_brg = s->brg_cfg; | ||
784 | } | ||
785 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
786 | tty_termios_encode_baud_rate(termios, baud, baud); | ||
787 | s->baud = baud; | ||
788 | |||
789 | /* Update timeout according to new baud rate */ | ||
790 | uart_update_timeout(port, termios->c_cflag, baud); | ||
791 | |||
792 | spin_lock_irqsave(&s->data_lock, flags); | ||
793 | if (s->lcr_reg != new_lcr) { | ||
794 | s->lcr_reg = new_lcr; | ||
795 | s->lcr_commit = 1; | ||
796 | } | ||
797 | if (s->brg_cfg != new_brg) { | ||
798 | s->brg_cfg = new_brg; | ||
799 | s->brg_commit = 1; | ||
800 | } | ||
801 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
802 | |||
803 | /* Trigger work thread for doing the actual configuration change */ | ||
804 | max3107_dowork(s); | ||
805 | } | ||
806 | |||
807 | /* Port shutdown function */ | ||
808 | static void max3107_shutdown(struct uart_port *port) | ||
809 | { | ||
810 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
811 | |||
812 | if (s->suspended && s->pdata->hw_suspend) | ||
813 | s->pdata->hw_suspend(s, 0); | ||
814 | |||
815 | /* Free the interrupt */ | ||
816 | free_irq(s->spi->irq, s); | ||
817 | |||
818 | if (s->workqueue) { | ||
819 | /* Flush and destroy work queue */ | ||
820 | flush_workqueue(s->workqueue); | ||
821 | destroy_workqueue(s->workqueue); | ||
822 | s->workqueue = NULL; | ||
823 | } | ||
824 | |||
825 | /* Suspend HW */ | ||
826 | if (s->pdata->hw_suspend) | ||
827 | s->pdata->hw_suspend(s, 1); | ||
828 | } | ||
829 | |||
830 | /* Port startup function */ | ||
831 | static int max3107_startup(struct uart_port *port) | ||
832 | { | ||
833 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
834 | |||
835 | /* Initialize work queue */ | ||
836 | s->workqueue = create_freezeable_workqueue("max3107"); | ||
837 | if (!s->workqueue) { | ||
838 | dev_err(&s->spi->dev, "Workqueue creation failed\n"); | ||
839 | return -EBUSY; | ||
840 | } | ||
841 | INIT_WORK(&s->work, max3107_work); | ||
842 | |||
843 | /* Setup IRQ */ | ||
844 | if (request_irq(s->spi->irq, max3107_irq, IRQF_TRIGGER_FALLING, | ||
845 | "max3107", s)) { | ||
846 | dev_err(&s->spi->dev, "IRQ reguest failed\n"); | ||
847 | destroy_workqueue(s->workqueue); | ||
848 | s->workqueue = NULL; | ||
849 | return -EBUSY; | ||
850 | } | ||
851 | |||
852 | /* Resume HW */ | ||
853 | if (s->pdata->hw_suspend) | ||
854 | s->pdata->hw_suspend(s, 0); | ||
855 | |||
856 | /* Init registers */ | ||
857 | max3107_register_init(s); | ||
858 | |||
859 | return 0; | ||
860 | } | ||
861 | |||
862 | /* Port type function */ | ||
863 | static const char *max3107_type(struct uart_port *port) | ||
864 | { | ||
865 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
866 | return s->spi->modalias; | ||
867 | } | ||
868 | |||
869 | /* Port release function */ | ||
870 | static void max3107_release_port(struct uart_port *port) | ||
871 | { | ||
872 | /* Do nothing */ | ||
873 | } | ||
874 | |||
875 | /* Port request function */ | ||
876 | static int max3107_request_port(struct uart_port *port) | ||
877 | { | ||
878 | /* Do nothing */ | ||
879 | return 0; | ||
880 | } | ||
881 | |||
882 | /* Port config function */ | ||
883 | static void max3107_config_port(struct uart_port *port, int flags) | ||
884 | { | ||
885 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
886 | s->port.type = PORT_MAX3107; | ||
887 | } | ||
888 | |||
889 | /* Port verify function */ | ||
890 | static int max3107_verify_port(struct uart_port *port, | ||
891 | struct serial_struct *ser) | ||
892 | { | ||
893 | if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3107) | ||
894 | return 0; | ||
895 | |||
896 | return -EINVAL; | ||
897 | } | ||
898 | |||
899 | /* Port stop TX function */ | ||
900 | static void max3107_stop_tx(struct uart_port *port) | ||
901 | { | ||
902 | /* Do nothing */ | ||
903 | } | ||
904 | |||
905 | /* Port break control function */ | ||
906 | static void max3107_break_ctl(struct uart_port *port, int break_state) | ||
907 | { | ||
908 | /* We don't support break control, do nothing */ | ||
909 | } | ||
910 | |||
911 | |||
912 | /* Port functions */ | ||
913 | static struct uart_ops max3107_ops = { | ||
914 | .tx_empty = max3107_tx_empty, | ||
915 | .set_mctrl = max3107_set_mctrl, | ||
916 | .get_mctrl = max3107_get_mctrl, | ||
917 | .stop_tx = max3107_stop_tx, | ||
918 | .start_tx = max3107_start_tx, | ||
919 | .stop_rx = max3107_stop_rx, | ||
920 | .enable_ms = max3107_enable_ms, | ||
921 | .break_ctl = max3107_break_ctl, | ||
922 | .startup = max3107_startup, | ||
923 | .shutdown = max3107_shutdown, | ||
924 | .set_termios = max3107_set_termios, | ||
925 | .type = max3107_type, | ||
926 | .release_port = max3107_release_port, | ||
927 | .request_port = max3107_request_port, | ||
928 | .config_port = max3107_config_port, | ||
929 | .verify_port = max3107_verify_port, | ||
930 | }; | ||
931 | |||
932 | /* UART driver data */ | ||
933 | static struct uart_driver max3107_uart_driver = { | ||
934 | .owner = THIS_MODULE, | ||
935 | .driver_name = "ttyMAX", | ||
936 | .dev_name = "ttyMAX", | ||
937 | .nr = 1, | ||
938 | }; | ||
939 | |||
940 | static int driver_registered = 0; | ||
941 | |||
942 | |||
943 | |||
944 | /* 'Generic' platform data */ | ||
945 | static struct max3107_plat generic_plat_data = { | ||
946 | .loopback = 0, | ||
947 | .ext_clk = 1, | ||
948 | .hw_suspend = max3107_hw_susp, | ||
949 | .polled_mode = 0, | ||
950 | .poll_time = 0, | ||
951 | }; | ||
952 | |||
953 | |||
954 | /*******************************************************************/ | ||
955 | |||
956 | /** | ||
957 | * max3107_probe - SPI bus probe entry point | ||
958 | * @spi: the spi device | ||
959 | * | ||
960 | * SPI wants us to probe this device and if appropriate claim it. | ||
961 | * Perform any platform specific requirements and then initialise | ||
962 | * the device. | ||
963 | */ | ||
964 | |||
965 | int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata) | ||
966 | { | ||
967 | struct max3107_port *s; | ||
968 | u16 buf[2]; /* Buffer for SPI transfers */ | ||
969 | int retval; | ||
970 | |||
971 | pr_info("enter max3107 probe\n"); | ||
972 | |||
973 | /* Allocate port structure */ | ||
974 | s = kzalloc(sizeof(*s), GFP_KERNEL); | ||
975 | if (!s) { | ||
976 | pr_err("Allocating port structure failed\n"); | ||
977 | return -ENOMEM; | ||
978 | } | ||
979 | |||
980 | s->pdata = pdata; | ||
981 | |||
982 | /* SPI Rx buffer | ||
983 | * +2 for RX FIFO interrupt | ||
984 | * disabling and RX level query | ||
985 | */ | ||
986 | s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL); | ||
987 | if (!s->rxbuf) { | ||
988 | pr_err("Allocating RX buffer failed\n"); | ||
989 | return -ENOMEM; | ||
990 | } | ||
991 | s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL); | ||
992 | if (!s->rxstr) { | ||
993 | pr_err("Allocating RX buffer failed\n"); | ||
994 | return -ENOMEM; | ||
995 | } | ||
996 | /* SPI Tx buffer | ||
997 | * SPI transfer buffer | ||
998 | * +3 for TX FIFO empty | ||
999 | * interrupt disabling and | ||
1000 | * enabling and TX enabling | ||
1001 | */ | ||
1002 | s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL); | ||
1003 | if (!s->txbuf) { | ||
1004 | pr_err("Allocating TX buffer failed\n"); | ||
1005 | return -ENOMEM; | ||
1006 | } | ||
1007 | /* Initialize shared data lock */ | ||
1008 | spin_lock_init(&s->data_lock); | ||
1009 | |||
1010 | /* SPI intializations */ | ||
1011 | dev_set_drvdata(&spi->dev, s); | ||
1012 | spi->mode = SPI_MODE_0; | ||
1013 | spi->dev.platform_data = pdata; | ||
1014 | spi->bits_per_word = 16; | ||
1015 | s->ext_clk = pdata->ext_clk; | ||
1016 | s->loopback = pdata->loopback; | ||
1017 | spi_setup(spi); | ||
1018 | s->spi = spi; | ||
1019 | |||
1020 | /* Check REV ID to ensure we are talking to what we expect */ | ||
1021 | buf[0] = MAX3107_REVID_REG; | ||
1022 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { | ||
1023 | dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n"); | ||
1024 | return -EIO; | ||
1025 | } | ||
1026 | if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 && | ||
1027 | (buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) { | ||
1028 | dev_err(&s->spi->dev, "REVID %x does not match\n", | ||
1029 | (buf[0] & MAX3107_SPI_RX_DATA_MASK)); | ||
1030 | return -ENODEV; | ||
1031 | } | ||
1032 | |||
1033 | /* Disable all interrupts */ | ||
1034 | buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG | 0x0000); | ||
1035 | buf[0] |= 0x0000; | ||
1036 | |||
1037 | /* Configure clock source */ | ||
1038 | buf[1] = (MAX3107_WRITE_BIT | MAX3107_CLKSRC_REG); | ||
1039 | if (s->ext_clk) { | ||
1040 | /* External clock */ | ||
1041 | buf[1] |= MAX3107_CLKSRC_EXTCLK_BIT; | ||
1042 | } | ||
1043 | |||
1044 | /* PLL bypass ON */ | ||
1045 | buf[1] |= MAX3107_CLKSRC_PLLBYP_BIT; | ||
1046 | |||
1047 | /* Perform SPI transfer */ | ||
1048 | if (max3107_rw(s, (u8 *)buf, NULL, 4)) { | ||
1049 | dev_err(&s->spi->dev, "SPI transfer for init failed\n"); | ||
1050 | return -EIO; | ||
1051 | } | ||
1052 | |||
1053 | /* Register UART driver */ | ||
1054 | if (!driver_registered) { | ||
1055 | retval = uart_register_driver(&max3107_uart_driver); | ||
1056 | if (retval) { | ||
1057 | dev_err(&s->spi->dev, "Registering UART driver failed\n"); | ||
1058 | return retval; | ||
1059 | } | ||
1060 | driver_registered = 1; | ||
1061 | } | ||
1062 | |||
1063 | /* Initialize UART port data */ | ||
1064 | s->port.fifosize = 128; | ||
1065 | s->port.ops = &max3107_ops; | ||
1066 | s->port.line = 0; | ||
1067 | s->port.dev = &spi->dev; | ||
1068 | s->port.uartclk = 9600; | ||
1069 | s->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; | ||
1070 | s->port.irq = s->spi->irq; | ||
1071 | s->port.type = PORT_MAX3107; | ||
1072 | |||
1073 | /* Add UART port */ | ||
1074 | retval = uart_add_one_port(&max3107_uart_driver, &s->port); | ||
1075 | if (retval < 0) { | ||
1076 | dev_err(&s->spi->dev, "Adding UART port failed\n"); | ||
1077 | return retval; | ||
1078 | } | ||
1079 | |||
1080 | if (pdata->configure) { | ||
1081 | retval = pdata->configure(s); | ||
1082 | if (retval < 0) | ||
1083 | return retval; | ||
1084 | } | ||
1085 | |||
1086 | /* Go to suspend mode */ | ||
1087 | if (pdata->hw_suspend) | ||
1088 | pdata->hw_suspend(s, 1); | ||
1089 | |||
1090 | return 0; | ||
1091 | } | ||
1092 | EXPORT_SYMBOL_GPL(max3107_probe); | ||
1093 | |||
1094 | /* Driver remove function */ | ||
1095 | int max3107_remove(struct spi_device *spi) | ||
1096 | { | ||
1097 | struct max3107_port *s = dev_get_drvdata(&spi->dev); | ||
1098 | |||
1099 | pr_info("enter max3107 remove\n"); | ||
1100 | |||
1101 | /* Remove port */ | ||
1102 | if (uart_remove_one_port(&max3107_uart_driver, &s->port)) | ||
1103 | dev_warn(&s->spi->dev, "Removing UART port failed\n"); | ||
1104 | |||
1105 | |||
1106 | /* Free TxRx buffer */ | ||
1107 | kfree(s->rxbuf); | ||
1108 | kfree(s->rxstr); | ||
1109 | kfree(s->txbuf); | ||
1110 | |||
1111 | /* Free port structure */ | ||
1112 | kfree(s); | ||
1113 | |||
1114 | return 0; | ||
1115 | } | ||
1116 | EXPORT_SYMBOL_GPL(max3107_remove); | ||
1117 | |||
1118 | /* Driver suspend function */ | ||
1119 | int max3107_suspend(struct spi_device *spi, pm_message_t state) | ||
1120 | { | ||
1121 | #ifdef CONFIG_PM | ||
1122 | struct max3107_port *s = dev_get_drvdata(&spi->dev); | ||
1123 | |||
1124 | pr_debug("enter suspend\n"); | ||
1125 | |||
1126 | /* Suspend UART port */ | ||
1127 | uart_suspend_port(&max3107_uart_driver, &s->port); | ||
1128 | |||
1129 | /* Go to suspend mode */ | ||
1130 | if (s->pdata->hw_suspend) | ||
1131 | s->pdata->hw_suspend(s, 1); | ||
1132 | #endif /* CONFIG_PM */ | ||
1133 | return 0; | ||
1134 | } | ||
1135 | EXPORT_SYMBOL_GPL(max3107_suspend); | ||
1136 | |||
1137 | /* Driver resume function */ | ||
1138 | int max3107_resume(struct spi_device *spi) | ||
1139 | { | ||
1140 | #ifdef CONFIG_PM | ||
1141 | struct max3107_port *s = dev_get_drvdata(&spi->dev); | ||
1142 | |||
1143 | pr_debug("enter resume\n"); | ||
1144 | |||
1145 | /* Resume from suspend */ | ||
1146 | if (s->pdata->hw_suspend) | ||
1147 | s->pdata->hw_suspend(s, 0); | ||
1148 | |||
1149 | /* Resume UART port */ | ||
1150 | uart_resume_port(&max3107_uart_driver, &s->port); | ||
1151 | #endif /* CONFIG_PM */ | ||
1152 | return 0; | ||
1153 | } | ||
1154 | EXPORT_SYMBOL_GPL(max3107_resume); | ||
1155 | |||
1156 | static int max3107_probe_generic(struct spi_device *spi) | ||
1157 | { | ||
1158 | return max3107_probe(spi, &generic_plat_data); | ||
1159 | } | ||
1160 | |||
1161 | /* Spi driver data */ | ||
1162 | static struct spi_driver max3107_driver = { | ||
1163 | .driver = { | ||
1164 | .name = "max3107", | ||
1165 | .bus = &spi_bus_type, | ||
1166 | .owner = THIS_MODULE, | ||
1167 | }, | ||
1168 | .probe = max3107_probe_generic, | ||
1169 | .remove = __devexit_p(max3107_remove), | ||
1170 | .suspend = max3107_suspend, | ||
1171 | .resume = max3107_resume, | ||
1172 | }; | ||
1173 | |||
1174 | /* Driver init function */ | ||
1175 | static int __init max3107_init(void) | ||
1176 | { | ||
1177 | pr_info("enter max3107 init\n"); | ||
1178 | return spi_register_driver(&max3107_driver); | ||
1179 | } | ||
1180 | |||
1181 | /* Driver exit function */ | ||
1182 | static void __exit max3107_exit(void) | ||
1183 | { | ||
1184 | pr_info("enter max3107 exit\n"); | ||
1185 | /* Unregister UART driver */ | ||
1186 | if (driver_registered) | ||
1187 | uart_unregister_driver(&max3107_uart_driver); | ||
1188 | spi_unregister_driver(&max3107_driver); | ||
1189 | } | ||
1190 | |||
1191 | module_init(max3107_init); | ||
1192 | module_exit(max3107_exit); | ||
1193 | |||
1194 | MODULE_DESCRIPTION("MAX3107 driver"); | ||
1195 | MODULE_AUTHOR("Aavamobile"); | ||
1196 | MODULE_ALIAS("max3107-spi"); | ||
1197 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/serial/max3107.h b/drivers/serial/max3107.h new file mode 100644 index 000000000000..7ab632392502 --- /dev/null +++ b/drivers/serial/max3107.h | |||
@@ -0,0 +1,441 @@ | |||
1 | /* | ||
2 | * max3107.h - spi uart protocol driver header for Maxim 3107 | ||
3 | * | ||
4 | * Copyright (C) Aavamobile 2009 | ||
5 | * Based on serial_max3100.h by Christian Pellegrin | ||
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 | #ifndef _MAX3107_H | ||
14 | #define _MAX3107_H | ||
15 | |||
16 | /* Serial error status definitions */ | ||
17 | #define MAX3107_PARITY_ERROR 1 | ||
18 | #define MAX3107_FRAME_ERROR 2 | ||
19 | #define MAX3107_OVERRUN_ERROR 4 | ||
20 | #define MAX3107_ALL_ERRORS (MAX3107_PARITY_ERROR | \ | ||
21 | MAX3107_FRAME_ERROR | \ | ||
22 | MAX3107_OVERRUN_ERROR) | ||
23 | |||
24 | /* GPIO definitions */ | ||
25 | #define MAX3107_GPIO_BASE 88 | ||
26 | #define MAX3107_GPIO_COUNT 4 | ||
27 | |||
28 | |||
29 | /* GPIO connected to chip's reset pin */ | ||
30 | #define MAX3107_RESET_GPIO 87 | ||
31 | |||
32 | |||
33 | /* Chip reset delay */ | ||
34 | #define MAX3107_RESET_DELAY 10 | ||
35 | |||
36 | /* Chip wakeup delay */ | ||
37 | #define MAX3107_WAKEUP_DELAY 50 | ||
38 | |||
39 | |||
40 | /* Sleep mode definitions */ | ||
41 | #define MAX3107_DISABLE_FORCED_SLEEP 0 | ||
42 | #define MAX3107_ENABLE_FORCED_SLEEP 1 | ||
43 | #define MAX3107_DISABLE_AUTOSLEEP 2 | ||
44 | #define MAX3107_ENABLE_AUTOSLEEP 3 | ||
45 | |||
46 | |||
47 | /* Definitions for register access with SPI transfers | ||
48 | * | ||
49 | * SPI transfer format: | ||
50 | * | ||
51 | * Master to slave bits xzzzzzzzyyyyyyyy | ||
52 | * Slave to master bits aaaaaaaabbbbbbbb | ||
53 | * | ||
54 | * where: | ||
55 | * x = 0 for reads, 1 for writes | ||
56 | * z = register address | ||
57 | * y = new register value if write, 0 if read | ||
58 | * a = unspecified | ||
59 | * b = register value if read, unspecified if write | ||
60 | */ | ||
61 | |||
62 | /* SPI speed */ | ||
63 | #define MAX3107_SPI_SPEED (3125000 * 2) | ||
64 | |||
65 | /* Write bit */ | ||
66 | #define MAX3107_WRITE_BIT (1 << 15) | ||
67 | |||
68 | /* SPI TX data mask */ | ||
69 | #define MAX3107_SPI_RX_DATA_MASK (0x00ff) | ||
70 | |||
71 | /* SPI RX data mask */ | ||
72 | #define MAX3107_SPI_TX_DATA_MASK (0x00ff) | ||
73 | |||
74 | /* Register access masks */ | ||
75 | #define MAX3107_RHR_REG (0x0000) /* RX FIFO */ | ||
76 | #define MAX3107_THR_REG (0x0000) /* TX FIFO */ | ||
77 | #define MAX3107_IRQEN_REG (0x0100) /* IRQ enable */ | ||
78 | #define MAX3107_IRQSTS_REG (0x0200) /* IRQ status */ | ||
79 | #define MAX3107_LSR_IRQEN_REG (0x0300) /* LSR IRQ enable */ | ||
80 | #define MAX3107_LSR_IRQSTS_REG (0x0400) /* LSR IRQ status */ | ||
81 | #define MAX3107_SPCHR_IRQEN_REG (0x0500) /* Special char IRQ enable */ | ||
82 | #define MAX3107_SPCHR_IRQSTS_REG (0x0600) /* Special char IRQ status */ | ||
83 | #define MAX3107_STS_IRQEN_REG (0x0700) /* Status IRQ enable */ | ||
84 | #define MAX3107_STS_IRQSTS_REG (0x0800) /* Status IRQ status */ | ||
85 | #define MAX3107_MODE1_REG (0x0900) /* MODE1 */ | ||
86 | #define MAX3107_MODE2_REG (0x0a00) /* MODE2 */ | ||
87 | #define MAX3107_LCR_REG (0x0b00) /* LCR */ | ||
88 | #define MAX3107_RXTO_REG (0x0c00) /* RX timeout */ | ||
89 | #define MAX3107_HDPIXDELAY_REG (0x0d00) /* Auto transceiver delays */ | ||
90 | #define MAX3107_IRDA_REG (0x0e00) /* IRDA settings */ | ||
91 | #define MAX3107_FLOWLVL_REG (0x0f00) /* Flow control levels */ | ||
92 | #define MAX3107_FIFOTRIGLVL_REG (0x1000) /* FIFO IRQ trigger levels */ | ||
93 | #define MAX3107_TXFIFOLVL_REG (0x1100) /* TX FIFO level */ | ||
94 | #define MAX3107_RXFIFOLVL_REG (0x1200) /* RX FIFO level */ | ||
95 | #define MAX3107_FLOWCTRL_REG (0x1300) /* Flow control */ | ||
96 | #define MAX3107_XON1_REG (0x1400) /* XON1 character */ | ||
97 | #define MAX3107_XON2_REG (0x1500) /* XON2 character */ | ||
98 | #define MAX3107_XOFF1_REG (0x1600) /* XOFF1 character */ | ||
99 | #define MAX3107_XOFF2_REG (0x1700) /* XOFF2 character */ | ||
100 | #define MAX3107_GPIOCFG_REG (0x1800) /* GPIO config */ | ||
101 | #define MAX3107_GPIODATA_REG (0x1900) /* GPIO data */ | ||
102 | #define MAX3107_PLLCFG_REG (0x1a00) /* PLL config */ | ||
103 | #define MAX3107_BRGCFG_REG (0x1b00) /* Baud rate generator conf */ | ||
104 | #define MAX3107_BRGDIVLSB_REG (0x1c00) /* Baud rate divisor LSB */ | ||
105 | #define MAX3107_BRGDIVMSB_REG (0x1d00) /* Baud rate divisor MSB */ | ||
106 | #define MAX3107_CLKSRC_REG (0x1e00) /* Clock source */ | ||
107 | #define MAX3107_REVID_REG (0x1f00) /* Revision identification */ | ||
108 | |||
109 | /* IRQ register bits */ | ||
110 | #define MAX3107_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */ | ||
111 | #define MAX3107_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */ | ||
112 | #define MAX3107_IRQ_STS_BIT (1 << 2) /* Status interrupt */ | ||
113 | #define MAX3107_IRQ_RXFIFO_BIT (1 << 3) /* RX FIFO interrupt */ | ||
114 | #define MAX3107_IRQ_TXFIFO_BIT (1 << 4) /* TX FIFO interrupt */ | ||
115 | #define MAX3107_IRQ_TXEMPTY_BIT (1 << 5) /* TX FIFO empty interrupt */ | ||
116 | #define MAX3107_IRQ_RXEMPTY_BIT (1 << 6) /* RX FIFO empty interrupt */ | ||
117 | #define MAX3107_IRQ_CTS_BIT (1 << 7) /* CTS interrupt */ | ||
118 | |||
119 | /* LSR register bits */ | ||
120 | #define MAX3107_LSR_RXTO_BIT (1 << 0) /* RX timeout */ | ||
121 | #define MAX3107_LSR_RXOVR_BIT (1 << 1) /* RX overrun */ | ||
122 | #define MAX3107_LSR_RXPAR_BIT (1 << 2) /* RX parity error */ | ||
123 | #define MAX3107_LSR_FRERR_BIT (1 << 3) /* Frame error */ | ||
124 | #define MAX3107_LSR_RXBRK_BIT (1 << 4) /* RX break */ | ||
125 | #define MAX3107_LSR_RXNOISE_BIT (1 << 5) /* RX noise */ | ||
126 | #define MAX3107_LSR_UNDEF6_BIT (1 << 6) /* Undefined/not used */ | ||
127 | #define MAX3107_LSR_CTS_BIT (1 << 7) /* CTS pin state */ | ||
128 | |||
129 | /* Special character register bits */ | ||
130 | #define MAX3107_SPCHR_XON1_BIT (1 << 0) /* XON1 character */ | ||
131 | #define MAX3107_SPCHR_XON2_BIT (1 << 1) /* XON2 character */ | ||
132 | #define MAX3107_SPCHR_XOFF1_BIT (1 << 2) /* XOFF1 character */ | ||
133 | #define MAX3107_SPCHR_XOFF2_BIT (1 << 3) /* XOFF2 character */ | ||
134 | #define MAX3107_SPCHR_BREAK_BIT (1 << 4) /* RX break */ | ||
135 | #define MAX3107_SPCHR_MULTIDROP_BIT (1 << 5) /* 9-bit multidrop addr char */ | ||
136 | #define MAX3107_SPCHR_UNDEF6_BIT (1 << 6) /* Undefined/not used */ | ||
137 | #define MAX3107_SPCHR_UNDEF7_BIT (1 << 7) /* Undefined/not used */ | ||
138 | |||
139 | /* Status register bits */ | ||
140 | #define MAX3107_STS_GPIO0_BIT (1 << 0) /* GPIO 0 interrupt */ | ||
141 | #define MAX3107_STS_GPIO1_BIT (1 << 1) /* GPIO 1 interrupt */ | ||
142 | #define MAX3107_STS_GPIO2_BIT (1 << 2) /* GPIO 2 interrupt */ | ||
143 | #define MAX3107_STS_GPIO3_BIT (1 << 3) /* GPIO 3 interrupt */ | ||
144 | #define MAX3107_STS_UNDEF4_BIT (1 << 4) /* Undefined/not used */ | ||
145 | #define MAX3107_STS_CLKREADY_BIT (1 << 5) /* Clock ready */ | ||
146 | #define MAX3107_STS_SLEEP_BIT (1 << 6) /* Sleep interrupt */ | ||
147 | #define MAX3107_STS_UNDEF7_BIT (1 << 7) /* Undefined/not used */ | ||
148 | |||
149 | /* MODE1 register bits */ | ||
150 | #define MAX3107_MODE1_RXDIS_BIT (1 << 0) /* RX disable */ | ||
151 | #define MAX3107_MODE1_TXDIS_BIT (1 << 1) /* TX disable */ | ||
152 | #define MAX3107_MODE1_TXHIZ_BIT (1 << 2) /* TX pin three-state */ | ||
153 | #define MAX3107_MODE1_RTSHIZ_BIT (1 << 3) /* RTS pin three-state */ | ||
154 | #define MAX3107_MODE1_TRNSCVCTRL_BIT (1 << 4) /* Transceiver ctrl enable */ | ||
155 | #define MAX3107_MODE1_FORCESLEEP_BIT (1 << 5) /* Force sleep mode */ | ||
156 | #define MAX3107_MODE1_AUTOSLEEP_BIT (1 << 6) /* Auto sleep enable */ | ||
157 | #define MAX3107_MODE1_IRQSEL_BIT (1 << 7) /* IRQ pin enable */ | ||
158 | |||
159 | /* MODE2 register bits */ | ||
160 | #define MAX3107_MODE2_RST_BIT (1 << 0) /* Chip reset */ | ||
161 | #define MAX3107_MODE2_FIFORST_BIT (1 << 1) /* FIFO reset */ | ||
162 | #define MAX3107_MODE2_RXTRIGINV_BIT (1 << 2) /* RX FIFO INT invert */ | ||
163 | #define MAX3107_MODE2_RXEMPTINV_BIT (1 << 3) /* RX FIFO empty INT invert */ | ||
164 | #define MAX3107_MODE2_SPCHR_BIT (1 << 4) /* Special chr detect enable */ | ||
165 | #define MAX3107_MODE2_LOOPBACK_BIT (1 << 5) /* Internal loopback enable */ | ||
166 | #define MAX3107_MODE2_MULTIDROP_BIT (1 << 6) /* 9-bit multidrop enable */ | ||
167 | #define MAX3107_MODE2_ECHOSUPR_BIT (1 << 7) /* ECHO suppression enable */ | ||
168 | |||
169 | /* LCR register bits */ | ||
170 | #define MAX3107_LCR_LENGTH0_BIT (1 << 0) /* Word length bit 0 */ | ||
171 | #define MAX3107_LCR_LENGTH1_BIT (1 << 1) /* Word length bit 1 | ||
172 | * | ||
173 | * Word length bits table: | ||
174 | * 00 -> 5 bit words | ||
175 | * 01 -> 6 bit words | ||
176 | * 10 -> 7 bit words | ||
177 | * 11 -> 8 bit words | ||
178 | */ | ||
179 | #define MAX3107_LCR_STOPLEN_BIT (1 << 2) /* STOP length bit | ||
180 | * | ||
181 | * STOP length bit table: | ||
182 | * 0 -> 1 stop bit | ||
183 | * 1 -> 1-1.5 stop bits if | ||
184 | * word length is 5, | ||
185 | * 2 stop bits otherwise | ||
186 | */ | ||
187 | #define MAX3107_LCR_PARITY_BIT (1 << 3) /* Parity bit enable */ | ||
188 | #define MAX3107_LCR_EVENPARITY_BIT (1 << 4) /* Even parity bit enable */ | ||
189 | #define MAX3107_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */ | ||
190 | #define MAX3107_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */ | ||
191 | #define MAX3107_LCR_RTS_BIT (1 << 7) /* RTS pin control */ | ||
192 | #define MAX3107_LCR_WORD_LEN_5 (0x0000) | ||
193 | #define MAX3107_LCR_WORD_LEN_6 (0x0001) | ||
194 | #define MAX3107_LCR_WORD_LEN_7 (0x0002) | ||
195 | #define MAX3107_LCR_WORD_LEN_8 (0x0003) | ||
196 | |||
197 | |||
198 | /* IRDA register bits */ | ||
199 | #define MAX3107_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */ | ||
200 | #define MAX3107_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */ | ||
201 | #define MAX3107_IRDA_SHORTIR_BIT (1 << 2) /* Short SIR mode enable */ | ||
202 | #define MAX3107_IRDA_MIR_BIT (1 << 3) /* MIR mode enable */ | ||
203 | #define MAX3107_IRDA_RXINV_BIT (1 << 4) /* RX logic inversion enable */ | ||
204 | #define MAX3107_IRDA_TXINV_BIT (1 << 5) /* TX logic inversion enable */ | ||
205 | #define MAX3107_IRDA_UNDEF6_BIT (1 << 6) /* Undefined/not used */ | ||
206 | #define MAX3107_IRDA_UNDEF7_BIT (1 << 7) /* Undefined/not used */ | ||
207 | |||
208 | /* Flow control trigger level register masks */ | ||
209 | #define MAX3107_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */ | ||
210 | #define MAX3107_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */ | ||
211 | #define MAX3107_FLOWLVL_HALT(words) ((words/8) & 0x000f) | ||
212 | #define MAX3107_FLOWLVL_RES(words) (((words/8) & 0x000f) << 4) | ||
213 | |||
214 | /* FIFO interrupt trigger level register masks */ | ||
215 | #define MAX3107_FIFOTRIGLVL_TX_MASK (0x000f) /* TX FIFO trigger level */ | ||
216 | #define MAX3107_FIFOTRIGLVL_RX_MASK (0x00f0) /* RX FIFO trigger level */ | ||
217 | #define MAX3107_FIFOTRIGLVL_TX(words) ((words/8) & 0x000f) | ||
218 | #define MAX3107_FIFOTRIGLVL_RX(words) (((words/8) & 0x000f) << 4) | ||
219 | |||
220 | /* Flow control register bits */ | ||
221 | #define MAX3107_FLOWCTRL_AUTORTS_BIT (1 << 0) /* Auto RTS flow ctrl enable */ | ||
222 | #define MAX3107_FLOWCTRL_AUTOCTS_BIT (1 << 1) /* Auto CTS flow ctrl enable */ | ||
223 | #define MAX3107_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs | ||
224 | * are used in conjunction with | ||
225 | * XOFF2 for definition of | ||
226 | * special character */ | ||
227 | #define MAX3107_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */ | ||
228 | #define MAX3107_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */ | ||
229 | #define MAX3107_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1 | ||
230 | * | ||
231 | * SWFLOW bits 1 & 0 table: | ||
232 | * 00 -> no transmitter flow | ||
233 | * control | ||
234 | * 01 -> receiver compares | ||
235 | * XON2 and XOFF2 | ||
236 | * and controls | ||
237 | * transmitter | ||
238 | * 10 -> receiver compares | ||
239 | * XON1 and XOFF1 | ||
240 | * and controls | ||
241 | * transmitter | ||
242 | * 11 -> receiver compares | ||
243 | * XON1, XON2, XOFF1 and | ||
244 | * XOFF2 and controls | ||
245 | * transmitter | ||
246 | */ | ||
247 | #define MAX3107_FLOWCTRL_SWFLOW2_BIT (1 << 6) /* SWFLOW bit 2 */ | ||
248 | #define MAX3107_FLOWCTRL_SWFLOW3_BIT (1 << 7) /* SWFLOW bit 3 | ||
249 | * | ||
250 | * SWFLOW bits 3 & 2 table: | ||
251 | * 00 -> no received flow | ||
252 | * control | ||
253 | * 01 -> transmitter generates | ||
254 | * XON2 and XOFF2 | ||
255 | * 10 -> transmitter generates | ||
256 | * XON1 and XOFF1 | ||
257 | * 11 -> transmitter generates | ||
258 | * XON1, XON2, XOFF1 and | ||
259 | * XOFF2 | ||
260 | */ | ||
261 | |||
262 | /* GPIO configuration register bits */ | ||
263 | #define MAX3107_GPIOCFG_GP0OUT_BIT (1 << 0) /* GPIO 0 output enable */ | ||
264 | #define MAX3107_GPIOCFG_GP1OUT_BIT (1 << 1) /* GPIO 1 output enable */ | ||
265 | #define MAX3107_GPIOCFG_GP2OUT_BIT (1 << 2) /* GPIO 2 output enable */ | ||
266 | #define MAX3107_GPIOCFG_GP3OUT_BIT (1 << 3) /* GPIO 3 output enable */ | ||
267 | #define MAX3107_GPIOCFG_GP0OD_BIT (1 << 4) /* GPIO 0 open-drain enable */ | ||
268 | #define MAX3107_GPIOCFG_GP1OD_BIT (1 << 5) /* GPIO 1 open-drain enable */ | ||
269 | #define MAX3107_GPIOCFG_GP2OD_BIT (1 << 6) /* GPIO 2 open-drain enable */ | ||
270 | #define MAX3107_GPIOCFG_GP3OD_BIT (1 << 7) /* GPIO 3 open-drain enable */ | ||
271 | |||
272 | /* GPIO DATA register bits */ | ||
273 | #define MAX3107_GPIODATA_GP0OUT_BIT (1 << 0) /* GPIO 0 output value */ | ||
274 | #define MAX3107_GPIODATA_GP1OUT_BIT (1 << 1) /* GPIO 1 output value */ | ||
275 | #define MAX3107_GPIODATA_GP2OUT_BIT (1 << 2) /* GPIO 2 output value */ | ||
276 | #define MAX3107_GPIODATA_GP3OUT_BIT (1 << 3) /* GPIO 3 output value */ | ||
277 | #define MAX3107_GPIODATA_GP0IN_BIT (1 << 4) /* GPIO 0 input value */ | ||
278 | #define MAX3107_GPIODATA_GP1IN_BIT (1 << 5) /* GPIO 1 input value */ | ||
279 | #define MAX3107_GPIODATA_GP2IN_BIT (1 << 6) /* GPIO 2 input value */ | ||
280 | #define MAX3107_GPIODATA_GP3IN_BIT (1 << 7) /* GPIO 3 input value */ | ||
281 | |||
282 | /* PLL configuration register masks */ | ||
283 | #define MAX3107_PLLCFG_PREDIV_MASK (0x003f) /* PLL predivision value */ | ||
284 | #define MAX3107_PLLCFG_PLLFACTOR_MASK (0x00c0) /* PLL multiplication factor */ | ||
285 | |||
286 | /* Baud rate generator configuration register masks and bits */ | ||
287 | #define MAX3107_BRGCFG_FRACT_MASK (0x000f) /* Fractional portion of | ||
288 | * Baud rate generator divisor | ||
289 | */ | ||
290 | #define MAX3107_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */ | ||
291 | #define MAX3107_BRGCFG_4XMODE_BIT (1 << 5) /* Quadruple baud rate */ | ||
292 | #define MAX3107_BRGCFG_UNDEF6_BIT (1 << 6) /* Undefined/not used */ | ||
293 | #define MAX3107_BRGCFG_UNDEF7_BIT (1 << 7) /* Undefined/not used */ | ||
294 | |||
295 | /* Clock source register bits */ | ||
296 | #define MAX3107_CLKSRC_INTOSC_BIT (1 << 0) /* Internal osc enable */ | ||
297 | #define MAX3107_CLKSRC_CRYST_BIT (1 << 1) /* Crystal osc enable */ | ||
298 | #define MAX3107_CLKSRC_PLL_BIT (1 << 2) /* PLL enable */ | ||
299 | #define MAX3107_CLKSRC_PLLBYP_BIT (1 << 3) /* PLL bypass */ | ||
300 | #define MAX3107_CLKSRC_EXTCLK_BIT (1 << 4) /* External clock enable */ | ||
301 | #define MAX3107_CLKSRC_UNDEF5_BIT (1 << 5) /* Undefined/not used */ | ||
302 | #define MAX3107_CLKSRC_UNDEF6_BIT (1 << 6) /* Undefined/not used */ | ||
303 | #define MAX3107_CLKSRC_CLK2RTS_BIT (1 << 7) /* Baud clk to RTS pin */ | ||
304 | |||
305 | |||
306 | /* HW definitions */ | ||
307 | #define MAX3107_RX_FIFO_SIZE 128 | ||
308 | #define MAX3107_TX_FIFO_SIZE 128 | ||
309 | #define MAX3107_REVID1 0x00a0 | ||
310 | #define MAX3107_REVID2 0x00a1 | ||
311 | |||
312 | |||
313 | /* Baud rate generator configuration values for external clock 13MHz */ | ||
314 | #define MAX3107_BRG13_B300 (0x0A9400 | 0x05) | ||
315 | #define MAX3107_BRG13_B600 (0x054A00 | 0x03) | ||
316 | #define MAX3107_BRG13_B1200 (0x02A500 | 0x01) | ||
317 | #define MAX3107_BRG13_B2400 (0x015200 | 0x09) | ||
318 | #define MAX3107_BRG13_B4800 (0x00A900 | 0x04) | ||
319 | #define MAX3107_BRG13_B9600 (0x005400 | 0x0A) | ||
320 | #define MAX3107_BRG13_B19200 (0x002A00 | 0x05) | ||
321 | #define MAX3107_BRG13_B38400 (0x001500 | 0x03) | ||
322 | #define MAX3107_BRG13_B57600 (0x000E00 | 0x02) | ||
323 | #define MAX3107_BRG13_B115200 (0x000700 | 0x01) | ||
324 | #define MAX3107_BRG13_B230400 (0x000300 | 0x08) | ||
325 | #define MAX3107_BRG13_B460800 (0x000100 | 0x0c) | ||
326 | #define MAX3107_BRG13_B921600 (0x000100 | 0x1c) | ||
327 | |||
328 | /* Baud rate generator configuration values for external clock 26MHz */ | ||
329 | #define MAX3107_BRG26_B300 (0x152800 | 0x0A) | ||
330 | #define MAX3107_BRG26_B600 (0x0A9400 | 0x05) | ||
331 | #define MAX3107_BRG26_B1200 (0x054A00 | 0x03) | ||
332 | #define MAX3107_BRG26_B2400 (0x02A500 | 0x01) | ||
333 | #define MAX3107_BRG26_B4800 (0x015200 | 0x09) | ||
334 | #define MAX3107_BRG26_B9600 (0x00A900 | 0x04) | ||
335 | #define MAX3107_BRG26_B19200 (0x005400 | 0x0A) | ||
336 | #define MAX3107_BRG26_B38400 (0x002A00 | 0x05) | ||
337 | #define MAX3107_BRG26_B57600 (0x001C00 | 0x03) | ||
338 | #define MAX3107_BRG26_B115200 (0x000E00 | 0x02) | ||
339 | #define MAX3107_BRG26_B230400 (0x000700 | 0x01) | ||
340 | #define MAX3107_BRG26_B460800 (0x000300 | 0x08) | ||
341 | #define MAX3107_BRG26_B921600 (0x000100 | 0x0C) | ||
342 | |||
343 | /* Baud rate generator configuration values for internal clock */ | ||
344 | #define MAX3107_BRG13_IB300 (0x008000 | 0x00) | ||
345 | #define MAX3107_BRG13_IB600 (0x004000 | 0x00) | ||
346 | #define MAX3107_BRG13_IB1200 (0x002000 | 0x00) | ||
347 | #define MAX3107_BRG13_IB2400 (0x001000 | 0x00) | ||
348 | #define MAX3107_BRG13_IB4800 (0x000800 | 0x00) | ||
349 | #define MAX3107_BRG13_IB9600 (0x000400 | 0x00) | ||
350 | #define MAX3107_BRG13_IB19200 (0x000200 | 0x00) | ||
351 | #define MAX3107_BRG13_IB38400 (0x000100 | 0x00) | ||
352 | #define MAX3107_BRG13_IB57600 (0x000000 | 0x0B) | ||
353 | #define MAX3107_BRG13_IB115200 (0x000000 | 0x05) | ||
354 | #define MAX3107_BRG13_IB230400 (0x000000 | 0x03) | ||
355 | #define MAX3107_BRG13_IB460800 (0x000000 | 0x00) | ||
356 | #define MAX3107_BRG13_IB921600 (0x000000 | 0x00) | ||
357 | |||
358 | |||
359 | struct baud_table { | ||
360 | int baud; | ||
361 | u32 new_brg; | ||
362 | }; | ||
363 | |||
364 | struct max3107_port { | ||
365 | /* UART port structure */ | ||
366 | struct uart_port port; | ||
367 | |||
368 | /* SPI device structure */ | ||
369 | struct spi_device *spi; | ||
370 | |||
371 | #if defined(CONFIG_GPIOLIB) | ||
372 | /* GPIO chip stucture */ | ||
373 | struct gpio_chip chip; | ||
374 | #endif | ||
375 | |||
376 | /* Workqueue that does all the magic */ | ||
377 | struct workqueue_struct *workqueue; | ||
378 | struct work_struct work; | ||
379 | |||
380 | /* Lock for shared data */ | ||
381 | spinlock_t data_lock; | ||
382 | |||
383 | /* Device configuration */ | ||
384 | int ext_clk; /* 1 if external clock used */ | ||
385 | int loopback; /* Current loopback mode state */ | ||
386 | int baud; /* Current baud rate */ | ||
387 | |||
388 | /* State flags */ | ||
389 | int suspended; /* Indicates suspend mode */ | ||
390 | int tx_fifo_empty; /* Flag for TX FIFO state */ | ||
391 | int rx_enabled; /* Flag for receiver state */ | ||
392 | int tx_enabled; /* Flag for transmitter state */ | ||
393 | |||
394 | u16 irqen_reg; /* Current IRQ enable register value */ | ||
395 | /* Shared data */ | ||
396 | u16 mode1_reg; /* Current mode1 register value*/ | ||
397 | int mode1_commit; /* Flag for setting new mode1 register value */ | ||
398 | u16 lcr_reg; /* Current LCR register value */ | ||
399 | int lcr_commit; /* Flag for setting new LCR register value */ | ||
400 | u32 brg_cfg; /* Current Baud rate generator config */ | ||
401 | int brg_commit; /* Flag for setting new baud rate generator | ||
402 | * config | ||
403 | */ | ||
404 | struct baud_table *baud_tbl; | ||
405 | int handle_irq; /* Indicates that IRQ should be handled */ | ||
406 | |||
407 | /* Rx buffer and str*/ | ||
408 | u16 *rxbuf; | ||
409 | u8 *rxstr; | ||
410 | /* Tx buffer*/ | ||
411 | u16 *txbuf; | ||
412 | |||
413 | struct max3107_plat *pdata; /* Platform data */ | ||
414 | }; | ||
415 | |||
416 | /* Platform data structure */ | ||
417 | struct max3107_plat { | ||
418 | /* Loopback mode enable */ | ||
419 | int loopback; | ||
420 | /* External clock enable */ | ||
421 | int ext_clk; | ||
422 | /* Called during the register initialisation */ | ||
423 | void (*init)(struct max3107_port *s); | ||
424 | /* Called when the port is found and configured */ | ||
425 | int (*configure)(struct max3107_port *s); | ||
426 | /* HW suspend function */ | ||
427 | void (*hw_suspend) (struct max3107_port *s, int suspend); | ||
428 | /* Polling mode enable */ | ||
429 | int polled_mode; | ||
430 | /* Polling period if polling mode enabled */ | ||
431 | int poll_time; | ||
432 | }; | ||
433 | |||
434 | extern int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len); | ||
435 | extern void max3107_hw_susp(struct max3107_port *s, int suspend); | ||
436 | extern int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata); | ||
437 | extern int max3107_remove(struct spi_device *spi); | ||
438 | extern int max3107_suspend(struct spi_device *spi, pm_message_t state); | ||
439 | extern int max3107_resume(struct spi_device *spi); | ||
440 | |||
441 | #endif /* _LINUX_SERIAL_MAX3107_H */ | ||
diff --git a/drivers/serial/mcf.c b/drivers/serial/mcf.c index b5aaef965f24..3394b7cc1722 100644 --- a/drivers/serial/mcf.c +++ b/drivers/serial/mcf.c | |||
@@ -70,16 +70,14 @@ static unsigned int mcf_tx_empty(struct uart_port *port) | |||
70 | static unsigned int mcf_get_mctrl(struct uart_port *port) | 70 | static unsigned int mcf_get_mctrl(struct uart_port *port) |
71 | { | 71 | { |
72 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); | 72 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); |
73 | unsigned long flags; | ||
74 | unsigned int sigs; | 73 | unsigned int sigs; |
75 | 74 | ||
76 | spin_lock_irqsave(&port->lock, flags); | ||
77 | sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ? | 75 | sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ? |
78 | 0 : TIOCM_CTS; | 76 | 0 : TIOCM_CTS; |
79 | sigs |= (pp->sigs & TIOCM_RTS); | 77 | sigs |= (pp->sigs & TIOCM_RTS); |
80 | sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0); | 78 | sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0); |
81 | sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0); | 79 | sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0); |
82 | spin_unlock_irqrestore(&port->lock, flags); | 80 | |
83 | return sigs; | 81 | return sigs; |
84 | } | 82 | } |
85 | 83 | ||
@@ -88,16 +86,13 @@ static unsigned int mcf_get_mctrl(struct uart_port *port) | |||
88 | static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs) | 86 | static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs) |
89 | { | 87 | { |
90 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); | 88 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); |
91 | unsigned long flags; | ||
92 | 89 | ||
93 | spin_lock_irqsave(&port->lock, flags); | ||
94 | pp->sigs = sigs; | 90 | pp->sigs = sigs; |
95 | mcf_setppdtr(port->line, (sigs & TIOCM_DTR)); | 91 | mcf_setppdtr(port->line, (sigs & TIOCM_DTR)); |
96 | if (sigs & TIOCM_RTS) | 92 | if (sigs & TIOCM_RTS) |
97 | writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1); | 93 | writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1); |
98 | else | 94 | else |
99 | writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0); | 95 | writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0); |
100 | spin_unlock_irqrestore(&port->lock, flags); | ||
101 | } | 96 | } |
102 | 97 | ||
103 | /****************************************************************************/ | 98 | /****************************************************************************/ |
@@ -105,12 +100,9 @@ static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs) | |||
105 | static void mcf_start_tx(struct uart_port *port) | 100 | static void mcf_start_tx(struct uart_port *port) |
106 | { | 101 | { |
107 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); | 102 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); |
108 | unsigned long flags; | ||
109 | 103 | ||
110 | spin_lock_irqsave(&port->lock, flags); | ||
111 | pp->imr |= MCFUART_UIR_TXREADY; | 104 | pp->imr |= MCFUART_UIR_TXREADY; |
112 | writeb(pp->imr, port->membase + MCFUART_UIMR); | 105 | writeb(pp->imr, port->membase + MCFUART_UIMR); |
113 | spin_unlock_irqrestore(&port->lock, flags); | ||
114 | } | 106 | } |
115 | 107 | ||
116 | /****************************************************************************/ | 108 | /****************************************************************************/ |
@@ -118,12 +110,9 @@ static void mcf_start_tx(struct uart_port *port) | |||
118 | static void mcf_stop_tx(struct uart_port *port) | 110 | static void mcf_stop_tx(struct uart_port *port) |
119 | { | 111 | { |
120 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); | 112 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); |
121 | unsigned long flags; | ||
122 | 113 | ||
123 | spin_lock_irqsave(&port->lock, flags); | ||
124 | pp->imr &= ~MCFUART_UIR_TXREADY; | 114 | pp->imr &= ~MCFUART_UIR_TXREADY; |
125 | writeb(pp->imr, port->membase + MCFUART_UIMR); | 115 | writeb(pp->imr, port->membase + MCFUART_UIMR); |
126 | spin_unlock_irqrestore(&port->lock, flags); | ||
127 | } | 116 | } |
128 | 117 | ||
129 | /****************************************************************************/ | 118 | /****************************************************************************/ |
@@ -131,12 +120,9 @@ static void mcf_stop_tx(struct uart_port *port) | |||
131 | static void mcf_stop_rx(struct uart_port *port) | 120 | static void mcf_stop_rx(struct uart_port *port) |
132 | { | 121 | { |
133 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); | 122 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); |
134 | unsigned long flags; | ||
135 | 123 | ||
136 | spin_lock_irqsave(&port->lock, flags); | ||
137 | pp->imr &= ~MCFUART_UIR_RXREADY; | 124 | pp->imr &= ~MCFUART_UIR_RXREADY; |
138 | writeb(pp->imr, port->membase + MCFUART_UIMR); | 125 | writeb(pp->imr, port->membase + MCFUART_UIMR); |
139 | spin_unlock_irqrestore(&port->lock, flags); | ||
140 | } | 126 | } |
141 | 127 | ||
142 | /****************************************************************************/ | 128 | /****************************************************************************/ |
@@ -366,13 +352,22 @@ static irqreturn_t mcf_interrupt(int irq, void *data) | |||
366 | struct uart_port *port = data; | 352 | struct uart_port *port = data; |
367 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); | 353 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); |
368 | unsigned int isr; | 354 | unsigned int isr; |
355 | irqreturn_t ret = IRQ_NONE; | ||
369 | 356 | ||
370 | isr = readb(port->membase + MCFUART_UISR) & pp->imr; | 357 | isr = readb(port->membase + MCFUART_UISR) & pp->imr; |
371 | if (isr & MCFUART_UIR_RXREADY) | 358 | |
359 | spin_lock(&port->lock); | ||
360 | if (isr & MCFUART_UIR_RXREADY) { | ||
372 | mcf_rx_chars(pp); | 361 | mcf_rx_chars(pp); |
373 | if (isr & MCFUART_UIR_TXREADY) | 362 | ret = IRQ_HANDLED; |
363 | } | ||
364 | if (isr & MCFUART_UIR_TXREADY) { | ||
374 | mcf_tx_chars(pp); | 365 | mcf_tx_chars(pp); |
375 | return IRQ_HANDLED; | 366 | ret = IRQ_HANDLED; |
367 | } | ||
368 | spin_unlock(&port->lock); | ||
369 | |||
370 | return ret; | ||
376 | } | 371 | } |
377 | 372 | ||
378 | /****************************************************************************/ | 373 | /****************************************************************************/ |
diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c new file mode 100644 index 000000000000..bc9af503907f --- /dev/null +++ b/drivers/serial/mfd.c | |||
@@ -0,0 +1,1498 @@ | |||
1 | /* | ||
2 | * mfd.c: driver for High Speed UART device of Intel Medfield platform | ||
3 | * | ||
4 | * Refer pxa.c, 8250.c and some other drivers in drivers/serial/ | ||
5 | * | ||
6 | * (C) Copyright 2010 Intel Corporation | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; version 2 | ||
11 | * of the License. | ||
12 | */ | ||
13 | |||
14 | /* Notes: | ||
15 | * 1. DMA channel allocation: 0/1 channel are assigned to port 0, | ||
16 | * 2/3 chan to port 1, 4/5 chan to port 3. Even number chans | ||
17 | * are used for RX, odd chans for TX | ||
18 | * | ||
19 | * 2. In A0 stepping, UART will not support TX half empty flag | ||
20 | * | ||
21 | * 3. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always | ||
22 | * asserted, only when the HW is reset the DDCD and DDSR will | ||
23 | * be triggered | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/console.h> | ||
29 | #include <linux/sysrq.h> | ||
30 | #include <linux/serial_reg.h> | ||
31 | #include <linux/circ_buf.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/tty.h> | ||
35 | #include <linux/tty_flip.h> | ||
36 | #include <linux/serial_core.h> | ||
37 | #include <linux/serial_mfd.h> | ||
38 | #include <linux/dma-mapping.h> | ||
39 | #include <linux/pci.h> | ||
40 | #include <linux/io.h> | ||
41 | #include <linux/debugfs.h> | ||
42 | |||
43 | #define MFD_HSU_A0_STEPPING 1 | ||
44 | |||
45 | #define HSU_DMA_BUF_SIZE 2048 | ||
46 | |||
47 | #define chan_readl(chan, offset) readl(chan->reg + offset) | ||
48 | #define chan_writel(chan, offset, val) writel(val, chan->reg + offset) | ||
49 | |||
50 | #define mfd_readl(obj, offset) readl(obj->reg + offset) | ||
51 | #define mfd_writel(obj, offset, val) writel(val, obj->reg + offset) | ||
52 | |||
53 | #define HSU_DMA_TIMEOUT_CHECK_FREQ (HZ/10) | ||
54 | |||
55 | struct hsu_dma_buffer { | ||
56 | u8 *buf; | ||
57 | dma_addr_t dma_addr; | ||
58 | u32 dma_size; | ||
59 | u32 ofs; | ||
60 | }; | ||
61 | |||
62 | struct hsu_dma_chan { | ||
63 | u32 id; | ||
64 | enum dma_data_direction dirt; | ||
65 | struct uart_hsu_port *uport; | ||
66 | void __iomem *reg; | ||
67 | struct timer_list rx_timer; /* only needed by RX channel */ | ||
68 | }; | ||
69 | |||
70 | struct uart_hsu_port { | ||
71 | struct uart_port port; | ||
72 | unsigned char ier; | ||
73 | unsigned char lcr; | ||
74 | unsigned char mcr; | ||
75 | unsigned int lsr_break_flag; | ||
76 | char name[12]; | ||
77 | int index; | ||
78 | struct device *dev; | ||
79 | |||
80 | struct hsu_dma_chan *txc; | ||
81 | struct hsu_dma_chan *rxc; | ||
82 | struct hsu_dma_buffer txbuf; | ||
83 | struct hsu_dma_buffer rxbuf; | ||
84 | int use_dma; /* flag for DMA/PIO */ | ||
85 | int running; | ||
86 | int dma_tx_on; | ||
87 | }; | ||
88 | |||
89 | /* Top level data structure of HSU */ | ||
90 | struct hsu_port { | ||
91 | void __iomem *reg; | ||
92 | unsigned long paddr; | ||
93 | unsigned long iolen; | ||
94 | u32 irq; | ||
95 | |||
96 | struct uart_hsu_port port[3]; | ||
97 | struct hsu_dma_chan chans[10]; | ||
98 | |||
99 | struct dentry *debugfs; | ||
100 | }; | ||
101 | |||
102 | static inline unsigned int serial_in(struct uart_hsu_port *up, int offset) | ||
103 | { | ||
104 | unsigned int val; | ||
105 | |||
106 | if (offset > UART_MSR) { | ||
107 | offset <<= 2; | ||
108 | val = readl(up->port.membase + offset); | ||
109 | } else | ||
110 | val = (unsigned int)readb(up->port.membase + offset); | ||
111 | |||
112 | return val; | ||
113 | } | ||
114 | |||
115 | static inline void serial_out(struct uart_hsu_port *up, int offset, int value) | ||
116 | { | ||
117 | if (offset > UART_MSR) { | ||
118 | offset <<= 2; | ||
119 | writel(value, up->port.membase + offset); | ||
120 | } else { | ||
121 | unsigned char val = value & 0xff; | ||
122 | writeb(val, up->port.membase + offset); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | #ifdef CONFIG_DEBUG_FS | ||
127 | |||
128 | #define HSU_REGS_BUFSIZE 1024 | ||
129 | |||
130 | static int hsu_show_regs_open(struct inode *inode, struct file *file) | ||
131 | { | ||
132 | file->private_data = inode->i_private; | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static ssize_t port_show_regs(struct file *file, char __user *user_buf, | ||
137 | size_t count, loff_t *ppos) | ||
138 | { | ||
139 | struct uart_hsu_port *up = file->private_data; | ||
140 | char *buf; | ||
141 | u32 len = 0; | ||
142 | ssize_t ret; | ||
143 | |||
144 | buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL); | ||
145 | if (!buf) | ||
146 | return 0; | ||
147 | |||
148 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
149 | "MFD HSU port[%d] regs:\n", up->index); | ||
150 | |||
151 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
152 | "=================================\n"); | ||
153 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
154 | "IER: \t\t0x%08x\n", serial_in(up, UART_IER)); | ||
155 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
156 | "IIR: \t\t0x%08x\n", serial_in(up, UART_IIR)); | ||
157 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
158 | "LCR: \t\t0x%08x\n", serial_in(up, UART_LCR)); | ||
159 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
160 | "MCR: \t\t0x%08x\n", serial_in(up, UART_MCR)); | ||
161 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
162 | "LSR: \t\t0x%08x\n", serial_in(up, UART_LSR)); | ||
163 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
164 | "MSR: \t\t0x%08x\n", serial_in(up, UART_MSR)); | ||
165 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
166 | "FOR: \t\t0x%08x\n", serial_in(up, UART_FOR)); | ||
167 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
168 | "PS: \t\t0x%08x\n", serial_in(up, UART_PS)); | ||
169 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
170 | "MUL: \t\t0x%08x\n", serial_in(up, UART_MUL)); | ||
171 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
172 | "DIV: \t\t0x%08x\n", serial_in(up, UART_DIV)); | ||
173 | |||
174 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
175 | kfree(buf); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static ssize_t dma_show_regs(struct file *file, char __user *user_buf, | ||
180 | size_t count, loff_t *ppos) | ||
181 | { | ||
182 | struct hsu_dma_chan *chan = file->private_data; | ||
183 | char *buf; | ||
184 | u32 len = 0; | ||
185 | ssize_t ret; | ||
186 | |||
187 | buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL); | ||
188 | if (!buf) | ||
189 | return 0; | ||
190 | |||
191 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
192 | "MFD HSU DMA channel [%d] regs:\n", chan->id); | ||
193 | |||
194 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
195 | "=================================\n"); | ||
196 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
197 | "CR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_CR)); | ||
198 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
199 | "DCR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_DCR)); | ||
200 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
201 | "BSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_BSR)); | ||
202 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
203 | "MOTSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_MOTSR)); | ||
204 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
205 | "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0SAR)); | ||
206 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
207 | "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0TSR)); | ||
208 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
209 | "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1SAR)); | ||
210 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
211 | "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1TSR)); | ||
212 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
213 | "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2SAR)); | ||
214 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
215 | "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2TSR)); | ||
216 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
217 | "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3SAR)); | ||
218 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
219 | "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR)); | ||
220 | |||
221 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
222 | kfree(buf); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static const struct file_operations port_regs_ops = { | ||
227 | .owner = THIS_MODULE, | ||
228 | .open = hsu_show_regs_open, | ||
229 | .read = port_show_regs, | ||
230 | }; | ||
231 | |||
232 | static const struct file_operations dma_regs_ops = { | ||
233 | .owner = THIS_MODULE, | ||
234 | .open = hsu_show_regs_open, | ||
235 | .read = dma_show_regs, | ||
236 | }; | ||
237 | |||
238 | static int hsu_debugfs_init(struct hsu_port *hsu) | ||
239 | { | ||
240 | int i; | ||
241 | char name[32]; | ||
242 | |||
243 | hsu->debugfs = debugfs_create_dir("hsu", NULL); | ||
244 | if (!hsu->debugfs) | ||
245 | return -ENOMEM; | ||
246 | |||
247 | for (i = 0; i < 3; i++) { | ||
248 | snprintf(name, sizeof(name), "port_%d_regs", i); | ||
249 | debugfs_create_file(name, S_IFREG | S_IRUGO, | ||
250 | hsu->debugfs, (void *)(&hsu->port[i]), &port_regs_ops); | ||
251 | } | ||
252 | |||
253 | for (i = 0; i < 6; i++) { | ||
254 | snprintf(name, sizeof(name), "dma_chan_%d_regs", i); | ||
255 | debugfs_create_file(name, S_IFREG | S_IRUGO, | ||
256 | hsu->debugfs, (void *)&hsu->chans[i], &dma_regs_ops); | ||
257 | } | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static void hsu_debugfs_remove(struct hsu_port *hsu) | ||
263 | { | ||
264 | if (hsu->debugfs) | ||
265 | debugfs_remove_recursive(hsu->debugfs); | ||
266 | } | ||
267 | |||
268 | #else | ||
269 | static inline int hsu_debugfs_init(struct hsu_port *hsu) | ||
270 | { | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static inline void hsu_debugfs_remove(struct hsu_port *hsu) | ||
275 | { | ||
276 | } | ||
277 | #endif /* CONFIG_DEBUG_FS */ | ||
278 | |||
279 | static void serial_hsu_enable_ms(struct uart_port *port) | ||
280 | { | ||
281 | struct uart_hsu_port *up = | ||
282 | container_of(port, struct uart_hsu_port, port); | ||
283 | |||
284 | up->ier |= UART_IER_MSI; | ||
285 | serial_out(up, UART_IER, up->ier); | ||
286 | } | ||
287 | |||
288 | void hsu_dma_tx(struct uart_hsu_port *up) | ||
289 | { | ||
290 | struct circ_buf *xmit = &up->port.state->xmit; | ||
291 | struct hsu_dma_buffer *dbuf = &up->txbuf; | ||
292 | int count; | ||
293 | |||
294 | /* test_and_set_bit may be better, but anyway it's in lock protected mode */ | ||
295 | if (up->dma_tx_on) | ||
296 | return; | ||
297 | |||
298 | /* Update the circ buf info */ | ||
299 | xmit->tail += dbuf->ofs; | ||
300 | xmit->tail &= UART_XMIT_SIZE - 1; | ||
301 | |||
302 | up->port.icount.tx += dbuf->ofs; | ||
303 | dbuf->ofs = 0; | ||
304 | |||
305 | /* Disable the channel */ | ||
306 | chan_writel(up->txc, HSU_CH_CR, 0x0); | ||
307 | |||
308 | if (!uart_circ_empty(xmit) && !uart_tx_stopped(&up->port)) { | ||
309 | dma_sync_single_for_device(up->port.dev, | ||
310 | dbuf->dma_addr, | ||
311 | dbuf->dma_size, | ||
312 | DMA_TO_DEVICE); | ||
313 | |||
314 | count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); | ||
315 | dbuf->ofs = count; | ||
316 | |||
317 | /* Reprogram the channel */ | ||
318 | chan_writel(up->txc, HSU_CH_D0SAR, dbuf->dma_addr + xmit->tail); | ||
319 | chan_writel(up->txc, HSU_CH_D0TSR, count); | ||
320 | |||
321 | /* Reenable the channel */ | ||
322 | chan_writel(up->txc, HSU_CH_DCR, 0x1 | ||
323 | | (0x1 << 8) | ||
324 | | (0x1 << 16) | ||
325 | | (0x1 << 24)); | ||
326 | up->dma_tx_on = 1; | ||
327 | chan_writel(up->txc, HSU_CH_CR, 0x1); | ||
328 | } | ||
329 | |||
330 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
331 | uart_write_wakeup(&up->port); | ||
332 | } | ||
333 | |||
334 | /* The buffer is already cache coherent */ | ||
335 | void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf) | ||
336 | { | ||
337 | dbuf->ofs = 0; | ||
338 | |||
339 | chan_writel(rxc, HSU_CH_BSR, 32); | ||
340 | chan_writel(rxc, HSU_CH_MOTSR, 4); | ||
341 | |||
342 | chan_writel(rxc, HSU_CH_D0SAR, dbuf->dma_addr); | ||
343 | chan_writel(rxc, HSU_CH_D0TSR, dbuf->dma_size); | ||
344 | chan_writel(rxc, HSU_CH_DCR, 0x1 | (0x1 << 8) | ||
345 | | (0x1 << 16) | ||
346 | | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ | ||
347 | ); | ||
348 | chan_writel(rxc, HSU_CH_CR, 0x3); | ||
349 | |||
350 | mod_timer(&rxc->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ); | ||
351 | } | ||
352 | |||
353 | /* Protected by spin_lock_irqsave(port->lock) */ | ||
354 | static void serial_hsu_start_tx(struct uart_port *port) | ||
355 | { | ||
356 | struct uart_hsu_port *up = | ||
357 | container_of(port, struct uart_hsu_port, port); | ||
358 | |||
359 | if (up->use_dma) { | ||
360 | hsu_dma_tx(up); | ||
361 | } else if (!(up->ier & UART_IER_THRI)) { | ||
362 | up->ier |= UART_IER_THRI; | ||
363 | serial_out(up, UART_IER, up->ier); | ||
364 | } | ||
365 | } | ||
366 | |||
367 | static void serial_hsu_stop_tx(struct uart_port *port) | ||
368 | { | ||
369 | struct uart_hsu_port *up = | ||
370 | container_of(port, struct uart_hsu_port, port); | ||
371 | struct hsu_dma_chan *txc = up->txc; | ||
372 | |||
373 | if (up->use_dma) | ||
374 | chan_writel(txc, HSU_CH_CR, 0x0); | ||
375 | else if (up->ier & UART_IER_THRI) { | ||
376 | up->ier &= ~UART_IER_THRI; | ||
377 | serial_out(up, UART_IER, up->ier); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | /* This is always called in spinlock protected mode, so | ||
382 | * modify timeout timer is safe here */ | ||
383 | void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts) | ||
384 | { | ||
385 | struct hsu_dma_buffer *dbuf = &up->rxbuf; | ||
386 | struct hsu_dma_chan *chan = up->rxc; | ||
387 | struct uart_port *port = &up->port; | ||
388 | struct tty_struct *tty = port->state->port.tty; | ||
389 | int count; | ||
390 | |||
391 | if (!tty) | ||
392 | return; | ||
393 | |||
394 | /* | ||
395 | * First need to know how many is already transferred, | ||
396 | * then check if its a timeout DMA irq, and return | ||
397 | * the trail bytes out, push them up and reenable the | ||
398 | * channel | ||
399 | */ | ||
400 | |||
401 | /* Timeout IRQ, need wait some time, see Errata 2 */ | ||
402 | if (int_sts & 0xf00) | ||
403 | udelay(2); | ||
404 | |||
405 | /* Stop the channel */ | ||
406 | chan_writel(chan, HSU_CH_CR, 0x0); | ||
407 | |||
408 | count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; | ||
409 | if (!count) { | ||
410 | /* Restart the channel before we leave */ | ||
411 | chan_writel(chan, HSU_CH_CR, 0x3); | ||
412 | return; | ||
413 | } | ||
414 | del_timer(&chan->rx_timer); | ||
415 | |||
416 | dma_sync_single_for_cpu(port->dev, dbuf->dma_addr, | ||
417 | dbuf->dma_size, DMA_FROM_DEVICE); | ||
418 | |||
419 | /* | ||
420 | * Head will only wrap around when we recycle | ||
421 | * the DMA buffer, and when that happens, we | ||
422 | * explicitly set tail to 0. So head will | ||
423 | * always be greater than tail. | ||
424 | */ | ||
425 | tty_insert_flip_string(tty, dbuf->buf, count); | ||
426 | port->icount.rx += count; | ||
427 | |||
428 | dma_sync_single_for_device(up->port.dev, dbuf->dma_addr, | ||
429 | dbuf->dma_size, DMA_FROM_DEVICE); | ||
430 | |||
431 | /* Reprogram the channel */ | ||
432 | chan_writel(chan, HSU_CH_D0SAR, dbuf->dma_addr); | ||
433 | chan_writel(chan, HSU_CH_D0TSR, dbuf->dma_size); | ||
434 | chan_writel(chan, HSU_CH_DCR, 0x1 | ||
435 | | (0x1 << 8) | ||
436 | | (0x1 << 16) | ||
437 | | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ | ||
438 | ); | ||
439 | tty_flip_buffer_push(tty); | ||
440 | |||
441 | chan_writel(chan, HSU_CH_CR, 0x3); | ||
442 | chan->rx_timer.expires = jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ; | ||
443 | add_timer(&chan->rx_timer); | ||
444 | |||
445 | } | ||
446 | |||
447 | static void serial_hsu_stop_rx(struct uart_port *port) | ||
448 | { | ||
449 | struct uart_hsu_port *up = | ||
450 | container_of(port, struct uart_hsu_port, port); | ||
451 | struct hsu_dma_chan *chan = up->rxc; | ||
452 | |||
453 | if (up->use_dma) | ||
454 | chan_writel(chan, HSU_CH_CR, 0x2); | ||
455 | else { | ||
456 | up->ier &= ~UART_IER_RLSI; | ||
457 | up->port.read_status_mask &= ~UART_LSR_DR; | ||
458 | serial_out(up, UART_IER, up->ier); | ||
459 | } | ||
460 | } | ||
461 | |||
462 | static inline void receive_chars(struct uart_hsu_port *up, int *status) | ||
463 | { | ||
464 | struct tty_struct *tty = up->port.state->port.tty; | ||
465 | unsigned int ch, flag; | ||
466 | unsigned int max_count = 256; | ||
467 | |||
468 | if (!tty) | ||
469 | return; | ||
470 | |||
471 | do { | ||
472 | ch = serial_in(up, UART_RX); | ||
473 | flag = TTY_NORMAL; | ||
474 | up->port.icount.rx++; | ||
475 | |||
476 | if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | | ||
477 | UART_LSR_FE | UART_LSR_OE))) { | ||
478 | |||
479 | dev_warn(up->dev, "We really rush into ERR/BI case" | ||
480 | "status = 0x%02x", *status); | ||
481 | /* For statistics only */ | ||
482 | if (*status & UART_LSR_BI) { | ||
483 | *status &= ~(UART_LSR_FE | UART_LSR_PE); | ||
484 | up->port.icount.brk++; | ||
485 | /* | ||
486 | * We do the SysRQ and SAK checking | ||
487 | * here because otherwise the break | ||
488 | * may get masked by ignore_status_mask | ||
489 | * or read_status_mask. | ||
490 | */ | ||
491 | if (uart_handle_break(&up->port)) | ||
492 | goto ignore_char; | ||
493 | } else if (*status & UART_LSR_PE) | ||
494 | up->port.icount.parity++; | ||
495 | else if (*status & UART_LSR_FE) | ||
496 | up->port.icount.frame++; | ||
497 | if (*status & UART_LSR_OE) | ||
498 | up->port.icount.overrun++; | ||
499 | |||
500 | /* Mask off conditions which should be ignored. */ | ||
501 | *status &= up->port.read_status_mask; | ||
502 | |||
503 | #ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE | ||
504 | if (up->port.cons && | ||
505 | up->port.cons->index == up->port.line) { | ||
506 | /* Recover the break flag from console xmit */ | ||
507 | *status |= up->lsr_break_flag; | ||
508 | up->lsr_break_flag = 0; | ||
509 | } | ||
510 | #endif | ||
511 | if (*status & UART_LSR_BI) { | ||
512 | flag = TTY_BREAK; | ||
513 | } else if (*status & UART_LSR_PE) | ||
514 | flag = TTY_PARITY; | ||
515 | else if (*status & UART_LSR_FE) | ||
516 | flag = TTY_FRAME; | ||
517 | } | ||
518 | |||
519 | if (uart_handle_sysrq_char(&up->port, ch)) | ||
520 | goto ignore_char; | ||
521 | |||
522 | uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag); | ||
523 | ignore_char: | ||
524 | *status = serial_in(up, UART_LSR); | ||
525 | } while ((*status & UART_LSR_DR) && max_count--); | ||
526 | tty_flip_buffer_push(tty); | ||
527 | } | ||
528 | |||
529 | static void transmit_chars(struct uart_hsu_port *up) | ||
530 | { | ||
531 | struct circ_buf *xmit = &up->port.state->xmit; | ||
532 | int count; | ||
533 | |||
534 | if (up->port.x_char) { | ||
535 | serial_out(up, UART_TX, up->port.x_char); | ||
536 | up->port.icount.tx++; | ||
537 | up->port.x_char = 0; | ||
538 | return; | ||
539 | } | ||
540 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | ||
541 | serial_hsu_stop_tx(&up->port); | ||
542 | return; | ||
543 | } | ||
544 | |||
545 | #ifndef MFD_HSU_A0_STEPPING | ||
546 | count = up->port.fifosize / 2; | ||
547 | #else | ||
548 | /* | ||
549 | * A0 only supports fully empty IRQ, and the first char written | ||
550 | * into it won't clear the EMPT bit, so we may need be cautious | ||
551 | * by useing a shorter buffer | ||
552 | */ | ||
553 | count = up->port.fifosize - 4; | ||
554 | #endif | ||
555 | do { | ||
556 | serial_out(up, UART_TX, xmit->buf[xmit->tail]); | ||
557 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
558 | |||
559 | up->port.icount.tx++; | ||
560 | if (uart_circ_empty(xmit)) | ||
561 | break; | ||
562 | } while (--count > 0); | ||
563 | |||
564 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
565 | uart_write_wakeup(&up->port); | ||
566 | |||
567 | if (uart_circ_empty(xmit)) | ||
568 | serial_hsu_stop_tx(&up->port); | ||
569 | } | ||
570 | |||
571 | static inline void check_modem_status(struct uart_hsu_port *up) | ||
572 | { | ||
573 | int status; | ||
574 | |||
575 | status = serial_in(up, UART_MSR); | ||
576 | |||
577 | if ((status & UART_MSR_ANY_DELTA) == 0) | ||
578 | return; | ||
579 | |||
580 | if (status & UART_MSR_TERI) | ||
581 | up->port.icount.rng++; | ||
582 | if (status & UART_MSR_DDSR) | ||
583 | up->port.icount.dsr++; | ||
584 | /* We may only get DDCD when HW init and reset */ | ||
585 | if (status & UART_MSR_DDCD) | ||
586 | uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); | ||
587 | /* Will start/stop_tx accordingly */ | ||
588 | if (status & UART_MSR_DCTS) | ||
589 | uart_handle_cts_change(&up->port, status & UART_MSR_CTS); | ||
590 | |||
591 | wake_up_interruptible(&up->port.state->port.delta_msr_wait); | ||
592 | } | ||
593 | |||
594 | /* | ||
595 | * This handles the interrupt from one port. | ||
596 | */ | ||
597 | static irqreturn_t port_irq(int irq, void *dev_id) | ||
598 | { | ||
599 | struct uart_hsu_port *up = dev_id; | ||
600 | unsigned int iir, lsr; | ||
601 | unsigned long flags; | ||
602 | |||
603 | if (unlikely(!up->running)) | ||
604 | return IRQ_NONE; | ||
605 | |||
606 | spin_lock_irqsave(&up->port.lock, flags); | ||
607 | if (up->use_dma) { | ||
608 | lsr = serial_in(up, UART_LSR); | ||
609 | if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE | | ||
610 | UART_LSR_FE | UART_LSR_OE))) | ||
611 | dev_warn(up->dev, | ||
612 | "Got lsr irq while using DMA, lsr = 0x%2x\n", | ||
613 | lsr); | ||
614 | check_modem_status(up); | ||
615 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
616 | return IRQ_HANDLED; | ||
617 | } | ||
618 | |||
619 | iir = serial_in(up, UART_IIR); | ||
620 | if (iir & UART_IIR_NO_INT) { | ||
621 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
622 | return IRQ_NONE; | ||
623 | } | ||
624 | |||
625 | lsr = serial_in(up, UART_LSR); | ||
626 | if (lsr & UART_LSR_DR) | ||
627 | receive_chars(up, &lsr); | ||
628 | check_modem_status(up); | ||
629 | |||
630 | /* lsr will be renewed during the receive_chars */ | ||
631 | if (lsr & UART_LSR_THRE) | ||
632 | transmit_chars(up); | ||
633 | |||
634 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
635 | return IRQ_HANDLED; | ||
636 | } | ||
637 | |||
638 | static inline void dma_chan_irq(struct hsu_dma_chan *chan) | ||
639 | { | ||
640 | struct uart_hsu_port *up = chan->uport; | ||
641 | unsigned long flags; | ||
642 | u32 int_sts; | ||
643 | |||
644 | spin_lock_irqsave(&up->port.lock, flags); | ||
645 | |||
646 | if (!up->use_dma || !up->running) | ||
647 | goto exit; | ||
648 | |||
649 | /* | ||
650 | * No matter what situation, need read clear the IRQ status | ||
651 | * There is a bug, see Errata 5, HSD 2900918 | ||
652 | */ | ||
653 | int_sts = chan_readl(chan, HSU_CH_SR); | ||
654 | |||
655 | /* Rx channel */ | ||
656 | if (chan->dirt == DMA_FROM_DEVICE) | ||
657 | hsu_dma_rx(up, int_sts); | ||
658 | |||
659 | /* Tx channel */ | ||
660 | if (chan->dirt == DMA_TO_DEVICE) { | ||
661 | chan_writel(chan, HSU_CH_CR, 0x0); | ||
662 | up->dma_tx_on = 0; | ||
663 | hsu_dma_tx(up); | ||
664 | } | ||
665 | |||
666 | exit: | ||
667 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
668 | return; | ||
669 | } | ||
670 | |||
671 | static irqreturn_t dma_irq(int irq, void *dev_id) | ||
672 | { | ||
673 | struct hsu_port *hsu = dev_id; | ||
674 | u32 int_sts, i; | ||
675 | |||
676 | int_sts = mfd_readl(hsu, HSU_GBL_DMAISR); | ||
677 | |||
678 | /* Currently we only have 6 channels may be used */ | ||
679 | for (i = 0; i < 6; i++) { | ||
680 | if (int_sts & 0x1) | ||
681 | dma_chan_irq(&hsu->chans[i]); | ||
682 | int_sts >>= 1; | ||
683 | } | ||
684 | |||
685 | return IRQ_HANDLED; | ||
686 | } | ||
687 | |||
688 | static unsigned int serial_hsu_tx_empty(struct uart_port *port) | ||
689 | { | ||
690 | struct uart_hsu_port *up = | ||
691 | container_of(port, struct uart_hsu_port, port); | ||
692 | unsigned long flags; | ||
693 | unsigned int ret; | ||
694 | |||
695 | spin_lock_irqsave(&up->port.lock, flags); | ||
696 | ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; | ||
697 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
698 | |||
699 | return ret; | ||
700 | } | ||
701 | |||
702 | static unsigned int serial_hsu_get_mctrl(struct uart_port *port) | ||
703 | { | ||
704 | struct uart_hsu_port *up = | ||
705 | container_of(port, struct uart_hsu_port, port); | ||
706 | unsigned char status; | ||
707 | unsigned int ret; | ||
708 | |||
709 | status = serial_in(up, UART_MSR); | ||
710 | |||
711 | ret = 0; | ||
712 | if (status & UART_MSR_DCD) | ||
713 | ret |= TIOCM_CAR; | ||
714 | if (status & UART_MSR_RI) | ||
715 | ret |= TIOCM_RNG; | ||
716 | if (status & UART_MSR_DSR) | ||
717 | ret |= TIOCM_DSR; | ||
718 | if (status & UART_MSR_CTS) | ||
719 | ret |= TIOCM_CTS; | ||
720 | return ret; | ||
721 | } | ||
722 | |||
723 | static void serial_hsu_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
724 | { | ||
725 | struct uart_hsu_port *up = | ||
726 | container_of(port, struct uart_hsu_port, port); | ||
727 | unsigned char mcr = 0; | ||
728 | |||
729 | if (mctrl & TIOCM_RTS) | ||
730 | mcr |= UART_MCR_RTS; | ||
731 | if (mctrl & TIOCM_DTR) | ||
732 | mcr |= UART_MCR_DTR; | ||
733 | if (mctrl & TIOCM_OUT1) | ||
734 | mcr |= UART_MCR_OUT1; | ||
735 | if (mctrl & TIOCM_OUT2) | ||
736 | mcr |= UART_MCR_OUT2; | ||
737 | if (mctrl & TIOCM_LOOP) | ||
738 | mcr |= UART_MCR_LOOP; | ||
739 | |||
740 | mcr |= up->mcr; | ||
741 | |||
742 | serial_out(up, UART_MCR, mcr); | ||
743 | } | ||
744 | |||
745 | static void serial_hsu_break_ctl(struct uart_port *port, int break_state) | ||
746 | { | ||
747 | struct uart_hsu_port *up = | ||
748 | container_of(port, struct uart_hsu_port, port); | ||
749 | unsigned long flags; | ||
750 | |||
751 | spin_lock_irqsave(&up->port.lock, flags); | ||
752 | if (break_state == -1) | ||
753 | up->lcr |= UART_LCR_SBC; | ||
754 | else | ||
755 | up->lcr &= ~UART_LCR_SBC; | ||
756 | serial_out(up, UART_LCR, up->lcr); | ||
757 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
758 | } | ||
759 | |||
760 | /* | ||
761 | * What special to do: | ||
762 | * 1. chose the 64B fifo mode | ||
763 | * 2. make sure not to select half empty mode for A0 stepping | ||
764 | * 3. start dma or pio depends on configuration | ||
765 | * 4. we only allocate dma memory when needed | ||
766 | */ | ||
767 | static int serial_hsu_startup(struct uart_port *port) | ||
768 | { | ||
769 | struct uart_hsu_port *up = | ||
770 | container_of(port, struct uart_hsu_port, port); | ||
771 | unsigned long flags; | ||
772 | |||
773 | /* | ||
774 | * Clear the FIFO buffers and disable them. | ||
775 | * (they will be reenabled in set_termios()) | ||
776 | */ | ||
777 | serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); | ||
778 | serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | | ||
779 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); | ||
780 | serial_out(up, UART_FCR, 0); | ||
781 | |||
782 | /* Clear the interrupt registers. */ | ||
783 | (void) serial_in(up, UART_LSR); | ||
784 | (void) serial_in(up, UART_RX); | ||
785 | (void) serial_in(up, UART_IIR); | ||
786 | (void) serial_in(up, UART_MSR); | ||
787 | |||
788 | /* Now, initialize the UART, default is 8n1 */ | ||
789 | serial_out(up, UART_LCR, UART_LCR_WLEN8); | ||
790 | |||
791 | spin_lock_irqsave(&up->port.lock, flags); | ||
792 | |||
793 | up->port.mctrl |= TIOCM_OUT2; | ||
794 | serial_hsu_set_mctrl(&up->port, up->port.mctrl); | ||
795 | |||
796 | /* | ||
797 | * Finally, enable interrupts. Note: Modem status interrupts | ||
798 | * are set via set_termios(), which will be occurring imminently | ||
799 | * anyway, so we don't enable them here. | ||
800 | */ | ||
801 | if (!up->use_dma) | ||
802 | up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE; | ||
803 | else | ||
804 | up->ier = 0; | ||
805 | serial_out(up, UART_IER, up->ier); | ||
806 | |||
807 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
808 | |||
809 | /* DMA init */ | ||
810 | if (up->use_dma) { | ||
811 | struct hsu_dma_buffer *dbuf; | ||
812 | struct circ_buf *xmit = &port->state->xmit; | ||
813 | |||
814 | up->dma_tx_on = 0; | ||
815 | |||
816 | /* First allocate the RX buffer */ | ||
817 | dbuf = &up->rxbuf; | ||
818 | dbuf->buf = kzalloc(HSU_DMA_BUF_SIZE, GFP_KERNEL); | ||
819 | if (!dbuf->buf) { | ||
820 | up->use_dma = 0; | ||
821 | goto exit; | ||
822 | } | ||
823 | dbuf->dma_addr = dma_map_single(port->dev, | ||
824 | dbuf->buf, | ||
825 | HSU_DMA_BUF_SIZE, | ||
826 | DMA_FROM_DEVICE); | ||
827 | dbuf->dma_size = HSU_DMA_BUF_SIZE; | ||
828 | |||
829 | /* Start the RX channel right now */ | ||
830 | hsu_dma_start_rx_chan(up->rxc, dbuf); | ||
831 | |||
832 | /* Next init the TX DMA */ | ||
833 | dbuf = &up->txbuf; | ||
834 | dbuf->buf = xmit->buf; | ||
835 | dbuf->dma_addr = dma_map_single(port->dev, | ||
836 | dbuf->buf, | ||
837 | UART_XMIT_SIZE, | ||
838 | DMA_TO_DEVICE); | ||
839 | dbuf->dma_size = UART_XMIT_SIZE; | ||
840 | |||
841 | /* This should not be changed all around */ | ||
842 | chan_writel(up->txc, HSU_CH_BSR, 32); | ||
843 | chan_writel(up->txc, HSU_CH_MOTSR, 4); | ||
844 | dbuf->ofs = 0; | ||
845 | } | ||
846 | |||
847 | exit: | ||
848 | /* And clear the interrupt registers again for luck. */ | ||
849 | (void) serial_in(up, UART_LSR); | ||
850 | (void) serial_in(up, UART_RX); | ||
851 | (void) serial_in(up, UART_IIR); | ||
852 | (void) serial_in(up, UART_MSR); | ||
853 | |||
854 | up->running = 1; | ||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | static void serial_hsu_shutdown(struct uart_port *port) | ||
859 | { | ||
860 | struct uart_hsu_port *up = | ||
861 | container_of(port, struct uart_hsu_port, port); | ||
862 | unsigned long flags; | ||
863 | |||
864 | del_timer_sync(&up->rxc->rx_timer); | ||
865 | |||
866 | /* Disable interrupts from this port */ | ||
867 | up->ier = 0; | ||
868 | serial_out(up, UART_IER, 0); | ||
869 | up->running = 0; | ||
870 | |||
871 | spin_lock_irqsave(&up->port.lock, flags); | ||
872 | up->port.mctrl &= ~TIOCM_OUT2; | ||
873 | serial_hsu_set_mctrl(&up->port, up->port.mctrl); | ||
874 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
875 | |||
876 | /* Disable break condition and FIFOs */ | ||
877 | serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC); | ||
878 | serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | | ||
879 | UART_FCR_CLEAR_RCVR | | ||
880 | UART_FCR_CLEAR_XMIT); | ||
881 | serial_out(up, UART_FCR, 0); | ||
882 | } | ||
883 | |||
884 | static void | ||
885 | serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios, | ||
886 | struct ktermios *old) | ||
887 | { | ||
888 | struct uart_hsu_port *up = | ||
889 | container_of(port, struct uart_hsu_port, port); | ||
890 | struct tty_struct *tty = port->state->port.tty; | ||
891 | unsigned char cval, fcr = 0; | ||
892 | unsigned long flags; | ||
893 | unsigned int baud, quot; | ||
894 | u32 mul = 0x3600; | ||
895 | u32 ps = 0x10; | ||
896 | |||
897 | switch (termios->c_cflag & CSIZE) { | ||
898 | case CS5: | ||
899 | cval = UART_LCR_WLEN5; | ||
900 | break; | ||
901 | case CS6: | ||
902 | cval = UART_LCR_WLEN6; | ||
903 | break; | ||
904 | case CS7: | ||
905 | cval = UART_LCR_WLEN7; | ||
906 | break; | ||
907 | default: | ||
908 | case CS8: | ||
909 | cval = UART_LCR_WLEN8; | ||
910 | break; | ||
911 | } | ||
912 | |||
913 | /* CMSPAR isn't supported by this driver */ | ||
914 | if (tty) | ||
915 | tty->termios->c_cflag &= ~CMSPAR; | ||
916 | |||
917 | if (termios->c_cflag & CSTOPB) | ||
918 | cval |= UART_LCR_STOP; | ||
919 | if (termios->c_cflag & PARENB) | ||
920 | cval |= UART_LCR_PARITY; | ||
921 | if (!(termios->c_cflag & PARODD)) | ||
922 | cval |= UART_LCR_EPAR; | ||
923 | |||
924 | /* | ||
925 | * For those basic low baud rate we can get the direct | ||
926 | * scalar from 2746800, like 115200 = 2746800/24, for those | ||
927 | * higher baud rate, we have to handle them case by case, | ||
928 | * but DIV reg is never touched as its default value 0x3d09 | ||
929 | */ | ||
930 | baud = uart_get_baud_rate(port, termios, old, 0, 4000000); | ||
931 | quot = uart_get_divisor(port, baud); | ||
932 | |||
933 | switch (baud) { | ||
934 | case 3500000: | ||
935 | mul = 0x3345; | ||
936 | ps = 0xC; | ||
937 | quot = 1; | ||
938 | break; | ||
939 | case 2500000: | ||
940 | mul = 0x2710; | ||
941 | ps = 0x10; | ||
942 | quot = 1; | ||
943 | break; | ||
944 | case 18432000: | ||
945 | mul = 0x2400; | ||
946 | ps = 0x10; | ||
947 | quot = 1; | ||
948 | break; | ||
949 | case 1500000: | ||
950 | mul = 0x1D4C; | ||
951 | ps = 0xc; | ||
952 | quot = 1; | ||
953 | break; | ||
954 | default: | ||
955 | ; | ||
956 | } | ||
957 | |||
958 | if ((up->port.uartclk / quot) < (2400 * 16)) | ||
959 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B; | ||
960 | else if ((up->port.uartclk / quot) < (230400 * 16)) | ||
961 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_16B; | ||
962 | else | ||
963 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B; | ||
964 | |||
965 | fcr |= UART_FCR_HSU_64B_FIFO; | ||
966 | #ifdef MFD_HSU_A0_STEPPING | ||
967 | /* A0 doesn't support half empty IRQ */ | ||
968 | fcr |= UART_FCR_FULL_EMPT_TXI; | ||
969 | #endif | ||
970 | |||
971 | /* | ||
972 | * Ok, we're now changing the port state. Do it with | ||
973 | * interrupts disabled. | ||
974 | */ | ||
975 | spin_lock_irqsave(&up->port.lock, flags); | ||
976 | |||
977 | /* Update the per-port timeout */ | ||
978 | uart_update_timeout(port, termios->c_cflag, baud); | ||
979 | |||
980 | up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; | ||
981 | if (termios->c_iflag & INPCK) | ||
982 | up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; | ||
983 | if (termios->c_iflag & (BRKINT | PARMRK)) | ||
984 | up->port.read_status_mask |= UART_LSR_BI; | ||
985 | |||
986 | /* Characters to ignore */ | ||
987 | up->port.ignore_status_mask = 0; | ||
988 | if (termios->c_iflag & IGNPAR) | ||
989 | up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; | ||
990 | if (termios->c_iflag & IGNBRK) { | ||
991 | up->port.ignore_status_mask |= UART_LSR_BI; | ||
992 | /* | ||
993 | * If we're ignoring parity and break indicators, | ||
994 | * ignore overruns too (for real raw support). | ||
995 | */ | ||
996 | if (termios->c_iflag & IGNPAR) | ||
997 | up->port.ignore_status_mask |= UART_LSR_OE; | ||
998 | } | ||
999 | |||
1000 | /* Ignore all characters if CREAD is not set */ | ||
1001 | if ((termios->c_cflag & CREAD) == 0) | ||
1002 | up->port.ignore_status_mask |= UART_LSR_DR; | ||
1003 | |||
1004 | /* | ||
1005 | * CTS flow control flag and modem status interrupts, disable | ||
1006 | * MSI by default | ||
1007 | */ | ||
1008 | up->ier &= ~UART_IER_MSI; | ||
1009 | if (UART_ENABLE_MS(&up->port, termios->c_cflag)) | ||
1010 | up->ier |= UART_IER_MSI; | ||
1011 | |||
1012 | serial_out(up, UART_IER, up->ier); | ||
1013 | |||
1014 | if (termios->c_cflag & CRTSCTS) | ||
1015 | up->mcr |= UART_MCR_AFE | UART_MCR_RTS; | ||
1016 | else | ||
1017 | up->mcr &= ~UART_MCR_AFE; | ||
1018 | |||
1019 | serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ | ||
1020 | serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ | ||
1021 | serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ | ||
1022 | serial_out(up, UART_LCR, cval); /* reset DLAB */ | ||
1023 | serial_out(up, UART_MUL, mul); /* set MUL */ | ||
1024 | serial_out(up, UART_PS, ps); /* set PS */ | ||
1025 | up->lcr = cval; /* Save LCR */ | ||
1026 | serial_hsu_set_mctrl(&up->port, up->port.mctrl); | ||
1027 | serial_out(up, UART_FCR, fcr); | ||
1028 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
1029 | } | ||
1030 | |||
1031 | static void | ||
1032 | serial_hsu_pm(struct uart_port *port, unsigned int state, | ||
1033 | unsigned int oldstate) | ||
1034 | { | ||
1035 | } | ||
1036 | |||
1037 | static void serial_hsu_release_port(struct uart_port *port) | ||
1038 | { | ||
1039 | } | ||
1040 | |||
1041 | static int serial_hsu_request_port(struct uart_port *port) | ||
1042 | { | ||
1043 | return 0; | ||
1044 | } | ||
1045 | |||
1046 | static void serial_hsu_config_port(struct uart_port *port, int flags) | ||
1047 | { | ||
1048 | struct uart_hsu_port *up = | ||
1049 | container_of(port, struct uart_hsu_port, port); | ||
1050 | up->port.type = PORT_MFD; | ||
1051 | } | ||
1052 | |||
1053 | static int | ||
1054 | serial_hsu_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
1055 | { | ||
1056 | /* We don't want the core code to modify any port params */ | ||
1057 | return -EINVAL; | ||
1058 | } | ||
1059 | |||
1060 | static const char * | ||
1061 | serial_hsu_type(struct uart_port *port) | ||
1062 | { | ||
1063 | struct uart_hsu_port *up = | ||
1064 | container_of(port, struct uart_hsu_port, port); | ||
1065 | return up->name; | ||
1066 | } | ||
1067 | |||
1068 | /* Mainly for uart console use */ | ||
1069 | static struct uart_hsu_port *serial_hsu_ports[3]; | ||
1070 | static struct uart_driver serial_hsu_reg; | ||
1071 | |||
1072 | #ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE | ||
1073 | |||
1074 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) | ||
1075 | |||
1076 | /* Wait for transmitter & holding register to empty */ | ||
1077 | static inline void wait_for_xmitr(struct uart_hsu_port *up) | ||
1078 | { | ||
1079 | unsigned int status, tmout = 1000; | ||
1080 | |||
1081 | /* Wait up to 1ms for the character to be sent. */ | ||
1082 | do { | ||
1083 | status = serial_in(up, UART_LSR); | ||
1084 | |||
1085 | if (status & UART_LSR_BI) | ||
1086 | up->lsr_break_flag = UART_LSR_BI; | ||
1087 | |||
1088 | if (--tmout == 0) | ||
1089 | break; | ||
1090 | udelay(1); | ||
1091 | } while (!(status & BOTH_EMPTY)); | ||
1092 | |||
1093 | /* Wait up to 1s for flow control if necessary */ | ||
1094 | if (up->port.flags & UPF_CONS_FLOW) { | ||
1095 | tmout = 1000000; | ||
1096 | while (--tmout && | ||
1097 | ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) | ||
1098 | udelay(1); | ||
1099 | } | ||
1100 | } | ||
1101 | |||
1102 | static void serial_hsu_console_putchar(struct uart_port *port, int ch) | ||
1103 | { | ||
1104 | struct uart_hsu_port *up = | ||
1105 | container_of(port, struct uart_hsu_port, port); | ||
1106 | |||
1107 | wait_for_xmitr(up); | ||
1108 | serial_out(up, UART_TX, ch); | ||
1109 | } | ||
1110 | |||
1111 | /* | ||
1112 | * Print a string to the serial port trying not to disturb | ||
1113 | * any possible real use of the port... | ||
1114 | * | ||
1115 | * The console_lock must be held when we get here. | ||
1116 | */ | ||
1117 | static void | ||
1118 | serial_hsu_console_write(struct console *co, const char *s, unsigned int count) | ||
1119 | { | ||
1120 | struct uart_hsu_port *up = serial_hsu_ports[co->index]; | ||
1121 | unsigned long flags; | ||
1122 | unsigned int ier; | ||
1123 | int locked = 1; | ||
1124 | |||
1125 | local_irq_save(flags); | ||
1126 | if (up->port.sysrq) | ||
1127 | locked = 0; | ||
1128 | else if (oops_in_progress) { | ||
1129 | locked = spin_trylock(&up->port.lock); | ||
1130 | } else | ||
1131 | spin_lock(&up->port.lock); | ||
1132 | |||
1133 | /* First save the IER then disable the interrupts */ | ||
1134 | ier = serial_in(up, UART_IER); | ||
1135 | serial_out(up, UART_IER, 0); | ||
1136 | |||
1137 | uart_console_write(&up->port, s, count, serial_hsu_console_putchar); | ||
1138 | |||
1139 | /* | ||
1140 | * Finally, wait for transmitter to become empty | ||
1141 | * and restore the IER | ||
1142 | */ | ||
1143 | wait_for_xmitr(up); | ||
1144 | serial_out(up, UART_IER, ier); | ||
1145 | |||
1146 | if (locked) | ||
1147 | spin_unlock(&up->port.lock); | ||
1148 | local_irq_restore(flags); | ||
1149 | } | ||
1150 | |||
1151 | static struct console serial_hsu_console; | ||
1152 | |||
1153 | static int __init | ||
1154 | serial_hsu_console_setup(struct console *co, char *options) | ||
1155 | { | ||
1156 | struct uart_hsu_port *up; | ||
1157 | int baud = 115200; | ||
1158 | int bits = 8; | ||
1159 | int parity = 'n'; | ||
1160 | int flow = 'n'; | ||
1161 | int ret; | ||
1162 | |||
1163 | if (co->index == -1 || co->index >= serial_hsu_reg.nr) | ||
1164 | co->index = 0; | ||
1165 | up = serial_hsu_ports[co->index]; | ||
1166 | if (!up) | ||
1167 | return -ENODEV; | ||
1168 | |||
1169 | if (options) | ||
1170 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
1171 | |||
1172 | ret = uart_set_options(&up->port, co, baud, parity, bits, flow); | ||
1173 | |||
1174 | return ret; | ||
1175 | } | ||
1176 | |||
1177 | static struct console serial_hsu_console = { | ||
1178 | .name = "ttyMFD", | ||
1179 | .write = serial_hsu_console_write, | ||
1180 | .device = uart_console_device, | ||
1181 | .setup = serial_hsu_console_setup, | ||
1182 | .flags = CON_PRINTBUFFER, | ||
1183 | .index = 2, | ||
1184 | .data = &serial_hsu_reg, | ||
1185 | }; | ||
1186 | #endif | ||
1187 | |||
1188 | struct uart_ops serial_hsu_pops = { | ||
1189 | .tx_empty = serial_hsu_tx_empty, | ||
1190 | .set_mctrl = serial_hsu_set_mctrl, | ||
1191 | .get_mctrl = serial_hsu_get_mctrl, | ||
1192 | .stop_tx = serial_hsu_stop_tx, | ||
1193 | .start_tx = serial_hsu_start_tx, | ||
1194 | .stop_rx = serial_hsu_stop_rx, | ||
1195 | .enable_ms = serial_hsu_enable_ms, | ||
1196 | .break_ctl = serial_hsu_break_ctl, | ||
1197 | .startup = serial_hsu_startup, | ||
1198 | .shutdown = serial_hsu_shutdown, | ||
1199 | .set_termios = serial_hsu_set_termios, | ||
1200 | .pm = serial_hsu_pm, | ||
1201 | .type = serial_hsu_type, | ||
1202 | .release_port = serial_hsu_release_port, | ||
1203 | .request_port = serial_hsu_request_port, | ||
1204 | .config_port = serial_hsu_config_port, | ||
1205 | .verify_port = serial_hsu_verify_port, | ||
1206 | }; | ||
1207 | |||
1208 | static struct uart_driver serial_hsu_reg = { | ||
1209 | .owner = THIS_MODULE, | ||
1210 | .driver_name = "MFD serial", | ||
1211 | .dev_name = "ttyMFD", | ||
1212 | .major = TTY_MAJOR, | ||
1213 | .minor = 128, | ||
1214 | .nr = 3, | ||
1215 | }; | ||
1216 | |||
1217 | #ifdef CONFIG_PM | ||
1218 | static int serial_hsu_suspend(struct pci_dev *pdev, pm_message_t state) | ||
1219 | { | ||
1220 | void *priv = pci_get_drvdata(pdev); | ||
1221 | struct uart_hsu_port *up; | ||
1222 | |||
1223 | /* Make sure this is not the internal dma controller */ | ||
1224 | if (priv && (pdev->device != 0x081E)) { | ||
1225 | up = priv; | ||
1226 | uart_suspend_port(&serial_hsu_reg, &up->port); | ||
1227 | } | ||
1228 | |||
1229 | pci_save_state(pdev); | ||
1230 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
1231 | return 0; | ||
1232 | } | ||
1233 | |||
1234 | static int serial_hsu_resume(struct pci_dev *pdev) | ||
1235 | { | ||
1236 | void *priv = pci_get_drvdata(pdev); | ||
1237 | struct uart_hsu_port *up; | ||
1238 | int ret; | ||
1239 | |||
1240 | pci_set_power_state(pdev, PCI_D0); | ||
1241 | pci_restore_state(pdev); | ||
1242 | |||
1243 | ret = pci_enable_device(pdev); | ||
1244 | if (ret) | ||
1245 | dev_warn(&pdev->dev, | ||
1246 | "HSU: can't re-enable device, try to continue\n"); | ||
1247 | |||
1248 | if (priv && (pdev->device != 0x081E)) { | ||
1249 | up = priv; | ||
1250 | uart_resume_port(&serial_hsu_reg, &up->port); | ||
1251 | } | ||
1252 | return 0; | ||
1253 | } | ||
1254 | #else | ||
1255 | #define serial_hsu_suspend NULL | ||
1256 | #define serial_hsu_resume NULL | ||
1257 | #endif | ||
1258 | |||
1259 | /* temp global pointer before we settle down on using one or four PCI dev */ | ||
1260 | static struct hsu_port *phsu; | ||
1261 | |||
1262 | static int serial_hsu_probe(struct pci_dev *pdev, | ||
1263 | const struct pci_device_id *ent) | ||
1264 | { | ||
1265 | struct uart_hsu_port *uport; | ||
1266 | int index, ret; | ||
1267 | |||
1268 | printk(KERN_INFO "HSU: found PCI Serial controller(ID: %04x:%04x)\n", | ||
1269 | pdev->vendor, pdev->device); | ||
1270 | |||
1271 | switch (pdev->device) { | ||
1272 | case 0x081B: | ||
1273 | index = 0; | ||
1274 | break; | ||
1275 | case 0x081C: | ||
1276 | index = 1; | ||
1277 | break; | ||
1278 | case 0x081D: | ||
1279 | index = 2; | ||
1280 | break; | ||
1281 | case 0x081E: | ||
1282 | /* internal DMA controller */ | ||
1283 | index = 3; | ||
1284 | break; | ||
1285 | default: | ||
1286 | dev_err(&pdev->dev, "HSU: out of index!"); | ||
1287 | return -ENODEV; | ||
1288 | } | ||
1289 | |||
1290 | ret = pci_enable_device(pdev); | ||
1291 | if (ret) | ||
1292 | return ret; | ||
1293 | |||
1294 | if (index == 3) { | ||
1295 | /* DMA controller */ | ||
1296 | ret = request_irq(pdev->irq, dma_irq, 0, "hsu_dma", phsu); | ||
1297 | if (ret) { | ||
1298 | dev_err(&pdev->dev, "can not get IRQ\n"); | ||
1299 | goto err_disable; | ||
1300 | } | ||
1301 | pci_set_drvdata(pdev, phsu); | ||
1302 | } else { | ||
1303 | /* UART port 0~2 */ | ||
1304 | uport = &phsu->port[index]; | ||
1305 | uport->port.irq = pdev->irq; | ||
1306 | uport->port.dev = &pdev->dev; | ||
1307 | uport->dev = &pdev->dev; | ||
1308 | |||
1309 | ret = request_irq(pdev->irq, port_irq, 0, uport->name, uport); | ||
1310 | if (ret) { | ||
1311 | dev_err(&pdev->dev, "can not get IRQ\n"); | ||
1312 | goto err_disable; | ||
1313 | } | ||
1314 | uart_add_one_port(&serial_hsu_reg, &uport->port); | ||
1315 | |||
1316 | #ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE | ||
1317 | if (index == 2) { | ||
1318 | register_console(&serial_hsu_console); | ||
1319 | uport->port.cons = &serial_hsu_console; | ||
1320 | } | ||
1321 | #endif | ||
1322 | pci_set_drvdata(pdev, uport); | ||
1323 | } | ||
1324 | |||
1325 | return 0; | ||
1326 | |||
1327 | err_disable: | ||
1328 | pci_disable_device(pdev); | ||
1329 | return ret; | ||
1330 | } | ||
1331 | |||
1332 | static void hsu_dma_rx_timeout(unsigned long data) | ||
1333 | { | ||
1334 | struct hsu_dma_chan *chan = (void *)data; | ||
1335 | struct uart_hsu_port *up = chan->uport; | ||
1336 | struct hsu_dma_buffer *dbuf = &up->rxbuf; | ||
1337 | int count = 0; | ||
1338 | unsigned long flags; | ||
1339 | |||
1340 | spin_lock_irqsave(&up->port.lock, flags); | ||
1341 | |||
1342 | count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; | ||
1343 | |||
1344 | if (!count) { | ||
1345 | mod_timer(&chan->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ); | ||
1346 | goto exit; | ||
1347 | } | ||
1348 | |||
1349 | hsu_dma_rx(up, 0); | ||
1350 | exit: | ||
1351 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
1352 | } | ||
1353 | |||
1354 | static void hsu_global_init(void) | ||
1355 | { | ||
1356 | struct hsu_port *hsu; | ||
1357 | struct uart_hsu_port *uport; | ||
1358 | struct hsu_dma_chan *dchan; | ||
1359 | int i, ret; | ||
1360 | |||
1361 | hsu = kzalloc(sizeof(struct hsu_port), GFP_KERNEL); | ||
1362 | if (!hsu) | ||
1363 | return; | ||
1364 | |||
1365 | /* Get basic io resource and map it */ | ||
1366 | hsu->paddr = 0xffa28000; | ||
1367 | hsu->iolen = 0x1000; | ||
1368 | |||
1369 | if (!(request_mem_region(hsu->paddr, hsu->iolen, "HSU global"))) | ||
1370 | pr_warning("HSU: error in request mem region\n"); | ||
1371 | |||
1372 | hsu->reg = ioremap_nocache((unsigned long)hsu->paddr, hsu->iolen); | ||
1373 | if (!hsu->reg) { | ||
1374 | pr_err("HSU: error in ioremap\n"); | ||
1375 | ret = -ENOMEM; | ||
1376 | goto err_free_region; | ||
1377 | } | ||
1378 | |||
1379 | /* Initialise the 3 UART ports */ | ||
1380 | uport = hsu->port; | ||
1381 | for (i = 0; i < 3; i++) { | ||
1382 | uport->port.type = PORT_MFD; | ||
1383 | uport->port.iotype = UPIO_MEM; | ||
1384 | uport->port.mapbase = (resource_size_t)hsu->paddr | ||
1385 | + HSU_PORT_REG_OFFSET | ||
1386 | + i * HSU_PORT_REG_LENGTH; | ||
1387 | uport->port.membase = hsu->reg + HSU_PORT_REG_OFFSET | ||
1388 | + i * HSU_PORT_REG_LENGTH; | ||
1389 | |||
1390 | sprintf(uport->name, "hsu_port%d", i); | ||
1391 | uport->port.fifosize = 64; | ||
1392 | uport->port.ops = &serial_hsu_pops; | ||
1393 | uport->port.line = i; | ||
1394 | uport->port.flags = UPF_IOREMAP; | ||
1395 | /* set the scalable maxim support rate to 2746800 bps */ | ||
1396 | uport->port.uartclk = 115200 * 24 * 16; | ||
1397 | |||
1398 | uport->running = 0; | ||
1399 | uport->txc = &hsu->chans[i * 2]; | ||
1400 | uport->rxc = &hsu->chans[i * 2 + 1]; | ||
1401 | |||
1402 | serial_hsu_ports[i] = uport; | ||
1403 | uport->index = i; | ||
1404 | uport++; | ||
1405 | } | ||
1406 | |||
1407 | /* Initialise 6 dma channels */ | ||
1408 | dchan = hsu->chans; | ||
1409 | for (i = 0; i < 6; i++) { | ||
1410 | dchan->id = i; | ||
1411 | dchan->dirt = (i & 0x1) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
1412 | dchan->uport = &hsu->port[i/2]; | ||
1413 | dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET + | ||
1414 | i * HSU_DMA_CHANS_REG_LENGTH; | ||
1415 | |||
1416 | /* Work around for RX */ | ||
1417 | if (dchan->dirt == DMA_FROM_DEVICE) { | ||
1418 | init_timer(&dchan->rx_timer); | ||
1419 | dchan->rx_timer.function = hsu_dma_rx_timeout; | ||
1420 | dchan->rx_timer.data = (unsigned long)dchan; | ||
1421 | } | ||
1422 | dchan++; | ||
1423 | } | ||
1424 | |||
1425 | phsu = hsu; | ||
1426 | |||
1427 | hsu_debugfs_init(hsu); | ||
1428 | return; | ||
1429 | |||
1430 | err_free_region: | ||
1431 | release_mem_region(hsu->paddr, hsu->iolen); | ||
1432 | kfree(hsu); | ||
1433 | return; | ||
1434 | } | ||
1435 | |||
1436 | static void serial_hsu_remove(struct pci_dev *pdev) | ||
1437 | { | ||
1438 | struct hsu_port *hsu; | ||
1439 | int i; | ||
1440 | |||
1441 | hsu = pci_get_drvdata(pdev); | ||
1442 | if (!hsu) | ||
1443 | return; | ||
1444 | |||
1445 | for (i = 0; i < 3; i++) | ||
1446 | uart_remove_one_port(&serial_hsu_reg, &hsu->port[i].port); | ||
1447 | |||
1448 | pci_set_drvdata(pdev, NULL); | ||
1449 | free_irq(hsu->irq, hsu); | ||
1450 | pci_disable_device(pdev); | ||
1451 | } | ||
1452 | |||
1453 | /* First 3 are UART ports, and the 4th is the DMA */ | ||
1454 | static const struct pci_device_id pci_ids[] __devinitdata = { | ||
1455 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) }, | ||
1456 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) }, | ||
1457 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) }, | ||
1458 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081E) }, | ||
1459 | {}, | ||
1460 | }; | ||
1461 | |||
1462 | static struct pci_driver hsu_pci_driver = { | ||
1463 | .name = "HSU serial", | ||
1464 | .id_table = pci_ids, | ||
1465 | .probe = serial_hsu_probe, | ||
1466 | .remove = __devexit_p(serial_hsu_remove), | ||
1467 | .suspend = serial_hsu_suspend, | ||
1468 | .resume = serial_hsu_resume, | ||
1469 | }; | ||
1470 | |||
1471 | static int __init hsu_pci_init(void) | ||
1472 | { | ||
1473 | int ret; | ||
1474 | |||
1475 | hsu_global_init(); | ||
1476 | |||
1477 | ret = uart_register_driver(&serial_hsu_reg); | ||
1478 | if (ret) | ||
1479 | return ret; | ||
1480 | |||
1481 | return pci_register_driver(&hsu_pci_driver); | ||
1482 | } | ||
1483 | |||
1484 | static void __exit hsu_pci_exit(void) | ||
1485 | { | ||
1486 | pci_unregister_driver(&hsu_pci_driver); | ||
1487 | uart_unregister_driver(&serial_hsu_reg); | ||
1488 | |||
1489 | hsu_debugfs_remove(phsu); | ||
1490 | |||
1491 | kfree(phsu); | ||
1492 | } | ||
1493 | |||
1494 | module_init(hsu_pci_init); | ||
1495 | module_exit(hsu_pci_exit); | ||
1496 | |||
1497 | MODULE_LICENSE("GPL v2"); | ||
1498 | MODULE_ALIAS("platform:medfield-hsu"); | ||
diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c new file mode 100644 index 000000000000..f6ad1ecbff79 --- /dev/null +++ b/drivers/serial/mrst_max3110.c | |||
@@ -0,0 +1,844 @@ | |||
1 | /* | ||
2 | * max3110.c - spi uart protocol driver for Maxim 3110 on Moorestown | ||
3 | * | ||
4 | * Copyright (C) Intel 2008 Feng Tang <feng.tang@intel.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | * Note: | ||
22 | * 1. From Max3110 spec, the Rx FIFO has 8 words, while the Tx FIFO only has | ||
23 | * 1 word. If SPI master controller doesn't support sclk frequency change, | ||
24 | * then the char need be sent out one by one with some delay | ||
25 | * | ||
26 | * 2. Currently only RX availabe interrrupt is used, no need for waiting TXE | ||
27 | * interrupt for a low speed UART device | ||
28 | */ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/ioport.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/console.h> | ||
34 | #include <linux/sysrq.h> | ||
35 | #include <linux/platform_device.h> | ||
36 | #include <linux/tty.h> | ||
37 | #include <linux/tty_flip.h> | ||
38 | #include <linux/serial_core.h> | ||
39 | #include <linux/serial_reg.h> | ||
40 | |||
41 | #include <linux/kthread.h> | ||
42 | #include <linux/delay.h> | ||
43 | #include <asm/atomic.h> | ||
44 | #include <linux/spi/spi.h> | ||
45 | #include <linux/spi/dw_spi.h> | ||
46 | |||
47 | #include "mrst_max3110.h" | ||
48 | |||
49 | #define PR_FMT "mrst_max3110: " | ||
50 | |||
51 | #define UART_TX_NEEDED 1 | ||
52 | #define CON_TX_NEEDED 2 | ||
53 | #define BIT_IRQ_PENDING 3 | ||
54 | |||
55 | struct uart_max3110 { | ||
56 | struct uart_port port; | ||
57 | struct spi_device *spi; | ||
58 | char *name; | ||
59 | |||
60 | wait_queue_head_t wq; | ||
61 | struct task_struct *main_thread; | ||
62 | struct task_struct *read_thread; | ||
63 | struct mutex thread_mutex;; | ||
64 | |||
65 | u32 baud; | ||
66 | u16 cur_conf; | ||
67 | u8 clock; | ||
68 | u8 parity, word_7bits; | ||
69 | |||
70 | unsigned long uart_flags; | ||
71 | |||
72 | /* console related */ | ||
73 | struct circ_buf con_xmit; | ||
74 | |||
75 | /* irq related */ | ||
76 | u16 irq; | ||
77 | }; | ||
78 | |||
79 | /* global data structure, may need be removed */ | ||
80 | struct uart_max3110 *pmax; | ||
81 | static inline void receive_char(struct uart_max3110 *max, u8 ch); | ||
82 | static void receive_chars(struct uart_max3110 *max, | ||
83 | unsigned char *str, int len); | ||
84 | static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf); | ||
85 | static void max3110_console_receive(struct uart_max3110 *max); | ||
86 | |||
87 | int max3110_write_then_read(struct uart_max3110 *max, | ||
88 | const u8 *txbuf, u8 *rxbuf, unsigned len, int always_fast) | ||
89 | { | ||
90 | struct spi_device *spi = max->spi; | ||
91 | struct spi_message message; | ||
92 | struct spi_transfer x; | ||
93 | int ret; | ||
94 | |||
95 | if (!txbuf || !rxbuf) | ||
96 | return -EINVAL; | ||
97 | |||
98 | spi_message_init(&message); | ||
99 | memset(&x, 0, sizeof x); | ||
100 | x.len = len; | ||
101 | x.tx_buf = txbuf; | ||
102 | x.rx_buf = rxbuf; | ||
103 | spi_message_add_tail(&x, &message); | ||
104 | |||
105 | if (always_fast) | ||
106 | x.speed_hz = 3125000; | ||
107 | else if (max->baud) | ||
108 | x.speed_hz = max->baud; | ||
109 | |||
110 | /* Do the i/o */ | ||
111 | ret = spi_sync(spi, &message); | ||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | /* Write a u16 to the device, and return one u16 read back */ | ||
116 | int max3110_out(struct uart_max3110 *max, const u16 out) | ||
117 | { | ||
118 | u16 tmp; | ||
119 | int ret; | ||
120 | |||
121 | ret = max3110_write_then_read(max, (u8 *)&out, (u8 *)&tmp, 2, 1); | ||
122 | if (ret) | ||
123 | return ret; | ||
124 | |||
125 | /* If some valid data is read back */ | ||
126 | if (tmp & MAX3110_READ_DATA_AVAILABLE) | ||
127 | receive_char(max, (tmp & 0xff)); | ||
128 | |||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | #define MAX_READ_LEN 20 | ||
133 | /* | ||
134 | * This is usually used to read data from SPIC RX FIFO, which doesn't | ||
135 | * need any delay like flushing character out. It returns how many | ||
136 | * valide bytes are read back | ||
137 | */ | ||
138 | static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf) | ||
139 | { | ||
140 | u16 out[MAX_READ_LEN], in[MAX_READ_LEN]; | ||
141 | u8 *pbuf, valid_str[MAX_READ_LEN]; | ||
142 | int i, j, bytelen; | ||
143 | |||
144 | if (len > MAX_READ_LEN) { | ||
145 | pr_err(PR_FMT "read len %d is too large\n", len); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | bytelen = len * 2; | ||
150 | memset(out, 0, bytelen); | ||
151 | memset(in, 0, bytelen); | ||
152 | |||
153 | if (max3110_write_then_read(max, (u8 *)out, (u8 *)in, bytelen, 1)) | ||
154 | return 0; | ||
155 | |||
156 | /* If caller don't provide a buffer, then handle received char */ | ||
157 | pbuf = buf ? buf : valid_str; | ||
158 | |||
159 | for (i = 0, j = 0; i < len; i++) { | ||
160 | if (in[i] & MAX3110_READ_DATA_AVAILABLE) | ||
161 | pbuf[j++] = (u8)(in[i] & 0xff); | ||
162 | } | ||
163 | |||
164 | if (j && (pbuf == valid_str)) | ||
165 | receive_chars(max, valid_str, j); | ||
166 | |||
167 | return j; | ||
168 | } | ||
169 | |||
170 | static void serial_m3110_con_putchar(struct uart_port *port, int ch) | ||
171 | { | ||
172 | struct uart_max3110 *max = | ||
173 | container_of(port, struct uart_max3110, port); | ||
174 | struct circ_buf *xmit = &max->con_xmit; | ||
175 | |||
176 | if (uart_circ_chars_free(xmit)) { | ||
177 | xmit->buf[xmit->head] = (char)ch; | ||
178 | xmit->head = (xmit->head + 1) & (PAGE_SIZE - 1); | ||
179 | } | ||
180 | |||
181 | |||
182 | if (!test_and_set_bit(CON_TX_NEEDED, &max->uart_flags)) | ||
183 | wake_up_process(max->main_thread); | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Print a string to the serial port trying not to disturb | ||
188 | * any possible real use of the port... | ||
189 | * | ||
190 | * The console_lock must be held when we get here. | ||
191 | */ | ||
192 | static void serial_m3110_con_write(struct console *co, | ||
193 | const char *s, unsigned int count) | ||
194 | { | ||
195 | if (!pmax) | ||
196 | return; | ||
197 | |||
198 | uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar); | ||
199 | } | ||
200 | |||
201 | static int __init | ||
202 | serial_m3110_con_setup(struct console *co, char *options) | ||
203 | { | ||
204 | struct uart_max3110 *max = pmax; | ||
205 | int baud = 115200; | ||
206 | int bits = 8; | ||
207 | int parity = 'n'; | ||
208 | int flow = 'n'; | ||
209 | |||
210 | pr_info(PR_FMT "setting up console\n"); | ||
211 | |||
212 | if (!max) { | ||
213 | pr_err(PR_FMT "pmax is NULL, return"); | ||
214 | return -ENODEV; | ||
215 | } | ||
216 | |||
217 | if (options) | ||
218 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
219 | |||
220 | return uart_set_options(&max->port, co, baud, parity, bits, flow); | ||
221 | } | ||
222 | |||
223 | static struct tty_driver *serial_m3110_con_device(struct console *co, | ||
224 | int *index) | ||
225 | { | ||
226 | struct uart_driver *p = co->data; | ||
227 | *index = co->index; | ||
228 | return p->tty_driver; | ||
229 | } | ||
230 | |||
231 | static struct uart_driver serial_m3110_reg; | ||
232 | static struct console serial_m3110_console = { | ||
233 | .name = "ttyS", | ||
234 | .write = serial_m3110_con_write, | ||
235 | .device = serial_m3110_con_device, | ||
236 | .setup = serial_m3110_con_setup, | ||
237 | .flags = CON_PRINTBUFFER, | ||
238 | .index = -1, | ||
239 | .data = &serial_m3110_reg, | ||
240 | }; | ||
241 | |||
242 | #define MRST_CONSOLE (&serial_m3110_console) | ||
243 | |||
244 | static unsigned int serial_m3110_tx_empty(struct uart_port *port) | ||
245 | { | ||
246 | return 1; | ||
247 | } | ||
248 | |||
249 | static void serial_m3110_stop_tx(struct uart_port *port) | ||
250 | { | ||
251 | return; | ||
252 | } | ||
253 | |||
254 | /* stop_rx will be called in spin_lock env */ | ||
255 | static void serial_m3110_stop_rx(struct uart_port *port) | ||
256 | { | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | #define WORDS_PER_XFER 128 | ||
261 | static inline void send_circ_buf(struct uart_max3110 *max, | ||
262 | struct circ_buf *xmit) | ||
263 | { | ||
264 | int len, left = 0; | ||
265 | u16 obuf[WORDS_PER_XFER], ibuf[WORDS_PER_XFER]; | ||
266 | u8 valid_str[WORDS_PER_XFER]; | ||
267 | int i, j; | ||
268 | |||
269 | while (!uart_circ_empty(xmit)) { | ||
270 | left = uart_circ_chars_pending(xmit); | ||
271 | while (left) { | ||
272 | len = (left >= WORDS_PER_XFER) ? WORDS_PER_XFER : left; | ||
273 | |||
274 | memset(obuf, 0, len * 2); | ||
275 | memset(ibuf, 0, len * 2); | ||
276 | for (i = 0; i < len; i++) { | ||
277 | obuf[i] = (u8)xmit->buf[xmit->tail] | WD_TAG; | ||
278 | xmit->tail = (xmit->tail + 1) & | ||
279 | (UART_XMIT_SIZE - 1); | ||
280 | } | ||
281 | max3110_write_then_read(max, (u8 *)obuf, | ||
282 | (u8 *)ibuf, len * 2, 0); | ||
283 | |||
284 | for (i = 0, j = 0; i < len; i++) { | ||
285 | if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE) | ||
286 | valid_str[j++] = (u8)(ibuf[i] & 0xff); | ||
287 | } | ||
288 | |||
289 | if (j) | ||
290 | receive_chars(max, valid_str, j); | ||
291 | |||
292 | max->port.icount.tx += len; | ||
293 | left -= len; | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | |||
298 | static void transmit_char(struct uart_max3110 *max) | ||
299 | { | ||
300 | struct uart_port *port = &max->port; | ||
301 | struct circ_buf *xmit = &port->state->xmit; | ||
302 | |||
303 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) | ||
304 | return; | ||
305 | |||
306 | send_circ_buf(max, xmit); | ||
307 | |||
308 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
309 | uart_write_wakeup(port); | ||
310 | |||
311 | if (uart_circ_empty(xmit)) | ||
312 | serial_m3110_stop_tx(port); | ||
313 | } | ||
314 | |||
315 | /* This will be called by uart_write() and tty_write, can't | ||
316 | * go to sleep */ | ||
317 | static void serial_m3110_start_tx(struct uart_port *port) | ||
318 | { | ||
319 | struct uart_max3110 *max = | ||
320 | container_of(port, struct uart_max3110, port); | ||
321 | |||
322 | if (!test_and_set_bit(UART_TX_NEEDED, &max->uart_flags)) | ||
323 | wake_up_process(max->main_thread); | ||
324 | } | ||
325 | |||
326 | static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len) | ||
327 | { | ||
328 | struct uart_port *port = &max->port; | ||
329 | struct tty_struct *tty; | ||
330 | int usable; | ||
331 | |||
332 | /* If uart is not opened, just return */ | ||
333 | if (!port->state) | ||
334 | return; | ||
335 | |||
336 | tty = port->state->port.tty; | ||
337 | if (!tty) | ||
338 | return; /* receive some char before the tty is opened */ | ||
339 | |||
340 | while (len) { | ||
341 | usable = tty_buffer_request_room(tty, len); | ||
342 | if (usable) { | ||
343 | tty_insert_flip_string(tty, str, usable); | ||
344 | str += usable; | ||
345 | port->icount.rx += usable; | ||
346 | tty_flip_buffer_push(tty); | ||
347 | } | ||
348 | len -= usable; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | static inline void receive_char(struct uart_max3110 *max, u8 ch) | ||
353 | { | ||
354 | receive_chars(max, &ch, 1); | ||
355 | } | ||
356 | |||
357 | static void max3110_console_receive(struct uart_max3110 *max) | ||
358 | { | ||
359 | int loop = 1, num, total = 0; | ||
360 | u8 recv_buf[512], *pbuf; | ||
361 | |||
362 | pbuf = recv_buf; | ||
363 | do { | ||
364 | num = max3110_read_multi(max, 8, pbuf); | ||
365 | |||
366 | if (num) { | ||
367 | loop = 10; | ||
368 | pbuf += num; | ||
369 | total += num; | ||
370 | |||
371 | if (total >= 500) { | ||
372 | receive_chars(max, recv_buf, total); | ||
373 | pbuf = recv_buf; | ||
374 | total = 0; | ||
375 | } | ||
376 | } | ||
377 | } while (--loop); | ||
378 | |||
379 | if (total) | ||
380 | receive_chars(max, recv_buf, total); | ||
381 | } | ||
382 | |||
383 | static int max3110_main_thread(void *_max) | ||
384 | { | ||
385 | struct uart_max3110 *max = _max; | ||
386 | wait_queue_head_t *wq = &max->wq; | ||
387 | int ret = 0; | ||
388 | struct circ_buf *xmit = &max->con_xmit; | ||
389 | |||
390 | init_waitqueue_head(wq); | ||
391 | pr_info(PR_FMT "start main thread\n"); | ||
392 | |||
393 | do { | ||
394 | wait_event_interruptible(*wq, max->uart_flags || kthread_should_stop()); | ||
395 | |||
396 | mutex_lock(&max->thread_mutex); | ||
397 | |||
398 | if (test_and_clear_bit(BIT_IRQ_PENDING, &max->uart_flags)) | ||
399 | max3110_console_receive(max); | ||
400 | |||
401 | /* first handle console output */ | ||
402 | if (test_and_clear_bit(CON_TX_NEEDED, &max->uart_flags)) | ||
403 | send_circ_buf(max, xmit); | ||
404 | |||
405 | /* handle uart output */ | ||
406 | if (test_and_clear_bit(UART_TX_NEEDED, &max->uart_flags)) | ||
407 | transmit_char(max); | ||
408 | |||
409 | mutex_unlock(&max->thread_mutex); | ||
410 | |||
411 | } while (!kthread_should_stop()); | ||
412 | |||
413 | return ret; | ||
414 | } | ||
415 | |||
416 | #ifdef CONFIG_MRST_MAX3110_IRQ | ||
417 | static irqreturn_t serial_m3110_irq(int irq, void *dev_id) | ||
418 | { | ||
419 | struct uart_max3110 *max = dev_id; | ||
420 | |||
421 | /* max3110's irq is a falling edge, not level triggered, | ||
422 | * so no need to disable the irq */ | ||
423 | if (!test_and_set_bit(BIT_IRQ_PENDING, &max->uart_flags)) | ||
424 | wake_up_process(max->main_thread); | ||
425 | |||
426 | return IRQ_HANDLED; | ||
427 | } | ||
428 | #else | ||
429 | /* if don't use RX IRQ, then need a thread to polling read */ | ||
430 | static int max3110_read_thread(void *_max) | ||
431 | { | ||
432 | struct uart_max3110 *max = _max; | ||
433 | |||
434 | pr_info(PR_FMT "start read thread\n"); | ||
435 | do { | ||
436 | mutex_lock(&max->thread_mutex); | ||
437 | max3110_console_receive(max); | ||
438 | mutex_unlock(&max->thread_mutex); | ||
439 | |||
440 | set_current_state(TASK_INTERRUPTIBLE); | ||
441 | schedule_timeout(HZ / 20); | ||
442 | } while (!kthread_should_stop()); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | #endif | ||
447 | |||
448 | static int serial_m3110_startup(struct uart_port *port) | ||
449 | { | ||
450 | struct uart_max3110 *max = | ||
451 | container_of(port, struct uart_max3110, port); | ||
452 | u16 config = 0; | ||
453 | int ret = 0; | ||
454 | |||
455 | if (port->line != 0) | ||
456 | pr_err(PR_FMT "uart port startup failed\n"); | ||
457 | |||
458 | /* firstly disable all IRQ and config it to 115200, 8n1 */ | ||
459 | config = WC_TAG | WC_FIFO_ENABLE | ||
460 | | WC_1_STOPBITS | ||
461 | | WC_8BIT_WORD | ||
462 | | WC_BAUD_DR2; | ||
463 | ret = max3110_out(max, config); | ||
464 | |||
465 | /* as we use thread to handle tx/rx, need set low latency */ | ||
466 | port->state->port.tty->low_latency = 1; | ||
467 | |||
468 | #ifdef CONFIG_MRST_MAX3110_IRQ | ||
469 | ret = request_irq(max->irq, serial_m3110_irq, | ||
470 | IRQ_TYPE_EDGE_FALLING, "max3110", max); | ||
471 | if (ret) | ||
472 | return ret; | ||
473 | |||
474 | /* enable RX IRQ only */ | ||
475 | config |= WC_RXA_IRQ_ENABLE; | ||
476 | max3110_out(max, config); | ||
477 | #else | ||
478 | /* if IRQ is disabled, start a read thread for input data */ | ||
479 | max->read_thread = | ||
480 | kthread_run(max3110_read_thread, max, "max3110_read"); | ||
481 | #endif | ||
482 | |||
483 | max->cur_conf = config; | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | static void serial_m3110_shutdown(struct uart_port *port) | ||
488 | { | ||
489 | struct uart_max3110 *max = | ||
490 | container_of(port, struct uart_max3110, port); | ||
491 | u16 config; | ||
492 | |||
493 | if (max->read_thread) { | ||
494 | kthread_stop(max->read_thread); | ||
495 | max->read_thread = NULL; | ||
496 | } | ||
497 | |||
498 | #ifdef CONFIG_MRST_MAX3110_IRQ | ||
499 | free_irq(max->irq, max); | ||
500 | #endif | ||
501 | |||
502 | /* Disable interrupts from this port */ | ||
503 | config = WC_TAG | WC_SW_SHDI; | ||
504 | max3110_out(max, config); | ||
505 | } | ||
506 | |||
507 | static void serial_m3110_release_port(struct uart_port *port) | ||
508 | { | ||
509 | } | ||
510 | |||
511 | static int serial_m3110_request_port(struct uart_port *port) | ||
512 | { | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static void serial_m3110_config_port(struct uart_port *port, int flags) | ||
517 | { | ||
518 | /* give it fake type */ | ||
519 | port->type = PORT_PXA; | ||
520 | } | ||
521 | |||
522 | static int | ||
523 | serial_m3110_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
524 | { | ||
525 | /* we don't want the core code to modify any port params */ | ||
526 | return -EINVAL; | ||
527 | } | ||
528 | |||
529 | |||
530 | static const char *serial_m3110_type(struct uart_port *port) | ||
531 | { | ||
532 | struct uart_max3110 *max = | ||
533 | container_of(port, struct uart_max3110, port); | ||
534 | return max->name; | ||
535 | } | ||
536 | |||
537 | static void | ||
538 | serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios, | ||
539 | struct ktermios *old) | ||
540 | { | ||
541 | struct uart_max3110 *max = | ||
542 | container_of(port, struct uart_max3110, port); | ||
543 | unsigned char cval; | ||
544 | unsigned int baud, parity = 0; | ||
545 | int clk_div = -1; | ||
546 | u16 new_conf = max->cur_conf; | ||
547 | |||
548 | switch (termios->c_cflag & CSIZE) { | ||
549 | case CS7: | ||
550 | cval = UART_LCR_WLEN7; | ||
551 | new_conf |= WC_7BIT_WORD; | ||
552 | break; | ||
553 | default: | ||
554 | case CS8: | ||
555 | cval = UART_LCR_WLEN8; | ||
556 | new_conf |= WC_8BIT_WORD; | ||
557 | break; | ||
558 | } | ||
559 | |||
560 | baud = uart_get_baud_rate(port, termios, old, 0, 230400); | ||
561 | |||
562 | /* first calc the div for 1.8MHZ clock case */ | ||
563 | switch (baud) { | ||
564 | case 300: | ||
565 | clk_div = WC_BAUD_DR384; | ||
566 | break; | ||
567 | case 600: | ||
568 | clk_div = WC_BAUD_DR192; | ||
569 | break; | ||
570 | case 1200: | ||
571 | clk_div = WC_BAUD_DR96; | ||
572 | break; | ||
573 | case 2400: | ||
574 | clk_div = WC_BAUD_DR48; | ||
575 | break; | ||
576 | case 4800: | ||
577 | clk_div = WC_BAUD_DR24; | ||
578 | break; | ||
579 | case 9600: | ||
580 | clk_div = WC_BAUD_DR12; | ||
581 | break; | ||
582 | case 19200: | ||
583 | clk_div = WC_BAUD_DR6; | ||
584 | break; | ||
585 | case 38400: | ||
586 | clk_div = WC_BAUD_DR3; | ||
587 | break; | ||
588 | case 57600: | ||
589 | clk_div = WC_BAUD_DR2; | ||
590 | break; | ||
591 | case 115200: | ||
592 | clk_div = WC_BAUD_DR1; | ||
593 | break; | ||
594 | case 230400: | ||
595 | if (max->clock & MAX3110_HIGH_CLK) | ||
596 | break; | ||
597 | default: | ||
598 | /* pick the previous baud rate */ | ||
599 | baud = max->baud; | ||
600 | clk_div = max->cur_conf & WC_BAUD_DIV_MASK; | ||
601 | tty_termios_encode_baud_rate(termios, baud, baud); | ||
602 | } | ||
603 | |||
604 | if (max->clock & MAX3110_HIGH_CLK) { | ||
605 | clk_div += 1; | ||
606 | /* high clk version max3110 doesn't support B300 */ | ||
607 | if (baud == 300) | ||
608 | baud = 600; | ||
609 | if (baud == 230400) | ||
610 | clk_div = WC_BAUD_DR1; | ||
611 | tty_termios_encode_baud_rate(termios, baud, baud); | ||
612 | } | ||
613 | |||
614 | new_conf = (new_conf & ~WC_BAUD_DIV_MASK) | clk_div; | ||
615 | if (termios->c_cflag & CSTOPB) | ||
616 | new_conf |= WC_2_STOPBITS; | ||
617 | else | ||
618 | new_conf &= ~WC_2_STOPBITS; | ||
619 | |||
620 | if (termios->c_cflag & PARENB) { | ||
621 | new_conf |= WC_PARITY_ENABLE; | ||
622 | parity |= UART_LCR_PARITY; | ||
623 | } else | ||
624 | new_conf &= ~WC_PARITY_ENABLE; | ||
625 | |||
626 | if (!(termios->c_cflag & PARODD)) | ||
627 | parity |= UART_LCR_EPAR; | ||
628 | max->parity = parity; | ||
629 | |||
630 | uart_update_timeout(port, termios->c_cflag, baud); | ||
631 | |||
632 | new_conf |= WC_TAG; | ||
633 | if (new_conf != max->cur_conf) { | ||
634 | max3110_out(max, new_conf); | ||
635 | max->cur_conf = new_conf; | ||
636 | max->baud = baud; | ||
637 | } | ||
638 | } | ||
639 | |||
640 | /* don't handle hw handshaking */ | ||
641 | static unsigned int serial_m3110_get_mctrl(struct uart_port *port) | ||
642 | { | ||
643 | return TIOCM_DSR | TIOCM_CAR | TIOCM_DSR; | ||
644 | } | ||
645 | |||
646 | static void serial_m3110_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
647 | { | ||
648 | } | ||
649 | |||
650 | static void serial_m3110_break_ctl(struct uart_port *port, int break_state) | ||
651 | { | ||
652 | } | ||
653 | |||
654 | static void serial_m3110_pm(struct uart_port *port, unsigned int state, | ||
655 | unsigned int oldstate) | ||
656 | { | ||
657 | } | ||
658 | |||
659 | static void serial_m3110_enable_ms(struct uart_port *port) | ||
660 | { | ||
661 | } | ||
662 | |||
663 | struct uart_ops serial_m3110_ops = { | ||
664 | .tx_empty = serial_m3110_tx_empty, | ||
665 | .set_mctrl = serial_m3110_set_mctrl, | ||
666 | .get_mctrl = serial_m3110_get_mctrl, | ||
667 | .stop_tx = serial_m3110_stop_tx, | ||
668 | .start_tx = serial_m3110_start_tx, | ||
669 | .stop_rx = serial_m3110_stop_rx, | ||
670 | .enable_ms = serial_m3110_enable_ms, | ||
671 | .break_ctl = serial_m3110_break_ctl, | ||
672 | .startup = serial_m3110_startup, | ||
673 | .shutdown = serial_m3110_shutdown, | ||
674 | .set_termios = serial_m3110_set_termios, /* must have */ | ||
675 | .pm = serial_m3110_pm, | ||
676 | .type = serial_m3110_type, | ||
677 | .release_port = serial_m3110_release_port, | ||
678 | .request_port = serial_m3110_request_port, | ||
679 | .config_port = serial_m3110_config_port, | ||
680 | .verify_port = serial_m3110_verify_port, | ||
681 | }; | ||
682 | |||
683 | static struct uart_driver serial_m3110_reg = { | ||
684 | .owner = THIS_MODULE, | ||
685 | .driver_name = "MRST serial", | ||
686 | .dev_name = "ttyS", | ||
687 | .major = TTY_MAJOR, | ||
688 | .minor = 64, | ||
689 | .nr = 1, | ||
690 | .cons = MRST_CONSOLE, | ||
691 | }; | ||
692 | |||
693 | static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state) | ||
694 | { | ||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | static int serial_m3110_resume(struct spi_device *spi) | ||
699 | { | ||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | static struct dw_spi_chip spi0_uart = { | ||
704 | .poll_mode = 1, | ||
705 | .enable_dma = 0, | ||
706 | .type = SPI_FRF_SPI, | ||
707 | }; | ||
708 | |||
709 | static int serial_m3110_probe(struct spi_device *spi) | ||
710 | { | ||
711 | struct uart_max3110 *max; | ||
712 | int ret; | ||
713 | unsigned char *buffer; | ||
714 | u16 res; | ||
715 | max = kzalloc(sizeof(*max), GFP_KERNEL); | ||
716 | if (!max) | ||
717 | return -ENOMEM; | ||
718 | |||
719 | /* set spi info */ | ||
720 | spi->mode = SPI_MODE_0; | ||
721 | spi->bits_per_word = 16; | ||
722 | max->clock = MAX3110_HIGH_CLK; | ||
723 | spi->controller_data = &spi0_uart; | ||
724 | |||
725 | spi_setup(spi); | ||
726 | |||
727 | max->port.type = PORT_PXA; /* need apply for a max3110 type */ | ||
728 | max->port.fifosize = 2; /* only have 16b buffer */ | ||
729 | max->port.ops = &serial_m3110_ops; | ||
730 | max->port.line = 0; | ||
731 | max->port.dev = &spi->dev; | ||
732 | max->port.uartclk = 115200; | ||
733 | |||
734 | max->spi = spi; | ||
735 | max->name = spi->modalias; /* use spi name as the name */ | ||
736 | max->irq = (u16)spi->irq; | ||
737 | |||
738 | mutex_init(&max->thread_mutex); | ||
739 | |||
740 | max->word_7bits = 0; | ||
741 | max->parity = 0; | ||
742 | max->baud = 0; | ||
743 | |||
744 | max->cur_conf = 0; | ||
745 | max->uart_flags = 0; | ||
746 | |||
747 | /* Check if reading configuration register returns something sane */ | ||
748 | |||
749 | res = RC_TAG; | ||
750 | ret = max3110_write_then_read(max, (u8 *)&res, (u8 *)&res, 2, 0); | ||
751 | if (ret < 0 || res == 0 || res == 0xffff) { | ||
752 | printk(KERN_ERR "MAX3111 deemed not present (conf reg %04x)", | ||
753 | res); | ||
754 | ret = -ENODEV; | ||
755 | goto err_get_page; | ||
756 | } | ||
757 | buffer = (unsigned char *)__get_free_page(GFP_KERNEL); | ||
758 | if (!buffer) { | ||
759 | ret = -ENOMEM; | ||
760 | goto err_get_page; | ||
761 | } | ||
762 | max->con_xmit.buf = (unsigned char *)buffer; | ||
763 | max->con_xmit.head = max->con_xmit.tail = 0; | ||
764 | |||
765 | max->main_thread = kthread_run(max3110_main_thread, | ||
766 | max, "max3110_main"); | ||
767 | if (IS_ERR(max->main_thread)) { | ||
768 | ret = PTR_ERR(max->main_thread); | ||
769 | goto err_kthread; | ||
770 | } | ||
771 | |||
772 | pmax = max; | ||
773 | /* give membase a psudo value to pass serial_core's check */ | ||
774 | max->port.membase = (void *)0xff110000; | ||
775 | uart_add_one_port(&serial_m3110_reg, &max->port); | ||
776 | |||
777 | return 0; | ||
778 | |||
779 | err_kthread: | ||
780 | free_page((unsigned long)buffer); | ||
781 | err_get_page: | ||
782 | pmax = NULL; | ||
783 | kfree(max); | ||
784 | return ret; | ||
785 | } | ||
786 | |||
787 | static int max3110_remove(struct spi_device *dev) | ||
788 | { | ||
789 | struct uart_max3110 *max = pmax; | ||
790 | |||
791 | if (!pmax) | ||
792 | return 0; | ||
793 | |||
794 | pmax = NULL; | ||
795 | uart_remove_one_port(&serial_m3110_reg, &max->port); | ||
796 | |||
797 | free_page((unsigned long)max->con_xmit.buf); | ||
798 | |||
799 | if (max->main_thread) | ||
800 | kthread_stop(max->main_thread); | ||
801 | |||
802 | kfree(max); | ||
803 | return 0; | ||
804 | } | ||
805 | |||
806 | static struct spi_driver uart_max3110_driver = { | ||
807 | .driver = { | ||
808 | .name = "spi_max3111", | ||
809 | .bus = &spi_bus_type, | ||
810 | .owner = THIS_MODULE, | ||
811 | }, | ||
812 | .probe = serial_m3110_probe, | ||
813 | .remove = __devexit_p(max3110_remove), | ||
814 | .suspend = serial_m3110_suspend, | ||
815 | .resume = serial_m3110_resume, | ||
816 | }; | ||
817 | |||
818 | |||
819 | int __init serial_m3110_init(void) | ||
820 | { | ||
821 | int ret = 0; | ||
822 | |||
823 | ret = uart_register_driver(&serial_m3110_reg); | ||
824 | if (ret) | ||
825 | return ret; | ||
826 | |||
827 | ret = spi_register_driver(&uart_max3110_driver); | ||
828 | if (ret) | ||
829 | uart_unregister_driver(&serial_m3110_reg); | ||
830 | |||
831 | return ret; | ||
832 | } | ||
833 | |||
834 | void __exit serial_m3110_exit(void) | ||
835 | { | ||
836 | spi_unregister_driver(&uart_max3110_driver); | ||
837 | uart_unregister_driver(&serial_m3110_reg); | ||
838 | } | ||
839 | |||
840 | module_init(serial_m3110_init); | ||
841 | module_exit(serial_m3110_exit); | ||
842 | |||
843 | MODULE_LICENSE("GPL"); | ||
844 | MODULE_ALIAS("max3110-uart"); | ||
diff --git a/drivers/serial/mrst_max3110.h b/drivers/serial/mrst_max3110.h new file mode 100644 index 000000000000..363478acb2c3 --- /dev/null +++ b/drivers/serial/mrst_max3110.h | |||
@@ -0,0 +1,59 @@ | |||
1 | #ifndef _MRST_MAX3110_H | ||
2 | #define _MRST_MAX3110_H | ||
3 | |||
4 | #define MAX3110_HIGH_CLK 0x1 /* 3.6864 MHZ */ | ||
5 | #define MAX3110_LOW_CLK 0x0 /* 1.8432 MHZ */ | ||
6 | |||
7 | /* status bits for all 4 MAX3110 operate modes */ | ||
8 | #define MAX3110_READ_DATA_AVAILABLE (1 << 15) | ||
9 | #define MAX3110_WRITE_BUF_EMPTY (1 << 14) | ||
10 | |||
11 | #define WC_TAG (3 << 14) | ||
12 | #define RC_TAG (1 << 14) | ||
13 | #define WD_TAG (2 << 14) | ||
14 | #define RD_TAG (0 << 14) | ||
15 | |||
16 | /* bits def for write configuration */ | ||
17 | #define WC_FIFO_ENABLE_MASK (1 << 13) | ||
18 | #define WC_FIFO_ENABLE (0 << 13) | ||
19 | |||
20 | #define WC_SW_SHDI (1 << 12) | ||
21 | |||
22 | #define WC_IRQ_MASK (0xF << 8) | ||
23 | #define WC_TXE_IRQ_ENABLE (1 << 11) /* TX empty irq */ | ||
24 | #define WC_RXA_IRQ_ENABLE (1 << 10) /* RX availabe irq */ | ||
25 | #define WC_PAR_HIGH_IRQ_ENABLE (1 << 9) | ||
26 | #define WC_REC_ACT_IRQ_ENABLE (1 << 8) | ||
27 | |||
28 | #define WC_IRDA_ENABLE (1 << 7) | ||
29 | |||
30 | #define WC_STOPBITS_MASK (1 << 6) | ||
31 | #define WC_2_STOPBITS (1 << 6) | ||
32 | #define WC_1_STOPBITS (0 << 6) | ||
33 | |||
34 | #define WC_PARITY_ENABLE_MASK (1 << 5) | ||
35 | #define WC_PARITY_ENABLE (1 << 5) | ||
36 | |||
37 | #define WC_WORDLEN_MASK (1 << 4) | ||
38 | #define WC_7BIT_WORD (1 << 4) | ||
39 | #define WC_8BIT_WORD (0 << 4) | ||
40 | |||
41 | #define WC_BAUD_DIV_MASK (0xF) | ||
42 | #define WC_BAUD_DR1 (0x0) | ||
43 | #define WC_BAUD_DR2 (0x1) | ||
44 | #define WC_BAUD_DR4 (0x2) | ||
45 | #define WC_BAUD_DR8 (0x3) | ||
46 | #define WC_BAUD_DR16 (0x4) | ||
47 | #define WC_BAUD_DR32 (0x5) | ||
48 | #define WC_BAUD_DR64 (0x6) | ||
49 | #define WC_BAUD_DR128 (0x7) | ||
50 | #define WC_BAUD_DR3 (0x8) | ||
51 | #define WC_BAUD_DR6 (0x9) | ||
52 | #define WC_BAUD_DR12 (0xA) | ||
53 | #define WC_BAUD_DR24 (0xB) | ||
54 | #define WC_BAUD_DR48 (0xC) | ||
55 | #define WC_BAUD_DR96 (0xD) | ||
56 | #define WC_BAUD_DR192 (0xE) | ||
57 | #define WC_BAUD_DR384 (0xF) | ||
58 | |||
59 | #endif | ||
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 7f2830709512..cd8511298bcb 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -58,9 +58,9 @@ static struct lock_class_key port_lock_key; | |||
58 | #define uart_console(port) (0) | 58 | #define uart_console(port) (0) |
59 | #endif | 59 | #endif |
60 | 60 | ||
61 | static void uart_change_speed(struct uart_state *state, | 61 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, |
62 | struct ktermios *old_termios); | 62 | struct ktermios *old_termios); |
63 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); | 63 | static void __uart_wait_until_sent(struct uart_port *port, int timeout); |
64 | static void uart_change_pm(struct uart_state *state, int pm_state); | 64 | static void uart_change_pm(struct uart_state *state, int pm_state); |
65 | 65 | ||
66 | /* | 66 | /* |
@@ -137,7 +137,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) | |||
137 | * Startup the port. This will be called once per open. All calls | 137 | * Startup the port. This will be called once per open. All calls |
138 | * will be serialised by the per-port mutex. | 138 | * will be serialised by the per-port mutex. |
139 | */ | 139 | */ |
140 | static int uart_startup(struct uart_state *state, int init_hw) | 140 | static int uart_startup(struct tty_struct *tty, struct uart_state *state, int init_hw) |
141 | { | 141 | { |
142 | struct uart_port *uport = state->uart_port; | 142 | struct uart_port *uport = state->uart_port; |
143 | struct tty_port *port = &state->port; | 143 | struct tty_port *port = &state->port; |
@@ -152,7 +152,7 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
152 | * once we have successfully opened the port. Also set | 152 | * once we have successfully opened the port. Also set |
153 | * up the tty->alt_speed kludge | 153 | * up the tty->alt_speed kludge |
154 | */ | 154 | */ |
155 | set_bit(TTY_IO_ERROR, &port->tty->flags); | 155 | set_bit(TTY_IO_ERROR, &tty->flags); |
156 | 156 | ||
157 | if (uport->type == PORT_UNKNOWN) | 157 | if (uport->type == PORT_UNKNOWN) |
158 | return 0; | 158 | return 0; |
@@ -177,26 +177,26 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
177 | /* | 177 | /* |
178 | * Initialise the hardware port settings. | 178 | * Initialise the hardware port settings. |
179 | */ | 179 | */ |
180 | uart_change_speed(state, NULL); | 180 | uart_change_speed(tty, state, NULL); |
181 | 181 | ||
182 | /* | 182 | /* |
183 | * Setup the RTS and DTR signals once the | 183 | * Setup the RTS and DTR signals once the |
184 | * port is open and ready to respond. | 184 | * port is open and ready to respond. |
185 | */ | 185 | */ |
186 | if (port->tty->termios->c_cflag & CBAUD) | 186 | if (tty->termios->c_cflag & CBAUD) |
187 | uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); | 187 | uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); |
188 | } | 188 | } |
189 | 189 | ||
190 | if (port->flags & ASYNC_CTS_FLOW) { | 190 | if (port->flags & ASYNC_CTS_FLOW) { |
191 | spin_lock_irq(&uport->lock); | 191 | spin_lock_irq(&uport->lock); |
192 | if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) | 192 | if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) |
193 | port->tty->hw_stopped = 1; | 193 | tty->hw_stopped = 1; |
194 | spin_unlock_irq(&uport->lock); | 194 | spin_unlock_irq(&uport->lock); |
195 | } | 195 | } |
196 | 196 | ||
197 | set_bit(ASYNCB_INITIALIZED, &port->flags); | 197 | set_bit(ASYNCB_INITIALIZED, &port->flags); |
198 | 198 | ||
199 | clear_bit(TTY_IO_ERROR, &port->tty->flags); | 199 | clear_bit(TTY_IO_ERROR, &tty->flags); |
200 | } | 200 | } |
201 | 201 | ||
202 | if (retval && capable(CAP_SYS_ADMIN)) | 202 | if (retval && capable(CAP_SYS_ADMIN)) |
@@ -210,11 +210,10 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
210 | * DTR is dropped if the hangup on close termio flag is on. Calls to | 210 | * DTR is dropped if the hangup on close termio flag is on. Calls to |
211 | * uart_shutdown are serialised by the per-port semaphore. | 211 | * uart_shutdown are serialised by the per-port semaphore. |
212 | */ | 212 | */ |
213 | static void uart_shutdown(struct uart_state *state) | 213 | static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) |
214 | { | 214 | { |
215 | struct uart_port *uport = state->uart_port; | 215 | struct uart_port *uport = state->uart_port; |
216 | struct tty_port *port = &state->port; | 216 | struct tty_port *port = &state->port; |
217 | struct tty_struct *tty = port->tty; | ||
218 | 217 | ||
219 | /* | 218 | /* |
220 | * Set the TTY IO error marker | 219 | * Set the TTY IO error marker |
@@ -430,11 +429,10 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) | |||
430 | EXPORT_SYMBOL(uart_get_divisor); | 429 | EXPORT_SYMBOL(uart_get_divisor); |
431 | 430 | ||
432 | /* FIXME: Consistent locking policy */ | 431 | /* FIXME: Consistent locking policy */ |
433 | static void | 432 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, |
434 | uart_change_speed(struct uart_state *state, struct ktermios *old_termios) | 433 | struct ktermios *old_termios) |
435 | { | 434 | { |
436 | struct tty_port *port = &state->port; | 435 | struct tty_port *port = &state->port; |
437 | struct tty_struct *tty = port->tty; | ||
438 | struct uart_port *uport = state->uart_port; | 436 | struct uart_port *uport = state->uart_port; |
439 | struct ktermios *termios; | 437 | struct ktermios *termios; |
440 | 438 | ||
@@ -463,8 +461,8 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios) | |||
463 | uport->ops->set_termios(uport, termios, old_termios); | 461 | uport->ops->set_termios(uport, termios, old_termios); |
464 | } | 462 | } |
465 | 463 | ||
466 | static inline int | 464 | static inline int __uart_put_char(struct uart_port *port, |
467 | __uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c) | 465 | struct circ_buf *circ, unsigned char c) |
468 | { | 466 | { |
469 | unsigned long flags; | 467 | unsigned long flags; |
470 | int ret = 0; | 468 | int ret = 0; |
@@ -494,8 +492,8 @@ static void uart_flush_chars(struct tty_struct *tty) | |||
494 | uart_start(tty); | 492 | uart_start(tty); |
495 | } | 493 | } |
496 | 494 | ||
497 | static int | 495 | static int uart_write(struct tty_struct *tty, |
498 | uart_write(struct tty_struct *tty, const unsigned char *buf, int count) | 496 | const unsigned char *buf, int count) |
499 | { | 497 | { |
500 | struct uart_state *state = tty->driver_data; | 498 | struct uart_state *state = tty->driver_data; |
501 | struct uart_port *port; | 499 | struct uart_port *port; |
@@ -675,7 +673,7 @@ static int uart_get_info(struct uart_state *state, | |||
675 | return 0; | 673 | return 0; |
676 | } | 674 | } |
677 | 675 | ||
678 | static int uart_set_info(struct uart_state *state, | 676 | static int uart_set_info(struct tty_struct *tty, struct uart_state *state, |
679 | struct serial_struct __user *newinfo) | 677 | struct serial_struct __user *newinfo) |
680 | { | 678 | { |
681 | struct serial_struct new_serial; | 679 | struct serial_struct new_serial; |
@@ -770,7 +768,7 @@ static int uart_set_info(struct uart_state *state, | |||
770 | * We need to shutdown the serial port at the old | 768 | * We need to shutdown the serial port at the old |
771 | * port/type/irq combination. | 769 | * port/type/irq combination. |
772 | */ | 770 | */ |
773 | uart_shutdown(state); | 771 | uart_shutdown(tty, state); |
774 | } | 772 | } |
775 | 773 | ||
776 | if (change_port) { | 774 | if (change_port) { |
@@ -869,25 +867,27 @@ static int uart_set_info(struct uart_state *state, | |||
869 | "is deprecated.\n", current->comm, | 867 | "is deprecated.\n", current->comm, |
870 | tty_name(port->tty, buf)); | 868 | tty_name(port->tty, buf)); |
871 | } | 869 | } |
872 | uart_change_speed(state, NULL); | 870 | uart_change_speed(tty, state, NULL); |
873 | } | 871 | } |
874 | } else | 872 | } else |
875 | retval = uart_startup(state, 1); | 873 | retval = uart_startup(tty, state, 1); |
876 | exit: | 874 | exit: |
877 | mutex_unlock(&port->mutex); | 875 | mutex_unlock(&port->mutex); |
878 | return retval; | 876 | return retval; |
879 | } | 877 | } |
880 | 878 | ||
881 | 879 | /** | |
882 | /* | 880 | * uart_get_lsr_info - get line status register info |
883 | * uart_get_lsr_info - get line status register info. | 881 | * @tty: tty associated with the UART |
884 | * Note: uart_ioctl protects us against hangups. | 882 | * @state: UART being queried |
883 | * @value: returned modem value | ||
884 | * | ||
885 | * Note: uart_ioctl protects us against hangups. | ||
885 | */ | 886 | */ |
886 | static int uart_get_lsr_info(struct uart_state *state, | 887 | static int uart_get_lsr_info(struct tty_struct *tty, |
887 | unsigned int __user *value) | 888 | struct uart_state *state, unsigned int __user *value) |
888 | { | 889 | { |
889 | struct uart_port *uport = state->uart_port; | 890 | struct uart_port *uport = state->uart_port; |
890 | struct tty_port *port = &state->port; | ||
891 | unsigned int result; | 891 | unsigned int result; |
892 | 892 | ||
893 | result = uport->ops->tx_empty(uport); | 893 | result = uport->ops->tx_empty(uport); |
@@ -900,7 +900,7 @@ static int uart_get_lsr_info(struct uart_state *state, | |||
900 | */ | 900 | */ |
901 | if (uport->x_char || | 901 | if (uport->x_char || |
902 | ((uart_circ_chars_pending(&state->xmit) > 0) && | 902 | ((uart_circ_chars_pending(&state->xmit) > 0) && |
903 | !port->tty->stopped && !port->tty->hw_stopped)) | 903 | !tty->stopped && !tty->hw_stopped)) |
904 | result &= ~TIOCSER_TEMT; | 904 | result &= ~TIOCSER_TEMT; |
905 | 905 | ||
906 | return put_user(result, value); | 906 | return put_user(result, value); |
@@ -961,7 +961,7 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state) | |||
961 | return 0; | 961 | return 0; |
962 | } | 962 | } |
963 | 963 | ||
964 | static int uart_do_autoconfig(struct uart_state *state) | 964 | static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state) |
965 | { | 965 | { |
966 | struct uart_port *uport = state->uart_port; | 966 | struct uart_port *uport = state->uart_port; |
967 | struct tty_port *port = &state->port; | 967 | struct tty_port *port = &state->port; |
@@ -980,7 +980,7 @@ static int uart_do_autoconfig(struct uart_state *state) | |||
980 | 980 | ||
981 | ret = -EBUSY; | 981 | ret = -EBUSY; |
982 | if (tty_port_users(port) == 1) { | 982 | if (tty_port_users(port) == 1) { |
983 | uart_shutdown(state); | 983 | uart_shutdown(tty, state); |
984 | 984 | ||
985 | /* | 985 | /* |
986 | * If we already have a port type configured, | 986 | * If we already have a port type configured, |
@@ -999,7 +999,7 @@ static int uart_do_autoconfig(struct uart_state *state) | |||
999 | */ | 999 | */ |
1000 | uport->ops->config_port(uport, flags); | 1000 | uport->ops->config_port(uport, flags); |
1001 | 1001 | ||
1002 | ret = uart_startup(state, 1); | 1002 | ret = uart_startup(tty, state, 1); |
1003 | } | 1003 | } |
1004 | mutex_unlock(&port->mutex); | 1004 | mutex_unlock(&port->mutex); |
1005 | return ret; | 1005 | return ret; |
@@ -1122,11 +1122,11 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, | |||
1122 | break; | 1122 | break; |
1123 | 1123 | ||
1124 | case TIOCSSERIAL: | 1124 | case TIOCSSERIAL: |
1125 | ret = uart_set_info(state, uarg); | 1125 | ret = uart_set_info(tty, state, uarg); |
1126 | break; | 1126 | break; |
1127 | 1127 | ||
1128 | case TIOCSERCONFIG: | 1128 | case TIOCSERCONFIG: |
1129 | ret = uart_do_autoconfig(state); | 1129 | ret = uart_do_autoconfig(tty, state); |
1130 | break; | 1130 | break; |
1131 | 1131 | ||
1132 | case TIOCSERGWILD: /* obsolete */ | 1132 | case TIOCSERGWILD: /* obsolete */ |
@@ -1172,7 +1172,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, | |||
1172 | */ | 1172 | */ |
1173 | switch (cmd) { | 1173 | switch (cmd) { |
1174 | case TIOCSERGETLSR: /* Get line status register */ | 1174 | case TIOCSERGETLSR: /* Get line status register */ |
1175 | ret = uart_get_lsr_info(state, uarg); | 1175 | ret = uart_get_lsr_info(tty, state, uarg); |
1176 | break; | 1176 | break; |
1177 | 1177 | ||
1178 | default: { | 1178 | default: { |
@@ -1194,7 +1194,7 @@ static void uart_set_ldisc(struct tty_struct *tty) | |||
1194 | struct uart_port *uport = state->uart_port; | 1194 | struct uart_port *uport = state->uart_port; |
1195 | 1195 | ||
1196 | if (uport->ops->set_ldisc) | 1196 | if (uport->ops->set_ldisc) |
1197 | uport->ops->set_ldisc(uport); | 1197 | uport->ops->set_ldisc(uport, tty->termios->c_line); |
1198 | } | 1198 | } |
1199 | 1199 | ||
1200 | static void uart_set_termios(struct tty_struct *tty, | 1200 | static void uart_set_termios(struct tty_struct *tty, |
@@ -1219,7 +1219,7 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1219 | return; | 1219 | return; |
1220 | } | 1220 | } |
1221 | 1221 | ||
1222 | uart_change_speed(state, old_termios); | 1222 | uart_change_speed(tty, state, old_termios); |
1223 | 1223 | ||
1224 | /* Handle transition to B0 status */ | 1224 | /* Handle transition to B0 status */ |
1225 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) | 1225 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) |
@@ -1272,8 +1272,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1272 | struct uart_state *state = tty->driver_data; | 1272 | struct uart_state *state = tty->driver_data; |
1273 | struct tty_port *port; | 1273 | struct tty_port *port; |
1274 | struct uart_port *uport; | 1274 | struct uart_port *uport; |
1275 | unsigned long flags; | ||
1275 | 1276 | ||
1276 | BUG_ON(!kernel_locked()); | 1277 | BUG_ON(!tty_locked()); |
1277 | 1278 | ||
1278 | if (!state) | 1279 | if (!state) |
1279 | return; | 1280 | return; |
@@ -1284,9 +1285,12 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1284 | pr_debug("uart_close(%d) called\n", uport->line); | 1285 | pr_debug("uart_close(%d) called\n", uport->line); |
1285 | 1286 | ||
1286 | mutex_lock(&port->mutex); | 1287 | mutex_lock(&port->mutex); |
1288 | spin_lock_irqsave(&port->lock, flags); | ||
1287 | 1289 | ||
1288 | if (tty_hung_up_p(filp)) | 1290 | if (tty_hung_up_p(filp)) { |
1291 | spin_unlock_irqrestore(&port->lock, flags); | ||
1289 | goto done; | 1292 | goto done; |
1293 | } | ||
1290 | 1294 | ||
1291 | if ((tty->count == 1) && (port->count != 1)) { | 1295 | if ((tty->count == 1) && (port->count != 1)) { |
1292 | /* | 1296 | /* |
@@ -1305,8 +1309,10 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1305 | tty->name, port->count); | 1309 | tty->name, port->count); |
1306 | port->count = 0; | 1310 | port->count = 0; |
1307 | } | 1311 | } |
1308 | if (port->count) | 1312 | if (port->count) { |
1313 | spin_unlock_irqrestore(&port->lock, flags); | ||
1309 | goto done; | 1314 | goto done; |
1315 | } | ||
1310 | 1316 | ||
1311 | /* | 1317 | /* |
1312 | * Now we wait for the transmit buffer to clear; and we notify | 1318 | * Now we wait for the transmit buffer to clear; and we notify |
@@ -1314,9 +1320,18 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1314 | * setting tty->closing. | 1320 | * setting tty->closing. |
1315 | */ | 1321 | */ |
1316 | tty->closing = 1; | 1322 | tty->closing = 1; |
1323 | spin_unlock_irqrestore(&port->lock, flags); | ||
1317 | 1324 | ||
1318 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 1325 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) { |
1319 | tty_wait_until_sent(tty, msecs_to_jiffies(port->closing_wait)); | 1326 | /* |
1327 | * hack: open-coded tty_wait_until_sent to avoid | ||
1328 | * recursive tty_lock | ||
1329 | */ | ||
1330 | long timeout = msecs_to_jiffies(port->closing_wait); | ||
1331 | if (wait_event_interruptible_timeout(tty->write_wait, | ||
1332 | !tty_chars_in_buffer(tty), timeout) >= 0) | ||
1333 | __uart_wait_until_sent(uport, timeout); | ||
1334 | } | ||
1320 | 1335 | ||
1321 | /* | 1336 | /* |
1322 | * At this point, we stop accepting input. To do this, we | 1337 | * At this point, we stop accepting input. To do this, we |
@@ -1332,45 +1347,47 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1332 | * has completely drained; this is especially | 1347 | * has completely drained; this is especially |
1333 | * important if there is a transmit FIFO! | 1348 | * important if there is a transmit FIFO! |
1334 | */ | 1349 | */ |
1335 | uart_wait_until_sent(tty, uport->timeout); | 1350 | __uart_wait_until_sent(uport, uport->timeout); |
1336 | } | 1351 | } |
1337 | 1352 | ||
1338 | uart_shutdown(state); | 1353 | uart_shutdown(tty, state); |
1339 | uart_flush_buffer(tty); | 1354 | uart_flush_buffer(tty); |
1340 | 1355 | ||
1341 | tty_ldisc_flush(tty); | 1356 | tty_ldisc_flush(tty); |
1342 | 1357 | ||
1343 | tty->closing = 0; | ||
1344 | tty_port_tty_set(port, NULL); | 1358 | tty_port_tty_set(port, NULL); |
1359 | spin_lock_irqsave(&port->lock, flags); | ||
1360 | tty->closing = 0; | ||
1345 | 1361 | ||
1346 | if (port->blocked_open) { | 1362 | if (port->blocked_open) { |
1363 | spin_unlock_irqrestore(&port->lock, flags); | ||
1347 | if (port->close_delay) | 1364 | if (port->close_delay) |
1348 | msleep_interruptible(port->close_delay); | 1365 | msleep_interruptible(port->close_delay); |
1366 | spin_lock_irqsave(&port->lock, flags); | ||
1349 | } else if (!uart_console(uport)) { | 1367 | } else if (!uart_console(uport)) { |
1368 | spin_unlock_irqrestore(&port->lock, flags); | ||
1350 | uart_change_pm(state, 3); | 1369 | uart_change_pm(state, 3); |
1370 | spin_lock_irqsave(&port->lock, flags); | ||
1351 | } | 1371 | } |
1352 | 1372 | ||
1353 | /* | 1373 | /* |
1354 | * Wake up anyone trying to open this port. | 1374 | * Wake up anyone trying to open this port. |
1355 | */ | 1375 | */ |
1356 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | 1376 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); |
1377 | spin_unlock_irqrestore(&port->lock, flags); | ||
1357 | wake_up_interruptible(&port->open_wait); | 1378 | wake_up_interruptible(&port->open_wait); |
1358 | 1379 | ||
1359 | done: | 1380 | done: |
1360 | mutex_unlock(&port->mutex); | 1381 | mutex_unlock(&port->mutex); |
1361 | } | 1382 | } |
1362 | 1383 | ||
1363 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | 1384 | static void __uart_wait_until_sent(struct uart_port *port, int timeout) |
1364 | { | 1385 | { |
1365 | struct uart_state *state = tty->driver_data; | ||
1366 | struct uart_port *port = state->uart_port; | ||
1367 | unsigned long char_time, expire; | 1386 | unsigned long char_time, expire; |
1368 | 1387 | ||
1369 | if (port->type == PORT_UNKNOWN || port->fifosize == 0) | 1388 | if (port->type == PORT_UNKNOWN || port->fifosize == 0) |
1370 | return; | 1389 | return; |
1371 | 1390 | ||
1372 | lock_kernel(); | ||
1373 | |||
1374 | /* | 1391 | /* |
1375 | * Set the check interval to be 1/5 of the estimated time to | 1392 | * Set the check interval to be 1/5 of the estimated time to |
1376 | * send a single character, and make it at least 1. The check | 1393 | * send a single character, and make it at least 1. The check |
@@ -1416,7 +1433,16 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1416 | break; | 1433 | break; |
1417 | } | 1434 | } |
1418 | set_current_state(TASK_RUNNING); /* might not be needed */ | 1435 | set_current_state(TASK_RUNNING); /* might not be needed */ |
1419 | unlock_kernel(); | 1436 | } |
1437 | |||
1438 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | ||
1439 | { | ||
1440 | struct uart_state *state = tty->driver_data; | ||
1441 | struct uart_port *port = state->uart_port; | ||
1442 | |||
1443 | tty_lock(); | ||
1444 | __uart_wait_until_sent(port, timeout); | ||
1445 | tty_unlock(); | ||
1420 | } | 1446 | } |
1421 | 1447 | ||
1422 | /* | 1448 | /* |
@@ -1429,16 +1455,19 @@ static void uart_hangup(struct tty_struct *tty) | |||
1429 | { | 1455 | { |
1430 | struct uart_state *state = tty->driver_data; | 1456 | struct uart_state *state = tty->driver_data; |
1431 | struct tty_port *port = &state->port; | 1457 | struct tty_port *port = &state->port; |
1458 | unsigned long flags; | ||
1432 | 1459 | ||
1433 | BUG_ON(!kernel_locked()); | 1460 | BUG_ON(!tty_locked()); |
1434 | pr_debug("uart_hangup(%d)\n", state->uart_port->line); | 1461 | pr_debug("uart_hangup(%d)\n", state->uart_port->line); |
1435 | 1462 | ||
1436 | mutex_lock(&port->mutex); | 1463 | mutex_lock(&port->mutex); |
1437 | if (port->flags & ASYNC_NORMAL_ACTIVE) { | 1464 | if (port->flags & ASYNC_NORMAL_ACTIVE) { |
1438 | uart_flush_buffer(tty); | 1465 | uart_flush_buffer(tty); |
1439 | uart_shutdown(state); | 1466 | uart_shutdown(tty, state); |
1467 | spin_lock_irqsave(&port->lock, flags); | ||
1440 | port->count = 0; | 1468 | port->count = 0; |
1441 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | 1469 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); |
1470 | spin_unlock_irqrestore(&port->lock, flags); | ||
1442 | tty_port_tty_set(port, NULL); | 1471 | tty_port_tty_set(port, NULL); |
1443 | wake_up_interruptible(&port->open_wait); | 1472 | wake_up_interruptible(&port->open_wait); |
1444 | wake_up_interruptible(&port->delta_msr_wait); | 1473 | wake_up_interruptible(&port->delta_msr_wait); |
@@ -1446,15 +1475,19 @@ static void uart_hangup(struct tty_struct *tty) | |||
1446 | mutex_unlock(&port->mutex); | 1475 | mutex_unlock(&port->mutex); |
1447 | } | 1476 | } |
1448 | 1477 | ||
1449 | /* | 1478 | /** |
1450 | * Copy across the serial console cflag setting into the termios settings | 1479 | * uart_update_termios - update the terminal hw settings |
1451 | * for the initial open of the port. This allows continuity between the | 1480 | * @tty: tty associated with UART |
1452 | * kernel settings, and the settings init adopts when it opens the port | 1481 | * @state: UART to update |
1453 | * for the first time. | 1482 | * |
1483 | * Copy across the serial console cflag setting into the termios settings | ||
1484 | * for the initial open of the port. This allows continuity between the | ||
1485 | * kernel settings, and the settings init adopts when it opens the port | ||
1486 | * for the first time. | ||
1454 | */ | 1487 | */ |
1455 | static void uart_update_termios(struct uart_state *state) | 1488 | static void uart_update_termios(struct tty_struct *tty, |
1489 | struct uart_state *state) | ||
1456 | { | 1490 | { |
1457 | struct tty_struct *tty = state->port.tty; | ||
1458 | struct uart_port *port = state->uart_port; | 1491 | struct uart_port *port = state->uart_port; |
1459 | 1492 | ||
1460 | if (uart_console(port) && port->cons->cflag) { | 1493 | if (uart_console(port) && port->cons->cflag) { |
@@ -1471,7 +1504,7 @@ static void uart_update_termios(struct uart_state *state) | |||
1471 | /* | 1504 | /* |
1472 | * Make termios settings take effect. | 1505 | * Make termios settings take effect. |
1473 | */ | 1506 | */ |
1474 | uart_change_speed(state, NULL); | 1507 | uart_change_speed(tty, state, NULL); |
1475 | 1508 | ||
1476 | /* | 1509 | /* |
1477 | * And finally enable the RTS and DTR signals. | 1510 | * And finally enable the RTS and DTR signals. |
@@ -1481,90 +1514,37 @@ static void uart_update_termios(struct uart_state *state) | |||
1481 | } | 1514 | } |
1482 | } | 1515 | } |
1483 | 1516 | ||
1484 | /* | 1517 | static int uart_carrier_raised(struct tty_port *port) |
1485 | * Block the open until the port is ready. We must be called with | ||
1486 | * the per-port semaphore held. | ||
1487 | */ | ||
1488 | static int | ||
1489 | uart_block_til_ready(struct file *filp, struct uart_state *state) | ||
1490 | { | 1518 | { |
1491 | DECLARE_WAITQUEUE(wait, current); | 1519 | struct uart_state *state = container_of(port, struct uart_state, port); |
1492 | struct uart_port *uport = state->uart_port; | 1520 | struct uart_port *uport = state->uart_port; |
1493 | struct tty_port *port = &state->port; | 1521 | int mctrl; |
1494 | unsigned int mctrl; | 1522 | spin_lock_irq(&uport->lock); |
1495 | 1523 | uport->ops->enable_ms(uport); | |
1496 | port->blocked_open++; | 1524 | mctrl = uport->ops->get_mctrl(uport); |
1497 | port->count--; | 1525 | spin_unlock_irq(&uport->lock); |
1498 | 1526 | if (mctrl & TIOCM_CAR) | |
1499 | add_wait_queue(&port->open_wait, &wait); | 1527 | return 1; |
1500 | while (1) { | 1528 | return 0; |
1501 | set_current_state(TASK_INTERRUPTIBLE); | 1529 | } |
1502 | |||
1503 | /* | ||
1504 | * If we have been hung up, tell userspace/restart open. | ||
1505 | */ | ||
1506 | if (tty_hung_up_p(filp) || port->tty == NULL) | ||
1507 | break; | ||
1508 | |||
1509 | /* | ||
1510 | * If the port has been closed, tell userspace/restart open. | ||
1511 | */ | ||
1512 | if (!(port->flags & ASYNC_INITIALIZED)) | ||
1513 | break; | ||
1514 | 1530 | ||
1515 | /* | 1531 | static void uart_dtr_rts(struct tty_port *port, int onoff) |
1516 | * If non-blocking mode is set, or CLOCAL mode is set, | 1532 | { |
1517 | * we don't want to wait for the modem status lines to | 1533 | struct uart_state *state = container_of(port, struct uart_state, port); |
1518 | * indicate that the port is ready. | 1534 | struct uart_port *uport = state->uart_port; |
1519 | * | ||
1520 | * Also, if the port is not enabled/configured, we want | ||
1521 | * to allow the open to succeed here. Note that we will | ||
1522 | * have set TTY_IO_ERROR for a non-existant port. | ||
1523 | */ | ||
1524 | if ((filp->f_flags & O_NONBLOCK) || | ||
1525 | (port->tty->termios->c_cflag & CLOCAL) || | ||
1526 | (port->tty->flags & (1 << TTY_IO_ERROR))) | ||
1527 | break; | ||
1528 | 1535 | ||
1529 | /* | 1536 | if (onoff) { |
1530 | * Set DTR to allow modem to know we're waiting. Do | 1537 | uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS); |
1531 | * not set RTS here - we want to make sure we catch | ||
1532 | * the data from the modem. | ||
1533 | */ | ||
1534 | if (port->tty->termios->c_cflag & CBAUD) | ||
1535 | uart_set_mctrl(uport, TIOCM_DTR); | ||
1536 | 1538 | ||
1537 | /* | 1539 | /* |
1538 | * and wait for the carrier to indicate that the | 1540 | * If this is the first open to succeed, |
1539 | * modem is ready for us. | 1541 | * adjust things to suit. |
1540 | */ | 1542 | */ |
1541 | spin_lock_irq(&uport->lock); | 1543 | if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags)) |
1542 | uport->ops->enable_ms(uport); | 1544 | uart_update_termios(port->tty, state); |
1543 | mctrl = uport->ops->get_mctrl(uport); | ||
1544 | spin_unlock_irq(&uport->lock); | ||
1545 | if (mctrl & TIOCM_CAR) | ||
1546 | break; | ||
1547 | |||
1548 | mutex_unlock(&port->mutex); | ||
1549 | schedule(); | ||
1550 | mutex_lock(&port->mutex); | ||
1551 | |||
1552 | if (signal_pending(current)) | ||
1553 | break; | ||
1554 | } | 1545 | } |
1555 | set_current_state(TASK_RUNNING); | 1546 | else |
1556 | remove_wait_queue(&port->open_wait, &wait); | 1547 | uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); |
1557 | |||
1558 | port->count++; | ||
1559 | port->blocked_open--; | ||
1560 | |||
1561 | if (signal_pending(current)) | ||
1562 | return -ERESTARTSYS; | ||
1563 | |||
1564 | if (!port->tty || tty_hung_up_p(filp)) | ||
1565 | return -EAGAIN; | ||
1566 | |||
1567 | return 0; | ||
1568 | } | 1548 | } |
1569 | 1549 | ||
1570 | static struct uart_state *uart_get(struct uart_driver *drv, int line) | 1550 | static struct uart_state *uart_get(struct uart_driver *drv, int line) |
@@ -1611,7 +1591,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1611 | struct tty_port *port; | 1591 | struct tty_port *port; |
1612 | int retval, line = tty->index; | 1592 | int retval, line = tty->index; |
1613 | 1593 | ||
1614 | BUG_ON(!kernel_locked()); | 1594 | BUG_ON(!tty_locked()); |
1615 | pr_debug("uart_open(%d) called\n", line); | 1595 | pr_debug("uart_open(%d) called\n", line); |
1616 | 1596 | ||
1617 | /* | 1597 | /* |
@@ -1668,23 +1648,14 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1668 | /* | 1648 | /* |
1669 | * Start up the serial port. | 1649 | * Start up the serial port. |
1670 | */ | 1650 | */ |
1671 | retval = uart_startup(state, 0); | 1651 | retval = uart_startup(tty, state, 0); |
1672 | 1652 | ||
1673 | /* | 1653 | /* |
1674 | * If we succeeded, wait until the port is ready. | 1654 | * If we succeeded, wait until the port is ready. |
1675 | */ | 1655 | */ |
1676 | if (retval == 0) | ||
1677 | retval = uart_block_til_ready(filp, state); | ||
1678 | mutex_unlock(&port->mutex); | 1656 | mutex_unlock(&port->mutex); |
1679 | 1657 | if (retval == 0) | |
1680 | /* | 1658 | retval = tty_port_block_til_ready(port, tty, filp); |
1681 | * If this is the first open to succeed, adjust things to suit. | ||
1682 | */ | ||
1683 | if (retval == 0 && !(port->flags & ASYNC_NORMAL_ACTIVE)) { | ||
1684 | set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | ||
1685 | |||
1686 | uart_update_termios(state); | ||
1687 | } | ||
1688 | 1659 | ||
1689 | fail: | 1660 | fail: |
1690 | return retval; | 1661 | return retval; |
@@ -2010,9 +1981,13 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) | |||
2010 | struct tty_port *port = &state->port; | 1981 | struct tty_port *port = &state->port; |
2011 | struct device *tty_dev; | 1982 | struct device *tty_dev; |
2012 | struct uart_match match = {uport, drv}; | 1983 | struct uart_match match = {uport, drv}; |
1984 | struct tty_struct *tty; | ||
2013 | 1985 | ||
2014 | mutex_lock(&port->mutex); | 1986 | mutex_lock(&port->mutex); |
2015 | 1987 | ||
1988 | /* Must be inside the mutex lock until we convert to tty_port */ | ||
1989 | tty = port->tty; | ||
1990 | |||
2016 | tty_dev = device_find_child(uport->dev, &match, serial_match_port); | 1991 | tty_dev = device_find_child(uport->dev, &match, serial_match_port); |
2017 | if (device_may_wakeup(tty_dev)) { | 1992 | if (device_may_wakeup(tty_dev)) { |
2018 | enable_irq_wake(uport->irq); | 1993 | enable_irq_wake(uport->irq); |
@@ -2105,9 +2080,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) | |||
2105 | ops->set_mctrl(uport, 0); | 2080 | ops->set_mctrl(uport, 0); |
2106 | spin_unlock_irq(&uport->lock); | 2081 | spin_unlock_irq(&uport->lock); |
2107 | if (console_suspend_enabled || !uart_console(uport)) { | 2082 | if (console_suspend_enabled || !uart_console(uport)) { |
2083 | /* Protected by port mutex for now */ | ||
2084 | struct tty_struct *tty = port->tty; | ||
2108 | ret = ops->startup(uport); | 2085 | ret = ops->startup(uport); |
2109 | if (ret == 0) { | 2086 | if (ret == 0) { |
2110 | uart_change_speed(state, NULL); | 2087 | if (tty) |
2088 | uart_change_speed(tty, state, NULL); | ||
2111 | spin_lock_irq(&uport->lock); | 2089 | spin_lock_irq(&uport->lock); |
2112 | ops->set_mctrl(uport, uport->mctrl); | 2090 | ops->set_mctrl(uport, uport->mctrl); |
2113 | ops->start_tx(uport); | 2091 | ops->start_tx(uport); |
@@ -2119,7 +2097,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) | |||
2119 | * Clear the "initialized" flag so we won't try | 2097 | * Clear the "initialized" flag so we won't try |
2120 | * to call the low level drivers shutdown method. | 2098 | * to call the low level drivers shutdown method. |
2121 | */ | 2099 | */ |
2122 | uart_shutdown(state); | 2100 | uart_shutdown(tty, state); |
2123 | } | 2101 | } |
2124 | } | 2102 | } |
2125 | 2103 | ||
@@ -2312,6 +2290,11 @@ static const struct tty_operations uart_ops = { | |||
2312 | #endif | 2290 | #endif |
2313 | }; | 2291 | }; |
2314 | 2292 | ||
2293 | static const struct tty_port_operations uart_port_ops = { | ||
2294 | .carrier_raised = uart_carrier_raised, | ||
2295 | .dtr_rts = uart_dtr_rts, | ||
2296 | }; | ||
2297 | |||
2315 | /** | 2298 | /** |
2316 | * uart_register_driver - register a driver with the uart core layer | 2299 | * uart_register_driver - register a driver with the uart core layer |
2317 | * @drv: low level driver structure | 2300 | * @drv: low level driver structure |
@@ -2368,6 +2351,7 @@ int uart_register_driver(struct uart_driver *drv) | |||
2368 | struct tty_port *port = &state->port; | 2351 | struct tty_port *port = &state->port; |
2369 | 2352 | ||
2370 | tty_port_init(port); | 2353 | tty_port_init(port); |
2354 | port->ops = &uart_port_ops; | ||
2371 | port->close_delay = 500; /* .5 seconds */ | 2355 | port->close_delay = 500; /* .5 seconds */ |
2372 | port->closing_wait = 30000; /* 30 seconds */ | 2356 | port->closing_wait = 30000; /* 30 seconds */ |
2373 | tasklet_init(&state->tlet, uart_tasklet_action, | 2357 | tasklet_init(&state->tlet, uart_tasklet_action, |
diff --git a/drivers/serial/timbuart.c b/drivers/serial/timbuart.c index 67ca642713b8..1f36b7eb7351 100644 --- a/drivers/serial/timbuart.c +++ b/drivers/serial/timbuart.c | |||
@@ -423,7 +423,7 @@ static struct uart_driver timbuart_driver = { | |||
423 | .nr = 1 | 423 | .nr = 1 |
424 | }; | 424 | }; |
425 | 425 | ||
426 | static int timbuart_probe(struct platform_device *dev) | 426 | static int __devinit timbuart_probe(struct platform_device *dev) |
427 | { | 427 | { |
428 | int err, irq; | 428 | int err, irq; |
429 | struct timbuart_port *uart; | 429 | struct timbuart_port *uart; |
@@ -489,7 +489,7 @@ err_mem: | |||
489 | return err; | 489 | return err; |
490 | } | 490 | } |
491 | 491 | ||
492 | static int timbuart_remove(struct platform_device *dev) | 492 | static int __devexit timbuart_remove(struct platform_device *dev) |
493 | { | 493 | { |
494 | struct timbuart_port *uart = platform_get_drvdata(dev); | 494 | struct timbuart_port *uart = platform_get_drvdata(dev); |
495 | 495 | ||
@@ -507,7 +507,7 @@ static struct platform_driver timbuart_platform_driver = { | |||
507 | .owner = THIS_MODULE, | 507 | .owner = THIS_MODULE, |
508 | }, | 508 | }, |
509 | .probe = timbuart_probe, | 509 | .probe = timbuart_probe, |
510 | .remove = timbuart_remove, | 510 | .remove = __devexit_p(timbuart_remove), |
511 | }; | 511 | }; |
512 | 512 | ||
513 | /*--------------------------------------------------------------------------*/ | 513 | /*--------------------------------------------------------------------------*/ |
diff --git a/drivers/staging/easycap/easycap.h b/drivers/staging/easycap/easycap.h index ad836d2d26fe..f3c827eb0abe 100644 --- a/drivers/staging/easycap/easycap.h +++ b/drivers/staging/easycap/easycap.h | |||
@@ -463,15 +463,12 @@ struct data_buffer audio_buffer[]; | |||
463 | void easycap_complete(struct urb *); | 463 | void easycap_complete(struct urb *); |
464 | int easycap_open(struct inode *, struct file *); | 464 | int easycap_open(struct inode *, struct file *); |
465 | int easycap_release(struct inode *, struct file *); | 465 | int easycap_release(struct inode *, struct file *); |
466 | int easycap_ioctl(struct inode *, struct file *, \ | 466 | long easycap_ioctl(struct file *, unsigned int, unsigned long); |
467 | unsigned int, unsigned long); | ||
468 | 467 | ||
469 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | 468 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ |
470 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) | 469 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) |
471 | int easycap_open_noinode(struct file *); | 470 | int easycap_open_noinode(struct file *); |
472 | int easycap_release_noinode(struct file *); | 471 | int easycap_release_noinode(struct file *); |
473 | long easycap_ioctl_noinode(struct file *, \ | ||
474 | unsigned int, unsigned long); | ||
475 | int videodev_release(struct video_device *); | 472 | int videodev_release(struct video_device *); |
476 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ | 473 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ |
477 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | 474 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ |
@@ -515,8 +512,7 @@ void easysnd_complete(struct urb *); | |||
515 | ssize_t easysnd_read(struct file *, char __user *, size_t, loff_t *); | 512 | ssize_t easysnd_read(struct file *, char __user *, size_t, loff_t *); |
516 | int easysnd_open(struct inode *, struct file *); | 513 | int easysnd_open(struct inode *, struct file *); |
517 | int easysnd_release(struct inode *, struct file *); | 514 | int easysnd_release(struct inode *, struct file *); |
518 | int easysnd_ioctl(struct inode *, struct file *, \ | 515 | long easysnd_ioctl(struct file *, unsigned int, unsigned long); |
519 | unsigned int, unsigned long); | ||
520 | unsigned int easysnd_poll(struct file *, poll_table *); | 516 | unsigned int easysnd_poll(struct file *, poll_table *); |
521 | void easysnd_delete(struct kref *); | 517 | void easysnd_delete(struct kref *); |
522 | int submit_audio_urbs(struct easycap *); | 518 | int submit_audio_urbs(struct easycap *); |
diff --git a/drivers/staging/easycap/easycap_ioctl.c b/drivers/staging/easycap/easycap_ioctl.c index 276b63dfe27e..9a42ae02cd5d 100644 --- a/drivers/staging/easycap/easycap_ioctl.c +++ b/drivers/staging/easycap/easycap_ioctl.c | |||
@@ -25,6 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | /*****************************************************************************/ | 26 | /*****************************************************************************/ |
27 | 27 | ||
28 | #include <linux/smp_lock.h> | ||
28 | #include "easycap.h" | 29 | #include "easycap.h" |
29 | #include "easycap_debug.h" | 30 | #include "easycap_debug.h" |
30 | #include "easycap_standard.h" | 31 | #include "easycap_standard.h" |
@@ -773,19 +774,10 @@ while (0xFFFFFFFF != easycap_control[i1].id) { | |||
773 | SAY("WARNING: failed to adjust mute: control not found\n"); | 774 | SAY("WARNING: failed to adjust mute: control not found\n"); |
774 | return -ENOENT; | 775 | return -ENOENT; |
775 | } | 776 | } |
776 | /****************************************************************************/ | 777 | |
777 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | ||
778 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) | ||
779 | long | ||
780 | easycap_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg)\ | ||
781 | { | ||
782 | return easycap_ioctl((struct inode *)NULL, file, cmd, arg); | ||
783 | } | ||
784 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ | ||
785 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
786 | /*--------------------------------------------------------------------------*/ | 778 | /*--------------------------------------------------------------------------*/ |
787 | int easycap_ioctl(struct inode *inode, struct file *file, \ | 779 | static int easycap_ioctl_bkl(struct inode *inode, struct file *file, |
788 | unsigned int cmd, unsigned long arg) | 780 | unsigned int cmd, unsigned long arg) |
789 | { | 781 | { |
790 | static struct easycap *peasycap; | 782 | static struct easycap *peasycap; |
791 | static struct usb_device *p; | 783 | static struct usb_device *p; |
@@ -1956,19 +1948,22 @@ default: { | |||
1956 | } | 1948 | } |
1957 | return 0; | 1949 | return 0; |
1958 | } | 1950 | } |
1959 | /****************************************************************************/ | 1951 | |
1960 | /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ | 1952 | long easycap_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
1961 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) | ||
1962 | long | ||
1963 | easysnd_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) | ||
1964 | { | 1953 | { |
1965 | return easysnd_ioctl((struct inode *)NULL, file, cmd, arg); | 1954 | struct inode *inode = file->f_dentry->d_inode; |
1955 | long ret; | ||
1956 | |||
1957 | lock_kernel(); | ||
1958 | ret = easycap_ioctl_bkl(inode, file, cmd, arg); | ||
1959 | unlock_kernel(); | ||
1960 | |||
1961 | return ret; | ||
1966 | } | 1962 | } |
1967 | #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ | 1963 | |
1968 | /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ | ||
1969 | /*--------------------------------------------------------------------------*/ | 1964 | /*--------------------------------------------------------------------------*/ |
1970 | int easysnd_ioctl(struct inode *inode, struct file *file, \ | 1965 | static int easysnd_ioctl_bkl(struct inode *inode, struct file *file, |
1971 | unsigned int cmd, unsigned long arg) | 1966 | unsigned int cmd, unsigned long arg) |
1972 | { | 1967 | { |
1973 | struct easycap *peasycap; | 1968 | struct easycap *peasycap; |
1974 | struct usb_device *p; | 1969 | struct usb_device *p; |
@@ -2158,6 +2153,19 @@ default: { | |||
2158 | } | 2153 | } |
2159 | return 0; | 2154 | return 0; |
2160 | } | 2155 | } |
2156 | |||
2157 | long easysnd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
2158 | { | ||
2159 | struct inode *inode = file->f_dentry->d_inode; | ||
2160 | long ret; | ||
2161 | |||
2162 | lock_kernel(); | ||
2163 | ret = easysnd_ioctl_bkl(inode, file, cmd, arg); | ||
2164 | unlock_kernel(); | ||
2165 | |||
2166 | return ret; | ||
2167 | } | ||
2168 | |||
2161 | /*****************************************************************************/ | 2169 | /*****************************************************************************/ |
2162 | int explain_ioctl(__u32 wot) | 2170 | int explain_ioctl(__u32 wot) |
2163 | { | 2171 | { |
diff --git a/drivers/staging/easycap/easycap_main.c b/drivers/staging/easycap/easycap_main.c index 09c194ce10a3..5a4bbd9b453f 100644 --- a/drivers/staging/easycap/easycap_main.c +++ b/drivers/staging/easycap/easycap_main.c | |||
@@ -60,13 +60,13 @@ struct usb_driver easycap_usb_driver = { | |||
60 | */ | 60 | */ |
61 | /*---------------------------------------------------------------------------*/ | 61 | /*---------------------------------------------------------------------------*/ |
62 | const struct file_operations easycap_fops = { | 62 | const struct file_operations easycap_fops = { |
63 | .owner = THIS_MODULE, | 63 | .owner = THIS_MODULE, |
64 | .open = easycap_open, | 64 | .open = easycap_open, |
65 | .release = easycap_release, | 65 | .release = easycap_release, |
66 | .ioctl = easycap_ioctl, | 66 | .unlocked_ioctl = easycap_ioctl, |
67 | .poll = easycap_poll, | 67 | .poll = easycap_poll, |
68 | .mmap = easycap_mmap, | 68 | .mmap = easycap_mmap, |
69 | .llseek = no_llseek, | 69 | .llseek = no_llseek, |
70 | }; | 70 | }; |
71 | struct vm_operations_struct easycap_vm_ops = { | 71 | struct vm_operations_struct easycap_vm_ops = { |
72 | .open = easycap_vma_open, | 72 | .open = easycap_vma_open, |
@@ -83,12 +83,12 @@ struct usb_class_driver easycap_class = { | |||
83 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) | 83 | #if defined(EASYCAP_IS_VIDEODEV_CLIENT) |
84 | #if defined(EASYCAP_NEEDS_V4L2_FOPS) | 84 | #if defined(EASYCAP_NEEDS_V4L2_FOPS) |
85 | const struct v4l2_file_operations v4l2_fops = { | 85 | const struct v4l2_file_operations v4l2_fops = { |
86 | .owner = THIS_MODULE, | 86 | .owner = THIS_MODULE, |
87 | .open = easycap_open_noinode, | 87 | .open = easycap_open_noinode, |
88 | .release = easycap_release_noinode, | 88 | .release = easycap_release_noinode, |
89 | .ioctl = easycap_ioctl_noinode, | 89 | .unlocked_ioctl = easycap_ioctl, |
90 | .poll = easycap_poll, | 90 | .poll = easycap_poll, |
91 | .mmap = easycap_mmap, | 91 | .mmap = easycap_mmap, |
92 | }; | 92 | }; |
93 | #endif /*EASYCAP_NEEDS_V4L2_FOPS*/ | 93 | #endif /*EASYCAP_NEEDS_V4L2_FOPS*/ |
94 | int video_device_many /*=0*/; | 94 | int video_device_many /*=0*/; |
@@ -102,12 +102,12 @@ struct video_device *pvideo_array[VIDEO_DEVICE_MANY], *pvideo_device; | |||
102 | */ | 102 | */ |
103 | /*--------------------------------------------------------------------------*/ | 103 | /*--------------------------------------------------------------------------*/ |
104 | const struct file_operations easysnd_fops = { | 104 | const struct file_operations easysnd_fops = { |
105 | .owner = THIS_MODULE, | 105 | .owner = THIS_MODULE, |
106 | .open = easysnd_open, | 106 | .open = easysnd_open, |
107 | .release = easysnd_release, | 107 | .release = easysnd_release, |
108 | .ioctl = easysnd_ioctl, | 108 | .unlocked_ioctl = easysnd_ioctl, |
109 | .read = easysnd_read, | 109 | .read = easysnd_read, |
110 | .llseek = no_llseek, | 110 | .llseek = no_llseek, |
111 | }; | 111 | }; |
112 | struct usb_class_driver easysnd_class = { | 112 | struct usb_class_driver easysnd_class = { |
113 | .name = "usb/easysnd%d", | 113 | .name = "usb/easysnd%d", |
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c index bc1c6051a6f6..97dae297ca3c 100644 --- a/drivers/staging/pohmelfs/inode.c +++ b/drivers/staging/pohmelfs/inode.c | |||
@@ -968,12 +968,18 @@ int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr) | |||
968 | goto err_out_exit; | 968 | goto err_out_exit; |
969 | } | 969 | } |
970 | 970 | ||
971 | err = inode_setattr(inode, attr); | 971 | if ((attr->ia_valid & ATTR_SIZE) && |
972 | if (err) { | 972 | attr->ia_size != i_size_read(inode)) { |
973 | dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); | 973 | err = vmtruncate(inode, attr->ia_size); |
974 | goto err_out_exit; | 974 | if (err) { |
975 | dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); | ||
976 | goto err_out_exit; | ||
977 | } | ||
975 | } | 978 | } |
976 | 979 | ||
980 | setattr_copy(inode, attr); | ||
981 | mark_inode_dirty(inode); | ||
982 | |||
977 | dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n", | 983 | dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n", |
978 | __func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode, | 984 | __func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode, |
979 | inode->i_uid, attr->ia_uid, inode->i_gid, attr->ia_gid, inode->i_size, attr->ia_size); | 985 | inode->i_uid, attr->ia_uid, inode->i_gid, attr->ia_gid, inode->i_size, attr->ia_size); |
@@ -1217,7 +1223,7 @@ void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info) | |||
1217 | } | 1223 | } |
1218 | } | 1224 | } |
1219 | 1225 | ||
1220 | static void pohmelfs_drop_inode(struct inode *inode) | 1226 | static int pohmelfs_drop_inode(struct inode *inode) |
1221 | { | 1227 | { |
1222 | struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); | 1228 | struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); |
1223 | struct pohmelfs_inode *pi = POHMELFS_I(inode); | 1229 | struct pohmelfs_inode *pi = POHMELFS_I(inode); |
@@ -1226,7 +1232,7 @@ static void pohmelfs_drop_inode(struct inode *inode) | |||
1226 | list_del_init(&pi->inode_entry); | 1232 | list_del_init(&pi->inode_entry); |
1227 | spin_unlock(&psb->ino_lock); | 1233 | spin_unlock(&psb->ino_lock); |
1228 | 1234 | ||
1229 | generic_drop_inode(inode); | 1235 | return generic_drop_inode(inode); |
1230 | } | 1236 | } |
1231 | 1237 | ||
1232 | static struct pohmelfs_inode *pohmelfs_get_inode_from_list(struct pohmelfs_sb *psb, | 1238 | static struct pohmelfs_inode *pohmelfs_get_inode_from_list(struct pohmelfs_sb *psb, |
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index be5d8db98165..0574d848b900 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c | |||
@@ -215,7 +215,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) | |||
215 | vhci = hcd_to_vhci(hcd); | 215 | vhci = hcd_to_vhci(hcd); |
216 | 216 | ||
217 | spin_lock_irqsave(&vhci->lock, flags); | 217 | spin_lock_irqsave(&vhci->lock, flags); |
218 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | 218 | if (!HCD_HW_ACCESSIBLE(hcd)) { |
219 | usbip_dbg_vhci_rh("hw accessible flag in on?\n"); | 219 | usbip_dbg_vhci_rh("hw accessible flag in on?\n"); |
220 | goto done; | 220 | goto done; |
221 | } | 221 | } |
@@ -269,7 +269,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
269 | 269 | ||
270 | u32 prev_port_status[VHCI_NPORTS]; | 270 | u32 prev_port_status[VHCI_NPORTS]; |
271 | 271 | ||
272 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) | 272 | if (!HCD_HW_ACCESSIBLE(hcd)) |
273 | return -ETIMEDOUT; | 273 | return -ETIMEDOUT; |
274 | 274 | ||
275 | /* | 275 | /* |
@@ -1041,7 +1041,7 @@ static int vhci_bus_resume(struct usb_hcd *hcd) | |||
1041 | dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); | 1041 | dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); |
1042 | 1042 | ||
1043 | spin_lock_irq(&vhci->lock); | 1043 | spin_lock_irq(&vhci->lock); |
1044 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | 1044 | if (!HCD_HW_ACCESSIBLE(hcd)) { |
1045 | rc = -ESHUTDOWN; | 1045 | rc = -ESHUTDOWN; |
1046 | } else { | 1046 | } else { |
1047 | /* vhci->rh_state = DUMMY_RH_RUNNING; | 1047 | /* vhci->rh_state = DUMMY_RH_RUNNING; |
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 80b4008c89ba..239f050efa35 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
@@ -41,7 +41,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/ | |||
41 | obj-$(CONFIG_USB_SERIAL) += serial/ | 41 | obj-$(CONFIG_USB_SERIAL) += serial/ |
42 | 42 | ||
43 | obj-$(CONFIG_USB) += misc/ | 43 | obj-$(CONFIG_USB) += misc/ |
44 | obj-y += early/ | 44 | obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/ |
45 | 45 | ||
46 | obj-$(CONFIG_USB_ATM) += atm/ | 46 | obj-$(CONFIG_USB_ATM) += atm/ |
47 | obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ | 47 | obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ |
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 101ffc965ee0..593fc5e2d2e6 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c | |||
@@ -564,7 +564,7 @@ static void cxacru_timeout_kill(unsigned long data) | |||
564 | } | 564 | } |
565 | 565 | ||
566 | static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, | 566 | static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, |
567 | int* actual_length) | 567 | int *actual_length) |
568 | { | 568 | { |
569 | struct timer_list timer; | 569 | struct timer_list timer; |
570 | 570 | ||
@@ -952,7 +952,7 @@ static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw, | |||
952 | put_unaligned(cpu_to_le32(addr), (__le32 *)(buf + offb)); | 952 | put_unaligned(cpu_to_le32(addr), (__le32 *)(buf + offb)); |
953 | offb += 4; | 953 | offb += 4; |
954 | addr += l; | 954 | addr += l; |
955 | if(l) | 955 | if (l) |
956 | memcpy(buf + offb, data + offd, l); | 956 | memcpy(buf + offb, data + offd, l); |
957 | if (l < stride) | 957 | if (l < stride) |
958 | memset(buf + offb + l, 0, stride - l); | 958 | memset(buf + offb + l, 0, stride - l); |
@@ -967,7 +967,7 @@ static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw, | |||
967 | } | 967 | } |
968 | offb = 0; | 968 | offb = 0; |
969 | } | 969 | } |
970 | } while(offd < size); | 970 | } while (offd < size); |
971 | dbg("sent fw %#x", fw); | 971 | dbg("sent fw %#x", fw); |
972 | 972 | ||
973 | ret = 0; | 973 | ret = 0; |
@@ -1043,8 +1043,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, | |||
1043 | if (instance->modem_type->boot_rom_patch) { | 1043 | if (instance->modem_type->boot_rom_patch) { |
1044 | val = cpu_to_le32(BR_ADDR); | 1044 | val = cpu_to_le32(BR_ADDR); |
1045 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4); | 1045 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4); |
1046 | } | 1046 | } else { |
1047 | else { | ||
1048 | ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0); | 1047 | ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0); |
1049 | } | 1048 | } |
1050 | if (ret) { | 1049 | if (ret) { |
@@ -1068,7 +1067,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, | |||
1068 | } | 1067 | } |
1069 | 1068 | ||
1070 | static int cxacru_find_firmware(struct cxacru_data *instance, | 1069 | static int cxacru_find_firmware(struct cxacru_data *instance, |
1071 | char* phase, const struct firmware **fw_p) | 1070 | char *phase, const struct firmware **fw_p) |
1072 | { | 1071 | { |
1073 | struct usbatm_data *usbatm = instance->usbatm; | 1072 | struct usbatm_data *usbatm = instance->usbatm; |
1074 | struct device *dev = &usbatm->usb_intf->dev; | 1073 | struct device *dev = &usbatm->usb_intf->dev; |
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 80f9617d3a15..4716e707de59 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c | |||
@@ -753,11 +753,13 @@ static struct usb_driver speedtch_usb_driver = { | |||
753 | .id_table = speedtch_usb_ids | 753 | .id_table = speedtch_usb_ids |
754 | }; | 754 | }; |
755 | 755 | ||
756 | static void speedtch_release_interfaces(struct usb_device *usb_dev, int num_interfaces) { | 756 | static void speedtch_release_interfaces(struct usb_device *usb_dev, |
757 | int num_interfaces) | ||
758 | { | ||
757 | struct usb_interface *cur_intf; | 759 | struct usb_interface *cur_intf; |
758 | int i; | 760 | int i; |
759 | 761 | ||
760 | for(i = 0; i < num_interfaces; i++) | 762 | for (i = 0; i < num_interfaces; i++) |
761 | if ((cur_intf = usb_ifnum_to_if(usb_dev, i))) { | 763 | if ((cur_intf = usb_ifnum_to_if(usb_dev, i))) { |
762 | usb_set_intfdata(cur_intf, NULL); | 764 | usb_set_intfdata(cur_intf, NULL); |
763 | usb_driver_release_interface(&speedtch_usb_driver, cur_intf); | 765 | usb_driver_release_interface(&speedtch_usb_driver, cur_intf); |
@@ -792,7 +794,7 @@ static int speedtch_bind(struct usbatm_data *usbatm, | |||
792 | 794 | ||
793 | /* claim all interfaces */ | 795 | /* claim all interfaces */ |
794 | 796 | ||
795 | for (i=0; i < num_interfaces; i++) { | 797 | for (i = 0; i < num_interfaces; i++) { |
796 | cur_intf = usb_ifnum_to_if(usb_dev, i); | 798 | cur_intf = usb_ifnum_to_if(usb_dev, i); |
797 | 799 | ||
798 | if ((i != ifnum) && cur_intf) { | 800 | if ((i != ifnum) && cur_intf) { |
@@ -842,7 +844,7 @@ static int speedtch_bind(struct usbatm_data *usbatm, | |||
842 | 844 | ||
843 | use_isoc = 0; /* fall back to bulk if endpoint not found */ | 845 | use_isoc = 0; /* fall back to bulk if endpoint not found */ |
844 | 846 | ||
845 | for (i=0; i<desc->desc.bNumEndpoints; i++) { | 847 | for (i = 0; i < desc->desc.bNumEndpoints; i++) { |
846 | const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc; | 848 | const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc; |
847 | 849 | ||
848 | if ((endpoint_desc->bEndpointAddress == target_address)) { | 850 | if ((endpoint_desc->bEndpointAddress == target_address)) { |
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index ebae94480140..5b3f555e01c9 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c | |||
@@ -67,6 +67,7 @@ | |||
67 | #include <linux/mutex.h> | 67 | #include <linux/mutex.h> |
68 | #include <linux/freezer.h> | 68 | #include <linux/freezer.h> |
69 | #include <linux/slab.h> | 69 | #include <linux/slab.h> |
70 | #include <linux/kernel.h> | ||
70 | 71 | ||
71 | #include <asm/unaligned.h> | 72 | #include <asm/unaligned.h> |
72 | 73 | ||
@@ -2436,7 +2437,6 @@ UEA_ATTR(firmid, 0); | |||
2436 | 2437 | ||
2437 | /* Retrieve the device End System Identifier (MAC) */ | 2438 | /* Retrieve the device End System Identifier (MAC) */ |
2438 | 2439 | ||
2439 | #define htoi(x) (isdigit(x) ? x-'0' : toupper(x)-'A'+10) | ||
2440 | static int uea_getesi(struct uea_softc *sc, u_char * esi) | 2440 | static int uea_getesi(struct uea_softc *sc, u_char * esi) |
2441 | { | 2441 | { |
2442 | unsigned char mac_str[2 * ETH_ALEN + 1]; | 2442 | unsigned char mac_str[2 * ETH_ALEN + 1]; |
@@ -2447,7 +2447,8 @@ static int uea_getesi(struct uea_softc *sc, u_char * esi) | |||
2447 | return 1; | 2447 | return 1; |
2448 | 2448 | ||
2449 | for (i = 0; i < ETH_ALEN; i++) | 2449 | for (i = 0; i < ETH_ALEN; i++) |
2450 | esi[i] = htoi(mac_str[2 * i]) * 16 + htoi(mac_str[2 * i + 1]); | 2450 | esi[i] = hex_to_bin(mac_str[2 * i]) * 16 + |
2451 | hex_to_bin(mac_str[2 * i + 1]); | ||
2451 | 2452 | ||
2452 | return 0; | 2453 | return 0; |
2453 | } | 2454 | } |
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 9b53e8df4648..05bf5a27b5b0 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c | |||
@@ -84,8 +84,8 @@ | |||
84 | 84 | ||
85 | #ifdef VERBOSE_DEBUG | 85 | #ifdef VERBOSE_DEBUG |
86 | static int usbatm_print_packet(const unsigned char *data, int len); | 86 | static int usbatm_print_packet(const unsigned char *data, int len); |
87 | #define PACKETDEBUG(arg...) usbatm_print_packet (arg) | 87 | #define PACKETDEBUG(arg...) usbatm_print_packet(arg) |
88 | #define vdbg(arg...) dbg (arg) | 88 | #define vdbg(arg...) dbg(arg) |
89 | #else | 89 | #else |
90 | #define PACKETDEBUG(arg...) | 90 | #define PACKETDEBUG(arg...) |
91 | #define vdbg(arg...) | 91 | #define vdbg(arg...) |
@@ -273,8 +273,7 @@ static void usbatm_complete(struct urb *urb) | |||
273 | 273 | ||
274 | if (unlikely(status) && | 274 | if (unlikely(status) && |
275 | (!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) || | 275 | (!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) || |
276 | status != -EILSEQ )) | 276 | status != -EILSEQ)) { |
277 | { | ||
278 | if (status == -ESHUTDOWN) | 277 | if (status == -ESHUTDOWN) |
279 | return; | 278 | return; |
280 | 279 | ||
@@ -494,7 +493,7 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, | |||
494 | ptr += data_len; | 493 | ptr += data_len; |
495 | __skb_pull(skb, data_len); | 494 | __skb_pull(skb, data_len); |
496 | 495 | ||
497 | if(!left) | 496 | if (!left) |
498 | continue; | 497 | continue; |
499 | 498 | ||
500 | memset(ptr, 0, left); | 499 | memset(ptr, 0, left); |
@@ -506,7 +505,7 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, | |||
506 | trailer[2] = ctrl->len >> 8; | 505 | trailer[2] = ctrl->len >> 8; |
507 | trailer[3] = ctrl->len; | 506 | trailer[3] = ctrl->len; |
508 | 507 | ||
509 | ctrl->crc = ~ crc32_be(ctrl->crc, ptr, left - 4); | 508 | ctrl->crc = ~crc32_be(ctrl->crc, ptr, left - 4); |
510 | 509 | ||
511 | trailer[4] = ctrl->crc >> 24; | 510 | trailer[4] = ctrl->crc >> 24; |
512 | trailer[5] = ctrl->crc >> 16; | 511 | trailer[5] = ctrl->crc >> 16; |
@@ -516,8 +515,7 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, | |||
516 | target[3] |= 0x2; /* adjust PTI */ | 515 | target[3] |= 0x2; /* adjust PTI */ |
517 | 516 | ||
518 | ctrl->len = 0; /* tag this skb finished */ | 517 | ctrl->len = 0; /* tag this skb finished */ |
519 | } | 518 | } else |
520 | else | ||
521 | ctrl->crc = crc32_be(ctrl->crc, ptr, left); | 519 | ctrl->crc = crc32_be(ctrl->crc, ptr, left); |
522 | } | 520 | } |
523 | 521 | ||
@@ -1146,7 +1144,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, | |||
1146 | instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->bulk_out); | 1144 | instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->bulk_out); |
1147 | 1145 | ||
1148 | /* tx buffer size must be a positive multiple of the stride */ | 1146 | /* tx buffer size must be a positive multiple of the stride */ |
1149 | instance->tx_channel.buf_size = max (instance->tx_channel.stride, | 1147 | instance->tx_channel.buf_size = max(instance->tx_channel.stride, |
1150 | snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride)); | 1148 | snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride)); |
1151 | 1149 | ||
1152 | /* rx buffer size must be a positive multiple of the endpoint maxpacket */ | 1150 | /* rx buffer size must be a positive multiple of the endpoint maxpacket */ |
@@ -1159,7 +1157,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, | |||
1159 | goto fail_unbind; | 1157 | goto fail_unbind; |
1160 | } | 1158 | } |
1161 | 1159 | ||
1162 | num_packets = max (1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */ | 1160 | num_packets = max(1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */ |
1163 | 1161 | ||
1164 | if (num_packets * maxpacket > UDSL_MAX_BUF_SIZE) | 1162 | if (num_packets * maxpacket > UDSL_MAX_BUF_SIZE) |
1165 | num_packets--; | 1163 | num_packets--; |
@@ -1262,7 +1260,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, | |||
1262 | usb_free_urb(instance->urbs[i]); | 1260 | usb_free_urb(instance->urbs[i]); |
1263 | } | 1261 | } |
1264 | 1262 | ||
1265 | kfree (instance); | 1263 | kfree(instance); |
1266 | 1264 | ||
1267 | return error; | 1265 | return error; |
1268 | } | 1266 | } |
@@ -1390,9 +1388,8 @@ static int usbatm_print_packet(const unsigned char *data, int len) | |||
1390 | for (i = 0; i < len;) { | 1388 | for (i = 0; i < len;) { |
1391 | buffer[0] = '\0'; | 1389 | buffer[0] = '\0'; |
1392 | sprintf(buffer, "%.3d :", i); | 1390 | sprintf(buffer, "%.3d :", i); |
1393 | for (j = 0; (j < 16) && (i < len); j++, i++) { | 1391 | for (j = 0; (j < 16) && (i < len); j++, i++) |
1394 | sprintf(buffer, "%s %2.2x", buffer, data[i]); | 1392 | sprintf(buffer, "%s %2.2x", buffer, data[i]); |
1395 | } | ||
1396 | dbg("%s", buffer); | 1393 | dbg("%s", buffer); |
1397 | } | 1394 | } |
1398 | return i; | 1395 | return i; |
diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h index 0863f85fcc26..5fc489405217 100644 --- a/drivers/usb/atm/usbatm.h +++ b/drivers/usb/atm/usbatm.h | |||
@@ -48,7 +48,7 @@ | |||
48 | dev_warn(&(instance)->usb_intf->dev, \ | 48 | dev_warn(&(instance)->usb_intf->dev, \ |
49 | "failed assertion '%s' at line %d", \ | 49 | "failed assertion '%s' at line %d", \ |
50 | __stringify(x), __LINE__); \ | 50 | __stringify(x), __LINE__); \ |
51 | } while(0) | 51 | } while (0) |
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | #define usb_err(instance, format, arg...) \ | 54 | #define usb_err(instance, format, arg...) \ |
@@ -59,7 +59,7 @@ | |||
59 | dev_warn(&(instance)->usb_intf->dev , format , ## arg) | 59 | dev_warn(&(instance)->usb_intf->dev , format , ## arg) |
60 | #ifdef DEBUG | 60 | #ifdef DEBUG |
61 | #define usb_dbg(instance, format, arg...) \ | 61 | #define usb_dbg(instance, format, arg...) \ |
62 | dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg) | 62 | dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg) |
63 | #else | 63 | #else |
64 | #define usb_dbg(instance, format, arg...) \ | 64 | #define usb_dbg(instance, format, arg...) \ |
65 | do {} while (0) | 65 | do {} while (0) |
@@ -104,21 +104,21 @@ struct usbatm_data; | |||
104 | /* | 104 | /* |
105 | * Assuming all methods exist and succeed, they are called in this order: | 105 | * Assuming all methods exist and succeed, they are called in this order: |
106 | * | 106 | * |
107 | * bind, heavy_init, atm_start, ..., atm_stop, unbind | 107 | * bind, heavy_init, atm_start, ..., atm_stop, unbind |
108 | */ | 108 | */ |
109 | 109 | ||
110 | struct usbatm_driver { | 110 | struct usbatm_driver { |
111 | const char *driver_name; | 111 | const char *driver_name; |
112 | 112 | ||
113 | /* init device ... can sleep, or cause probe() failure */ | 113 | /* init device ... can sleep, or cause probe() failure */ |
114 | int (*bind) (struct usbatm_data *, struct usb_interface *, | 114 | int (*bind) (struct usbatm_data *, struct usb_interface *, |
115 | const struct usb_device_id *id); | 115 | const struct usb_device_id *id); |
116 | 116 | ||
117 | /* additional device initialization that is too slow to be done in probe() */ | 117 | /* additional device initialization that is too slow to be done in probe() */ |
118 | int (*heavy_init) (struct usbatm_data *, struct usb_interface *); | 118 | int (*heavy_init) (struct usbatm_data *, struct usb_interface *); |
119 | 119 | ||
120 | /* cleanup device ... can sleep, but can't fail */ | 120 | /* cleanup device ... can sleep, but can't fail */ |
121 | void (*unbind) (struct usbatm_data *, struct usb_interface *); | 121 | void (*unbind) (struct usbatm_data *, struct usb_interface *); |
122 | 122 | ||
123 | /* init ATM device ... can sleep, or cause ATM initialization failure */ | 123 | /* init ATM device ... can sleep, or cause ATM initialization failure */ |
124 | int (*atm_start) (struct usbatm_data *, struct atm_dev *); | 124 | int (*atm_start) (struct usbatm_data *, struct atm_dev *); |
@@ -126,9 +126,9 @@ struct usbatm_driver { | |||
126 | /* cleanup ATM device ... can sleep, but can't fail */ | 126 | /* cleanup ATM device ... can sleep, but can't fail */ |
127 | void (*atm_stop) (struct usbatm_data *, struct atm_dev *); | 127 | void (*atm_stop) (struct usbatm_data *, struct atm_dev *); |
128 | 128 | ||
129 | int bulk_in; /* bulk rx endpoint */ | 129 | int bulk_in; /* bulk rx endpoint */ |
130 | int isoc_in; /* isochronous rx endpoint */ | 130 | int isoc_in; /* isochronous rx endpoint */ |
131 | int bulk_out; /* bulk tx endpoint */ | 131 | int bulk_out; /* bulk tx endpoint */ |
132 | 132 | ||
133 | unsigned rx_padding; | 133 | unsigned rx_padding; |
134 | unsigned tx_padding; | 134 | unsigned tx_padding; |
@@ -156,7 +156,7 @@ struct usbatm_channel { | |||
156 | struct usbatm_data { | 156 | struct usbatm_data { |
157 | /****************** | 157 | /****************** |
158 | * public fields * | 158 | * public fields * |
159 | ******************/ | 159 | ******************/ |
160 | 160 | ||
161 | /* mini driver */ | 161 | /* mini driver */ |
162 | struct usbatm_driver *driver; | 162 | struct usbatm_driver *driver; |
@@ -174,7 +174,7 @@ struct usbatm_data { | |||
174 | 174 | ||
175 | /******************************** | 175 | /******************************** |
176 | * private fields - do not use * | 176 | * private fields - do not use * |
177 | ********************************/ | 177 | ********************************/ |
178 | 178 | ||
179 | struct kref refcount; | 179 | struct kref refcount; |
180 | struct mutex serialize; | 180 | struct mutex serialize; |
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c index 17d167bbd2dc..48ee0c5ff282 100644 --- a/drivers/usb/atm/xusbatm.c +++ b/drivers/usb/atm/xusbatm.c | |||
@@ -49,13 +49,13 @@ static struct usbatm_driver xusbatm_drivers[XUSBATM_DRIVERS_MAX]; | |||
49 | static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1]; | 49 | static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1]; |
50 | static struct usb_driver xusbatm_usb_driver; | 50 | static struct usb_driver xusbatm_usb_driver; |
51 | 51 | ||
52 | static struct usb_interface *xusbatm_find_intf (struct usb_device *usb_dev, int altsetting, u8 ep) | 52 | static struct usb_interface *xusbatm_find_intf(struct usb_device *usb_dev, int altsetting, u8 ep) |
53 | { | 53 | { |
54 | struct usb_host_interface *alt; | 54 | struct usb_host_interface *alt; |
55 | struct usb_interface *intf; | 55 | struct usb_interface *intf; |
56 | int i, j; | 56 | int i, j; |
57 | 57 | ||
58 | for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) | 58 | for (i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) |
59 | if ((intf = usb_dev->actconfig->interface[i]) && (alt = usb_altnum_to_altsetting(intf, altsetting))) | 59 | if ((intf = usb_dev->actconfig->interface[i]) && (alt = usb_altnum_to_altsetting(intf, altsetting))) |
60 | for (j = 0; j < alt->desc.bNumEndpoints; j++) | 60 | for (j = 0; j < alt->desc.bNumEndpoints; j++) |
61 | if (alt->endpoint[j].desc.bEndpointAddress == ep) | 61 | if (alt->endpoint[j].desc.bEndpointAddress == ep) |
@@ -63,7 +63,7 @@ static struct usb_interface *xusbatm_find_intf (struct usb_device *usb_dev, int | |||
63 | return NULL; | 63 | return NULL; |
64 | } | 64 | } |
65 | 65 | ||
66 | static int xusbatm_capture_intf (struct usbatm_data *usbatm, struct usb_device *usb_dev, | 66 | static int xusbatm_capture_intf(struct usbatm_data *usbatm, struct usb_device *usb_dev, |
67 | struct usb_interface *intf, int altsetting, int claim) | 67 | struct usb_interface *intf, int altsetting, int claim) |
68 | { | 68 | { |
69 | int ifnum = intf->altsetting->desc.bInterfaceNumber; | 69 | int ifnum = intf->altsetting->desc.bInterfaceNumber; |
@@ -80,7 +80,7 @@ static int xusbatm_capture_intf (struct usbatm_data *usbatm, struct usb_device * | |||
80 | return 0; | 80 | return 0; |
81 | } | 81 | } |
82 | 82 | ||
83 | static void xusbatm_release_intf (struct usb_device *usb_dev, struct usb_interface *intf, int claimed) | 83 | static void xusbatm_release_intf(struct usb_device *usb_dev, struct usb_interface *intf, int claimed) |
84 | { | 84 | { |
85 | if (claimed) { | 85 | if (claimed) { |
86 | usb_set_intfdata(intf, NULL); | 86 | usb_set_intfdata(intf, NULL); |
@@ -147,7 +147,7 @@ static void xusbatm_unbind(struct usbatm_data *usbatm, | |||
147 | 147 | ||
148 | usb_dbg(usbatm, "%s entered\n", __func__); | 148 | usb_dbg(usbatm, "%s entered\n", __func__); |
149 | 149 | ||
150 | for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) { | 150 | for (i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) { |
151 | struct usb_interface *cur_intf = usb_dev->actconfig->interface[i]; | 151 | struct usb_interface *cur_intf = usb_dev->actconfig->interface[i]; |
152 | 152 | ||
153 | if (cur_intf && (usb_get_intfdata(cur_intf) == usbatm)) { | 153 | if (cur_intf && (usb_get_intfdata(cur_intf) == usbatm)) { |
diff --git a/drivers/usb/c67x00/c67x00-hcd.c b/drivers/usb/c67x00/c67x00-hcd.c index a22b887f4e9e..d3e1356d091e 100644 --- a/drivers/usb/c67x00/c67x00-hcd.c +++ b/drivers/usb/c67x00/c67x00-hcd.c | |||
@@ -264,7 +264,7 @@ static void c67x00_hcd_irq(struct c67x00_sie *sie, u16 int_status, u16 msg) | |||
264 | if (unlikely(hcd->state == HC_STATE_HALT)) | 264 | if (unlikely(hcd->state == HC_STATE_HALT)) |
265 | return; | 265 | return; |
266 | 266 | ||
267 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) | 267 | if (!HCD_HW_ACCESSIBLE(hcd)) |
268 | return; | 268 | return; |
269 | 269 | ||
270 | /* Handle Start of frame events */ | 270 | /* Handle Start of frame events */ |
@@ -282,7 +282,7 @@ static int c67x00_hcd_start(struct usb_hcd *hcd) | |||
282 | { | 282 | { |
283 | hcd->uses_new_polling = 1; | 283 | hcd->uses_new_polling = 1; |
284 | hcd->state = HC_STATE_RUNNING; | 284 | hcd->state = HC_STATE_RUNNING; |
285 | hcd->poll_rh = 1; | 285 | set_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
286 | 286 | ||
287 | return 0; | 287 | return 0; |
288 | } | 288 | } |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 89d260d6b031..1833b3a71515 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -636,19 +636,13 @@ static void acm_tty_unregister(struct acm *acm) | |||
636 | 636 | ||
637 | static int acm_tty_chars_in_buffer(struct tty_struct *tty); | 637 | static int acm_tty_chars_in_buffer(struct tty_struct *tty); |
638 | 638 | ||
639 | static void acm_port_down(struct acm *acm, int drain) | 639 | static void acm_port_down(struct acm *acm) |
640 | { | 640 | { |
641 | int i, nr = acm->rx_buflimit; | 641 | int i, nr = acm->rx_buflimit; |
642 | mutex_lock(&open_mutex); | 642 | mutex_lock(&open_mutex); |
643 | if (acm->dev) { | 643 | if (acm->dev) { |
644 | usb_autopm_get_interface(acm->control); | 644 | usb_autopm_get_interface(acm->control); |
645 | acm_set_control(acm, acm->ctrlout = 0); | 645 | acm_set_control(acm, acm->ctrlout = 0); |
646 | /* try letting the last writes drain naturally */ | ||
647 | if (drain) { | ||
648 | wait_event_interruptible_timeout(acm->drain_wait, | ||
649 | (ACM_NW == acm_wb_is_avail(acm)) || !acm->dev, | ||
650 | ACM_CLOSE_TIMEOUT * HZ); | ||
651 | } | ||
652 | usb_kill_urb(acm->ctrlurb); | 646 | usb_kill_urb(acm->ctrlurb); |
653 | for (i = 0; i < ACM_NW; i++) | 647 | for (i = 0; i < ACM_NW; i++) |
654 | usb_kill_urb(acm->wb[i].urb); | 648 | usb_kill_urb(acm->wb[i].urb); |
@@ -664,7 +658,7 @@ static void acm_tty_hangup(struct tty_struct *tty) | |||
664 | { | 658 | { |
665 | struct acm *acm = tty->driver_data; | 659 | struct acm *acm = tty->driver_data; |
666 | tty_port_hangup(&acm->port); | 660 | tty_port_hangup(&acm->port); |
667 | acm_port_down(acm, 0); | 661 | acm_port_down(acm); |
668 | } | 662 | } |
669 | 663 | ||
670 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) | 664 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) |
@@ -685,7 +679,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) | |||
685 | mutex_unlock(&open_mutex); | 679 | mutex_unlock(&open_mutex); |
686 | return; | 680 | return; |
687 | } | 681 | } |
688 | acm_port_down(acm, 0); | 682 | acm_port_down(acm); |
689 | tty_port_close_end(&acm->port, tty); | 683 | tty_port_close_end(&acm->port, tty); |
690 | tty_port_tty_set(&acm->port, NULL); | 684 | tty_port_tty_set(&acm->port, NULL); |
691 | } | 685 | } |
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 84f9e52327f2..e325162859b0 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
@@ -135,7 +135,7 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H | |||
135 | * ->lock locks what interrupt accesses. | 135 | * ->lock locks what interrupt accesses. |
136 | */ | 136 | */ |
137 | struct usblp { | 137 | struct usblp { |
138 | struct usb_device *dev; /* USB device */ | 138 | struct usb_device *dev; /* USB device */ |
139 | struct mutex wmut; | 139 | struct mutex wmut; |
140 | struct mutex mut; | 140 | struct mutex mut; |
141 | spinlock_t lock; /* locks rcomplete, wcomplete */ | 141 | spinlock_t lock; /* locks rcomplete, wcomplete */ |
@@ -169,7 +169,8 @@ struct usblp { | |||
169 | }; | 169 | }; |
170 | 170 | ||
171 | #ifdef DEBUG | 171 | #ifdef DEBUG |
172 | static void usblp_dump(struct usblp *usblp) { | 172 | static void usblp_dump(struct usblp *usblp) |
173 | { | ||
173 | int p; | 174 | int p; |
174 | 175 | ||
175 | dbg("usblp=0x%p", usblp); | 176 | dbg("usblp=0x%p", usblp); |
@@ -216,8 +217,8 @@ static const struct quirk_printer_struct quirk_printers[] = { | |||
216 | { 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */ | 217 | { 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */ |
217 | { 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */ | 218 | { 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */ |
218 | { 0x03f0, 0x0504, USBLP_QUIRK_BIDIR }, /* HP DeskJet 885C */ | 219 | { 0x03f0, 0x0504, USBLP_QUIRK_BIDIR }, /* HP DeskJet 885C */ |
219 | { 0x03f0, 0x0604, USBLP_QUIRK_BIDIR }, /* HP DeskJet 840C */ | 220 | { 0x03f0, 0x0604, USBLP_QUIRK_BIDIR }, /* HP DeskJet 840C */ |
220 | { 0x03f0, 0x0804, USBLP_QUIRK_BIDIR }, /* HP DeskJet 816C */ | 221 | { 0x03f0, 0x0804, USBLP_QUIRK_BIDIR }, /* HP DeskJet 816C */ |
221 | { 0x03f0, 0x1104, USBLP_QUIRK_BIDIR }, /* HP Deskjet 959C */ | 222 | { 0x03f0, 0x1104, USBLP_QUIRK_BIDIR }, /* HP Deskjet 959C */ |
222 | { 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */ | 223 | { 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */ |
223 | { 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */ | 224 | { 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */ |
@@ -254,9 +255,8 @@ static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, i | |||
254 | /* High byte has the interface index. | 255 | /* High byte has the interface index. |
255 | Low byte has the alternate setting. | 256 | Low byte has the alternate setting. |
256 | */ | 257 | */ |
257 | if ((request == USBLP_REQ_GET_ID) && (type == USB_TYPE_CLASS)) { | 258 | if ((request == USBLP_REQ_GET_ID) && (type == USB_TYPE_CLASS)) |
258 | index = (usblp->ifnum<<8)|usblp->protocol[usblp->current_protocol].alt_setting; | 259 | index = (usblp->ifnum<<8)|usblp->protocol[usblp->current_protocol].alt_setting; |
259 | } | ||
260 | 260 | ||
261 | retval = usb_control_msg(usblp->dev, | 261 | retval = usb_control_msg(usblp->dev, |
262 | dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0), | 262 | dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0), |
@@ -372,7 +372,7 @@ static int usblp_check_status(struct usblp *usblp, int err) | |||
372 | return newerr; | 372 | return newerr; |
373 | } | 373 | } |
374 | 374 | ||
375 | static int handle_bidir (struct usblp *usblp) | 375 | static int handle_bidir(struct usblp *usblp) |
376 | { | 376 | { |
377 | if (usblp->bidir && usblp->used) { | 377 | if (usblp->bidir && usblp->used) { |
378 | if (usblp_submit_read(usblp) < 0) | 378 | if (usblp_submit_read(usblp) < 0) |
@@ -395,14 +395,13 @@ static int usblp_open(struct inode *inode, struct file *file) | |||
395 | if (minor < 0) | 395 | if (minor < 0) |
396 | return -ENODEV; | 396 | return -ENODEV; |
397 | 397 | ||
398 | mutex_lock (&usblp_mutex); | 398 | mutex_lock(&usblp_mutex); |
399 | 399 | ||
400 | retval = -ENODEV; | 400 | retval = -ENODEV; |
401 | intf = usb_find_interface(&usblp_driver, minor); | 401 | intf = usb_find_interface(&usblp_driver, minor); |
402 | if (!intf) { | 402 | if (!intf) |
403 | goto out; | 403 | goto out; |
404 | } | 404 | usblp = usb_get_intfdata(intf); |
405 | usblp = usb_get_intfdata (intf); | ||
406 | if (!usblp || !usblp->dev || !usblp->present) | 405 | if (!usblp || !usblp->dev || !usblp->present) |
407 | goto out; | 406 | goto out; |
408 | 407 | ||
@@ -433,18 +432,18 @@ static int usblp_open(struct inode *inode, struct file *file) | |||
433 | retval = -EIO; | 432 | retval = -EIO; |
434 | } | 433 | } |
435 | out: | 434 | out: |
436 | mutex_unlock (&usblp_mutex); | 435 | mutex_unlock(&usblp_mutex); |
437 | return retval; | 436 | return retval; |
438 | } | 437 | } |
439 | 438 | ||
440 | static void usblp_cleanup (struct usblp *usblp) | 439 | static void usblp_cleanup(struct usblp *usblp) |
441 | { | 440 | { |
442 | printk(KERN_INFO "usblp%d: removed\n", usblp->minor); | 441 | printk(KERN_INFO "usblp%d: removed\n", usblp->minor); |
443 | 442 | ||
444 | kfree(usblp->readbuf); | 443 | kfree(usblp->readbuf); |
445 | kfree (usblp->device_id_string); | 444 | kfree(usblp->device_id_string); |
446 | kfree (usblp->statusbuf); | 445 | kfree(usblp->statusbuf); |
447 | kfree (usblp); | 446 | kfree(usblp); |
448 | } | 447 | } |
449 | 448 | ||
450 | static void usblp_unlink_urbs(struct usblp *usblp) | 449 | static void usblp_unlink_urbs(struct usblp *usblp) |
@@ -458,14 +457,14 @@ static int usblp_release(struct inode *inode, struct file *file) | |||
458 | 457 | ||
459 | usblp->flags &= ~LP_ABORT; | 458 | usblp->flags &= ~LP_ABORT; |
460 | 459 | ||
461 | mutex_lock (&usblp_mutex); | 460 | mutex_lock(&usblp_mutex); |
462 | usblp->used = 0; | 461 | usblp->used = 0; |
463 | if (usblp->present) { | 462 | if (usblp->present) { |
464 | usblp_unlink_urbs(usblp); | 463 | usblp_unlink_urbs(usblp); |
465 | usb_autopm_put_interface(usblp->intf); | 464 | usb_autopm_put_interface(usblp->intf); |
466 | } else /* finish cleanup from disconnect */ | 465 | } else /* finish cleanup from disconnect */ |
467 | usblp_cleanup (usblp); | 466 | usblp_cleanup(usblp); |
468 | mutex_unlock (&usblp_mutex); | 467 | mutex_unlock(&usblp_mutex); |
469 | return 0; | 468 | return 0; |
470 | } | 469 | } |
471 | 470 | ||
@@ -495,190 +494,190 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
495 | int twoints[2]; | 494 | int twoints[2]; |
496 | int retval = 0; | 495 | int retval = 0; |
497 | 496 | ||
498 | mutex_lock (&usblp->mut); | 497 | mutex_lock(&usblp->mut); |
499 | if (!usblp->present) { | 498 | if (!usblp->present) { |
500 | retval = -ENODEV; | 499 | retval = -ENODEV; |
501 | goto done; | 500 | goto done; |
502 | } | 501 | } |
503 | 502 | ||
504 | dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd), | 503 | dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd), |
505 | _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) ); | 504 | _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd)); |
506 | 505 | ||
507 | if (_IOC_TYPE(cmd) == 'P') /* new-style ioctl number */ | 506 | if (_IOC_TYPE(cmd) == 'P') /* new-style ioctl number */ |
508 | 507 | ||
509 | switch (_IOC_NR(cmd)) { | 508 | switch (_IOC_NR(cmd)) { |
510 | 509 | ||
511 | case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */ | 510 | case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */ |
512 | if (_IOC_DIR(cmd) != _IOC_READ) { | 511 | if (_IOC_DIR(cmd) != _IOC_READ) { |
513 | retval = -EINVAL; | 512 | retval = -EINVAL; |
514 | goto done; | 513 | goto done; |
515 | } | 514 | } |
516 | 515 | ||
517 | length = usblp_cache_device_id_string(usblp); | 516 | length = usblp_cache_device_id_string(usblp); |
518 | if (length < 0) { | 517 | if (length < 0) { |
519 | retval = length; | 518 | retval = length; |
520 | goto done; | 519 | goto done; |
521 | } | 520 | } |
522 | if (length > _IOC_SIZE(cmd)) | 521 | if (length > _IOC_SIZE(cmd)) |
523 | length = _IOC_SIZE(cmd); /* truncate */ | 522 | length = _IOC_SIZE(cmd); /* truncate */ |
524 | 523 | ||
525 | if (copy_to_user((void __user *) arg, | 524 | if (copy_to_user((void __user *) arg, |
526 | usblp->device_id_string, | 525 | usblp->device_id_string, |
527 | (unsigned long) length)) { | 526 | (unsigned long) length)) { |
528 | retval = -EFAULT; | 527 | retval = -EFAULT; |
529 | goto done; | 528 | goto done; |
530 | } | 529 | } |
531 | 530 | ||
532 | break; | 531 | break; |
533 | 532 | ||
534 | case IOCNR_GET_PROTOCOLS: | 533 | case IOCNR_GET_PROTOCOLS: |
535 | if (_IOC_DIR(cmd) != _IOC_READ || | 534 | if (_IOC_DIR(cmd) != _IOC_READ || |
536 | _IOC_SIZE(cmd) < sizeof(twoints)) { | 535 | _IOC_SIZE(cmd) < sizeof(twoints)) { |
537 | retval = -EINVAL; | 536 | retval = -EINVAL; |
538 | goto done; | 537 | goto done; |
539 | } | 538 | } |
540 | 539 | ||
541 | twoints[0] = usblp->current_protocol; | 540 | twoints[0] = usblp->current_protocol; |
542 | twoints[1] = 0; | 541 | twoints[1] = 0; |
543 | for (i = USBLP_FIRST_PROTOCOL; | 542 | for (i = USBLP_FIRST_PROTOCOL; |
544 | i <= USBLP_LAST_PROTOCOL; i++) { | 543 | i <= USBLP_LAST_PROTOCOL; i++) { |
545 | if (usblp->protocol[i].alt_setting >= 0) | 544 | if (usblp->protocol[i].alt_setting >= 0) |
546 | twoints[1] |= (1<<i); | 545 | twoints[1] |= (1<<i); |
547 | } | 546 | } |
548 | 547 | ||
549 | if (copy_to_user((void __user *)arg, | 548 | if (copy_to_user((void __user *)arg, |
550 | (unsigned char *)twoints, | 549 | (unsigned char *)twoints, |
551 | sizeof(twoints))) { | 550 | sizeof(twoints))) { |
552 | retval = -EFAULT; | 551 | retval = -EFAULT; |
553 | goto done; | 552 | goto done; |
554 | } | 553 | } |
555 | 554 | ||
556 | break; | 555 | break; |
557 | 556 | ||
558 | case IOCNR_SET_PROTOCOL: | 557 | case IOCNR_SET_PROTOCOL: |
559 | if (_IOC_DIR(cmd) != _IOC_WRITE) { | 558 | if (_IOC_DIR(cmd) != _IOC_WRITE) { |
560 | retval = -EINVAL; | 559 | retval = -EINVAL; |
561 | goto done; | 560 | goto done; |
562 | } | 561 | } |
563 | 562 | ||
564 | #ifdef DEBUG | 563 | #ifdef DEBUG |
565 | if (arg == -10) { | 564 | if (arg == -10) { |
566 | usblp_dump(usblp); | 565 | usblp_dump(usblp); |
567 | break; | 566 | break; |
568 | } | 567 | } |
569 | #endif | 568 | #endif |
570 | 569 | ||
571 | usblp_unlink_urbs(usblp); | 570 | usblp_unlink_urbs(usblp); |
572 | retval = usblp_set_protocol(usblp, arg); | 571 | retval = usblp_set_protocol(usblp, arg); |
573 | if (retval < 0) { | 572 | if (retval < 0) { |
574 | usblp_set_protocol(usblp, | 573 | usblp_set_protocol(usblp, |
575 | usblp->current_protocol); | 574 | usblp->current_protocol); |
576 | } | 575 | } |
577 | break; | 576 | break; |
578 | 577 | ||
579 | case IOCNR_HP_SET_CHANNEL: | 578 | case IOCNR_HP_SET_CHANNEL: |
580 | if (_IOC_DIR(cmd) != _IOC_WRITE || | 579 | if (_IOC_DIR(cmd) != _IOC_WRITE || |
581 | le16_to_cpu(usblp->dev->descriptor.idVendor) != 0x03F0 || | 580 | le16_to_cpu(usblp->dev->descriptor.idVendor) != 0x03F0 || |
582 | usblp->quirks & USBLP_QUIRK_BIDIR) { | 581 | usblp->quirks & USBLP_QUIRK_BIDIR) { |
583 | retval = -EINVAL; | 582 | retval = -EINVAL; |
584 | goto done; | 583 | goto done; |
585 | } | 584 | } |
586 | 585 | ||
587 | err = usblp_hp_channel_change_request(usblp, | 586 | err = usblp_hp_channel_change_request(usblp, |
588 | arg, &newChannel); | 587 | arg, &newChannel); |
589 | if (err < 0) { | 588 | if (err < 0) { |
590 | dev_err(&usblp->dev->dev, | 589 | dev_err(&usblp->dev->dev, |
591 | "usblp%d: error = %d setting " | 590 | "usblp%d: error = %d setting " |
592 | "HP channel\n", | 591 | "HP channel\n", |
593 | usblp->minor, err); | 592 | usblp->minor, err); |
594 | retval = -EIO; | 593 | retval = -EIO; |
595 | goto done; | 594 | goto done; |
596 | } | 595 | } |
597 | 596 | ||
598 | dbg("usblp%d requested/got HP channel %ld/%d", | 597 | dbg("usblp%d requested/got HP channel %ld/%d", |
599 | usblp->minor, arg, newChannel); | 598 | usblp->minor, arg, newChannel); |
600 | break; | 599 | break; |
601 | 600 | ||
602 | case IOCNR_GET_BUS_ADDRESS: | 601 | case IOCNR_GET_BUS_ADDRESS: |
603 | if (_IOC_DIR(cmd) != _IOC_READ || | 602 | if (_IOC_DIR(cmd) != _IOC_READ || |
604 | _IOC_SIZE(cmd) < sizeof(twoints)) { | 603 | _IOC_SIZE(cmd) < sizeof(twoints)) { |
605 | retval = -EINVAL; | 604 | retval = -EINVAL; |
606 | goto done; | 605 | goto done; |
607 | } | 606 | } |
608 | 607 | ||
609 | twoints[0] = usblp->dev->bus->busnum; | 608 | twoints[0] = usblp->dev->bus->busnum; |
610 | twoints[1] = usblp->dev->devnum; | 609 | twoints[1] = usblp->dev->devnum; |
611 | if (copy_to_user((void __user *)arg, | 610 | if (copy_to_user((void __user *)arg, |
612 | (unsigned char *)twoints, | 611 | (unsigned char *)twoints, |
613 | sizeof(twoints))) { | 612 | sizeof(twoints))) { |
614 | retval = -EFAULT; | 613 | retval = -EFAULT; |
615 | goto done; | 614 | goto done; |
616 | } | 615 | } |
617 | 616 | ||
618 | dbg("usblp%d is bus=%d, device=%d", | 617 | dbg("usblp%d is bus=%d, device=%d", |
619 | usblp->minor, twoints[0], twoints[1]); | 618 | usblp->minor, twoints[0], twoints[1]); |
620 | break; | 619 | break; |
621 | 620 | ||
622 | case IOCNR_GET_VID_PID: | 621 | case IOCNR_GET_VID_PID: |
623 | if (_IOC_DIR(cmd) != _IOC_READ || | 622 | if (_IOC_DIR(cmd) != _IOC_READ || |
624 | _IOC_SIZE(cmd) < sizeof(twoints)) { | 623 | _IOC_SIZE(cmd) < sizeof(twoints)) { |
625 | retval = -EINVAL; | 624 | retval = -EINVAL; |
626 | goto done; | 625 | goto done; |
627 | } | 626 | } |
628 | 627 | ||
629 | twoints[0] = le16_to_cpu(usblp->dev->descriptor.idVendor); | 628 | twoints[0] = le16_to_cpu(usblp->dev->descriptor.idVendor); |
630 | twoints[1] = le16_to_cpu(usblp->dev->descriptor.idProduct); | 629 | twoints[1] = le16_to_cpu(usblp->dev->descriptor.idProduct); |
631 | if (copy_to_user((void __user *)arg, | 630 | if (copy_to_user((void __user *)arg, |
632 | (unsigned char *)twoints, | 631 | (unsigned char *)twoints, |
633 | sizeof(twoints))) { | 632 | sizeof(twoints))) { |
634 | retval = -EFAULT; | 633 | retval = -EFAULT; |
635 | goto done; | 634 | goto done; |
636 | } | 635 | } |
637 | 636 | ||
638 | dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X", | 637 | dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X", |
639 | usblp->minor, twoints[0], twoints[1]); | 638 | usblp->minor, twoints[0], twoints[1]); |
640 | break; | 639 | break; |
641 | 640 | ||
642 | case IOCNR_SOFT_RESET: | 641 | case IOCNR_SOFT_RESET: |
643 | if (_IOC_DIR(cmd) != _IOC_NONE) { | 642 | if (_IOC_DIR(cmd) != _IOC_NONE) { |
644 | retval = -EINVAL; | 643 | retval = -EINVAL; |
645 | goto done; | 644 | goto done; |
646 | } | 645 | } |
647 | retval = usblp_reset(usblp); | 646 | retval = usblp_reset(usblp); |
648 | break; | 647 | break; |
649 | default: | 648 | default: |
650 | retval = -ENOTTY; | 649 | retval = -ENOTTY; |
651 | } | 650 | } |
652 | else /* old-style ioctl value */ | 651 | else /* old-style ioctl value */ |
653 | switch (cmd) { | 652 | switch (cmd) { |
654 | 653 | ||
655 | case LPGETSTATUS: | 654 | case LPGETSTATUS: |
656 | if ((retval = usblp_read_status(usblp, usblp->statusbuf))) { | 655 | if ((retval = usblp_read_status(usblp, usblp->statusbuf))) { |
657 | if (printk_ratelimit()) | 656 | if (printk_ratelimit()) |
658 | printk(KERN_ERR "usblp%d:" | 657 | printk(KERN_ERR "usblp%d:" |
659 | "failed reading printer status (%d)\n", | 658 | "failed reading printer status (%d)\n", |
660 | usblp->minor, retval); | 659 | usblp->minor, retval); |
661 | retval = -EIO; | 660 | retval = -EIO; |
662 | goto done; | 661 | goto done; |
663 | } | 662 | } |
664 | status = *usblp->statusbuf; | 663 | status = *usblp->statusbuf; |
665 | if (copy_to_user ((void __user *)arg, &status, sizeof(int))) | 664 | if (copy_to_user((void __user *)arg, &status, sizeof(int))) |
666 | retval = -EFAULT; | 665 | retval = -EFAULT; |
667 | break; | 666 | break; |
668 | 667 | ||
669 | case LPABORT: | 668 | case LPABORT: |
670 | if (arg) | 669 | if (arg) |
671 | usblp->flags |= LP_ABORT; | 670 | usblp->flags |= LP_ABORT; |
672 | else | 671 | else |
673 | usblp->flags &= ~LP_ABORT; | 672 | usblp->flags &= ~LP_ABORT; |
674 | break; | 673 | break; |
675 | 674 | ||
676 | default: | 675 | default: |
677 | retval = -ENOTTY; | 676 | retval = -ENOTTY; |
678 | } | 677 | } |
679 | 678 | ||
680 | done: | 679 | done: |
681 | mutex_unlock (&usblp->mut); | 680 | mutex_unlock(&usblp->mut); |
682 | return retval; | 681 | return retval; |
683 | } | 682 | } |
684 | 683 | ||
@@ -840,7 +839,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t len, lo | |||
840 | } | 839 | } |
841 | 840 | ||
842 | done: | 841 | done: |
843 | mutex_unlock (&usblp->mut); | 842 | mutex_unlock(&usblp->mut); |
844 | return count; | 843 | return count; |
845 | } | 844 | } |
846 | 845 | ||
@@ -1023,7 +1022,7 @@ raise_urb: | |||
1023 | * while you are sending print data, and you don't try to query the | 1022 | * while you are sending print data, and you don't try to query the |
1024 | * printer status every couple of milliseconds, you will probably be OK. | 1023 | * printer status every couple of milliseconds, you will probably be OK. |
1025 | */ | 1024 | */ |
1026 | static unsigned int usblp_quirks (__u16 vendor, __u16 product) | 1025 | static unsigned int usblp_quirks(__u16 vendor, __u16 product) |
1027 | { | 1026 | { |
1028 | int i; | 1027 | int i; |
1029 | 1028 | ||
@@ -1031,7 +1030,7 @@ static unsigned int usblp_quirks (__u16 vendor, __u16 product) | |||
1031 | if (vendor == quirk_printers[i].vendorId && | 1030 | if (vendor == quirk_printers[i].vendorId && |
1032 | product == quirk_printers[i].productId) | 1031 | product == quirk_printers[i].productId) |
1033 | return quirk_printers[i].quirks; | 1032 | return quirk_printers[i].quirks; |
1034 | } | 1033 | } |
1035 | return 0; | 1034 | return 0; |
1036 | } | 1035 | } |
1037 | 1036 | ||
@@ -1061,7 +1060,7 @@ static struct usb_class_driver usblp_class = { | |||
1061 | static ssize_t usblp_show_ieee1284_id(struct device *dev, struct device_attribute *attr, char *buf) | 1060 | static ssize_t usblp_show_ieee1284_id(struct device *dev, struct device_attribute *attr, char *buf) |
1062 | { | 1061 | { |
1063 | struct usb_interface *intf = to_usb_interface(dev); | 1062 | struct usb_interface *intf = to_usb_interface(dev); |
1064 | struct usblp *usblp = usb_get_intfdata (intf); | 1063 | struct usblp *usblp = usb_get_intfdata(intf); |
1065 | 1064 | ||
1066 | if (usblp->device_id_string[0] == 0 && | 1065 | if (usblp->device_id_string[0] == 0 && |
1067 | usblp->device_id_string[1] == 0) | 1066 | usblp->device_id_string[1] == 0) |
@@ -1075,7 +1074,7 @@ static DEVICE_ATTR(ieee1284_id, S_IRUGO, usblp_show_ieee1284_id, NULL); | |||
1075 | static int usblp_probe(struct usb_interface *intf, | 1074 | static int usblp_probe(struct usb_interface *intf, |
1076 | const struct usb_device_id *id) | 1075 | const struct usb_device_id *id) |
1077 | { | 1076 | { |
1078 | struct usb_device *dev = interface_to_usbdev (intf); | 1077 | struct usb_device *dev = interface_to_usbdev(intf); |
1079 | struct usblp *usblp; | 1078 | struct usblp *usblp; |
1080 | int protocol; | 1079 | int protocol; |
1081 | int retval; | 1080 | int retval; |
@@ -1089,7 +1088,7 @@ static int usblp_probe(struct usb_interface *intf, | |||
1089 | } | 1088 | } |
1090 | usblp->dev = dev; | 1089 | usblp->dev = dev; |
1091 | mutex_init(&usblp->wmut); | 1090 | mutex_init(&usblp->wmut); |
1092 | mutex_init (&usblp->mut); | 1091 | mutex_init(&usblp->mut); |
1093 | spin_lock_init(&usblp->lock); | 1092 | spin_lock_init(&usblp->lock); |
1094 | init_waitqueue_head(&usblp->rwait); | 1093 | init_waitqueue_head(&usblp->rwait); |
1095 | init_waitqueue_head(&usblp->wwait); | 1094 | init_waitqueue_head(&usblp->wwait); |
@@ -1153,7 +1152,7 @@ static int usblp_probe(struct usb_interface *intf, | |||
1153 | usblp_check_status(usblp, 0); | 1152 | usblp_check_status(usblp, 0); |
1154 | #endif | 1153 | #endif |
1155 | 1154 | ||
1156 | usb_set_intfdata (intf, usblp); | 1155 | usb_set_intfdata(intf, usblp); |
1157 | 1156 | ||
1158 | usblp->present = 1; | 1157 | usblp->present = 1; |
1159 | 1158 | ||
@@ -1177,7 +1176,7 @@ static int usblp_probe(struct usb_interface *intf, | |||
1177 | return 0; | 1176 | return 0; |
1178 | 1177 | ||
1179 | abort_intfdata: | 1178 | abort_intfdata: |
1180 | usb_set_intfdata (intf, NULL); | 1179 | usb_set_intfdata(intf, NULL); |
1181 | device_remove_file(&intf->dev, &dev_attr_ieee1284_id); | 1180 | device_remove_file(&intf->dev, &dev_attr_ieee1284_id); |
1182 | abort: | 1181 | abort: |
1183 | kfree(usblp->readbuf); | 1182 | kfree(usblp->readbuf); |
@@ -1340,35 +1339,35 @@ static int usblp_cache_device_id_string(struct usblp *usblp) | |||
1340 | 1339 | ||
1341 | static void usblp_disconnect(struct usb_interface *intf) | 1340 | static void usblp_disconnect(struct usb_interface *intf) |
1342 | { | 1341 | { |
1343 | struct usblp *usblp = usb_get_intfdata (intf); | 1342 | struct usblp *usblp = usb_get_intfdata(intf); |
1344 | 1343 | ||
1345 | usb_deregister_dev(intf, &usblp_class); | 1344 | usb_deregister_dev(intf, &usblp_class); |
1346 | 1345 | ||
1347 | if (!usblp || !usblp->dev) { | 1346 | if (!usblp || !usblp->dev) { |
1348 | dev_err(&intf->dev, "bogus disconnect\n"); | 1347 | dev_err(&intf->dev, "bogus disconnect\n"); |
1349 | BUG (); | 1348 | BUG(); |
1350 | } | 1349 | } |
1351 | 1350 | ||
1352 | device_remove_file(&intf->dev, &dev_attr_ieee1284_id); | 1351 | device_remove_file(&intf->dev, &dev_attr_ieee1284_id); |
1353 | 1352 | ||
1354 | mutex_lock (&usblp_mutex); | 1353 | mutex_lock(&usblp_mutex); |
1355 | mutex_lock (&usblp->mut); | 1354 | mutex_lock(&usblp->mut); |
1356 | usblp->present = 0; | 1355 | usblp->present = 0; |
1357 | wake_up(&usblp->wwait); | 1356 | wake_up(&usblp->wwait); |
1358 | wake_up(&usblp->rwait); | 1357 | wake_up(&usblp->rwait); |
1359 | usb_set_intfdata (intf, NULL); | 1358 | usb_set_intfdata(intf, NULL); |
1360 | 1359 | ||
1361 | usblp_unlink_urbs(usblp); | 1360 | usblp_unlink_urbs(usblp); |
1362 | mutex_unlock (&usblp->mut); | 1361 | mutex_unlock(&usblp->mut); |
1363 | 1362 | ||
1364 | if (!usblp->used) | 1363 | if (!usblp->used) |
1365 | usblp_cleanup (usblp); | 1364 | usblp_cleanup(usblp); |
1366 | mutex_unlock (&usblp_mutex); | 1365 | mutex_unlock(&usblp_mutex); |
1367 | } | 1366 | } |
1368 | 1367 | ||
1369 | static int usblp_suspend(struct usb_interface *intf, pm_message_t message) | 1368 | static int usblp_suspend(struct usb_interface *intf, pm_message_t message) |
1370 | { | 1369 | { |
1371 | struct usblp *usblp = usb_get_intfdata (intf); | 1370 | struct usblp *usblp = usb_get_intfdata(intf); |
1372 | 1371 | ||
1373 | usblp_unlink_urbs(usblp); | 1372 | usblp_unlink_urbs(usblp); |
1374 | #if 0 /* XXX Do we want this? What if someone is reading, should we fail? */ | 1373 | #if 0 /* XXX Do we want this? What if someone is reading, should we fail? */ |
@@ -1382,10 +1381,10 @@ static int usblp_suspend(struct usb_interface *intf, pm_message_t message) | |||
1382 | 1381 | ||
1383 | static int usblp_resume(struct usb_interface *intf) | 1382 | static int usblp_resume(struct usb_interface *intf) |
1384 | { | 1383 | { |
1385 | struct usblp *usblp = usb_get_intfdata (intf); | 1384 | struct usblp *usblp = usb_get_intfdata(intf); |
1386 | int r; | 1385 | int r; |
1387 | 1386 | ||
1388 | r = handle_bidir (usblp); | 1387 | r = handle_bidir(usblp); |
1389 | 1388 | ||
1390 | return r; | 1389 | return r; |
1391 | } | 1390 | } |
@@ -1401,7 +1400,7 @@ static const struct usb_device_id usblp_ids[] = { | |||
1401 | { } /* Terminating entry */ | 1400 | { } /* Terminating entry */ |
1402 | }; | 1401 | }; |
1403 | 1402 | ||
1404 | MODULE_DEVICE_TABLE (usb, usblp_ids); | 1403 | MODULE_DEVICE_TABLE(usb, usblp_ids); |
1405 | 1404 | ||
1406 | static struct usb_driver usblp_driver = { | 1405 | static struct usb_driver usblp_driver = { |
1407 | .name = "usblp", | 1406 | .name = "usblp", |
@@ -1426,8 +1425,8 @@ static void __exit usblp_exit(void) | |||
1426 | module_init(usblp_init); | 1425 | module_init(usblp_init); |
1427 | module_exit(usblp_exit); | 1426 | module_exit(usblp_exit); |
1428 | 1427 | ||
1429 | MODULE_AUTHOR( DRIVER_AUTHOR ); | 1428 | MODULE_AUTHOR(DRIVER_AUTHOR); |
1430 | MODULE_DESCRIPTION( DRIVER_DESC ); | 1429 | MODULE_DESCRIPTION(DRIVER_DESC); |
1431 | module_param(proto_bias, int, S_IRUGO | S_IWUSR); | 1430 | module_param(proto_bias, int, S_IRUGO | S_IWUSR); |
1432 | MODULE_PARM_DESC(proto_bias, "Favourite protocol number"); | 1431 | MODULE_PARM_DESC(proto_bias, "Favourite protocol number"); |
1433 | MODULE_LICENSE("GPL"); | 1432 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index c2f62a3993d2..f1aaff6202a5 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -1668,13 +1668,10 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) | |||
1668 | default: | 1668 | default: |
1669 | if (intf->dev.driver) | 1669 | if (intf->dev.driver) |
1670 | driver = to_usb_driver(intf->dev.driver); | 1670 | driver = to_usb_driver(intf->dev.driver); |
1671 | if (driver == NULL || driver->ioctl == NULL) { | 1671 | if (driver == NULL || driver->unlocked_ioctl == NULL) { |
1672 | retval = -ENOTTY; | 1672 | retval = -ENOTTY; |
1673 | } else { | 1673 | } else { |
1674 | /* keep API that guarantees BKL */ | 1674 | retval = driver->unlocked_ioctl(intf, ctl->ioctl_code, buf); |
1675 | lock_kernel(); | ||
1676 | retval = driver->ioctl(intf, ctl->ioctl_code, buf); | ||
1677 | unlock_kernel(); | ||
1678 | if (retval == -ENOIOCTLCMD) | 1675 | if (retval == -ENOIOCTLCMD) |
1679 | retval = -ENOTTY; | 1676 | retval = -ENOTTY; |
1680 | } | 1677 | } |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index a6bd53ace035..d7a4401ef019 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -1742,9 +1742,8 @@ static int usb_runtime_suspend(struct device *dev) | |||
1742 | } | 1742 | } |
1743 | 1743 | ||
1744 | /* Prevent the parent from suspending immediately after */ | 1744 | /* Prevent the parent from suspending immediately after */ |
1745 | else if (udev->parent) { | 1745 | else if (udev->parent) |
1746 | udev->parent->last_busy = jiffies; | 1746 | udev->parent->last_busy = jiffies; |
1747 | } | ||
1748 | } | 1747 | } |
1749 | 1748 | ||
1750 | /* Runtime suspend for a USB interface doesn't mean anything. */ | 1749 | /* Runtime suspend for a USB interface doesn't mean anything. */ |
@@ -1786,21 +1785,19 @@ static int usb_runtime_idle(struct device *dev) | |||
1786 | return 0; | 1785 | return 0; |
1787 | } | 1786 | } |
1788 | 1787 | ||
1789 | static struct dev_pm_ops usb_bus_pm_ops = { | 1788 | static const struct dev_pm_ops usb_bus_pm_ops = { |
1790 | .runtime_suspend = usb_runtime_suspend, | 1789 | .runtime_suspend = usb_runtime_suspend, |
1791 | .runtime_resume = usb_runtime_resume, | 1790 | .runtime_resume = usb_runtime_resume, |
1792 | .runtime_idle = usb_runtime_idle, | 1791 | .runtime_idle = usb_runtime_idle, |
1793 | }; | 1792 | }; |
1794 | 1793 | ||
1795 | #else | ||
1796 | |||
1797 | #define usb_bus_pm_ops (*(struct dev_pm_ops *) NULL) | ||
1798 | |||
1799 | #endif /* CONFIG_USB_SUSPEND */ | 1794 | #endif /* CONFIG_USB_SUSPEND */ |
1800 | 1795 | ||
1801 | struct bus_type usb_bus_type = { | 1796 | struct bus_type usb_bus_type = { |
1802 | .name = "usb", | 1797 | .name = "usb", |
1803 | .match = usb_device_match, | 1798 | .match = usb_device_match, |
1804 | .uevent = usb_uevent, | 1799 | .uevent = usb_uevent, |
1800 | #ifdef CONFIG_USB_SUSPEND | ||
1805 | .pm = &usb_bus_pm_ops, | 1801 | .pm = &usb_bus_pm_ops, |
1802 | #endif | ||
1806 | }; | 1803 | }; |
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 4f84a41ee7a8..3788e738e265 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c | |||
@@ -96,16 +96,21 @@ static ssize_t show_ep_interval(struct device *dev, | |||
96 | 96 | ||
97 | switch (usb_endpoint_type(ep->desc)) { | 97 | switch (usb_endpoint_type(ep->desc)) { |
98 | case USB_ENDPOINT_XFER_CONTROL: | 98 | case USB_ENDPOINT_XFER_CONTROL: |
99 | if (ep->udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ | 99 | if (ep->udev->speed == USB_SPEED_HIGH) |
100 | /* uframes per NAK */ | ||
100 | interval = ep->desc->bInterval; | 101 | interval = ep->desc->bInterval; |
101 | break; | 102 | break; |
103 | |||
102 | case USB_ENDPOINT_XFER_ISOC: | 104 | case USB_ENDPOINT_XFER_ISOC: |
103 | interval = 1 << (ep->desc->bInterval - 1); | 105 | interval = 1 << (ep->desc->bInterval - 1); |
104 | break; | 106 | break; |
107 | |||
105 | case USB_ENDPOINT_XFER_BULK: | 108 | case USB_ENDPOINT_XFER_BULK: |
106 | if (ep->udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ | 109 | if (ep->udev->speed == USB_SPEED_HIGH && !in) |
110 | /* uframes per NAK */ | ||
107 | interval = ep->desc->bInterval; | 111 | interval = ep->desc->bInterval; |
108 | break; | 112 | break; |
113 | |||
109 | case USB_ENDPOINT_XFER_INT: | 114 | case USB_ENDPOINT_XFER_INT: |
110 | if (ep->udev->speed == USB_SPEED_HIGH) | 115 | if (ep->udev->speed == USB_SPEED_HIGH) |
111 | interval = 1 << (ep->desc->bInterval - 1); | 116 | interval = 1 << (ep->desc->bInterval - 1); |
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 9a34ccb0a1c0..69ecd3c92311 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c | |||
@@ -105,8 +105,10 @@ int usb_choose_configuration(struct usb_device *udev) | |||
105 | /* When the first config's first interface is one of Microsoft's | 105 | /* When the first config's first interface is one of Microsoft's |
106 | * pet nonstandard Ethernet-over-USB protocols, ignore it unless | 106 | * pet nonstandard Ethernet-over-USB protocols, ignore it unless |
107 | * this kernel has enabled the necessary host side driver. | 107 | * this kernel has enabled the necessary host side driver. |
108 | * But: Don't ignore it if it's the only config. | ||
108 | */ | 109 | */ |
109 | if (i == 0 && desc && (is_rndis(desc) || is_activesync(desc))) { | 110 | if (i == 0 && num_configs > 1 && desc && |
111 | (is_rndis(desc) || is_activesync(desc))) { | ||
110 | #if !defined(CONFIG_USB_NET_RNDIS_HOST) && !defined(CONFIG_USB_NET_RNDIS_HOST_MODULE) | 112 | #if !defined(CONFIG_USB_NET_RNDIS_HOST) && !defined(CONFIG_USB_NET_RNDIS_HOST_MODULE) |
111 | continue; | 113 | continue; |
112 | #else | 114 | #else |
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 1cf2d1e79a5c..c3f98543caaf 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
@@ -66,10 +66,7 @@ static void companion_common(struct pci_dev *pdev, struct usb_hcd *hcd, | |||
66 | * vice versa. | 66 | * vice versa. |
67 | */ | 67 | */ |
68 | companion = NULL; | 68 | companion = NULL; |
69 | for (;;) { | 69 | for_each_pci_dev(companion) { |
70 | companion = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, companion); | ||
71 | if (!companion) | ||
72 | break; | ||
73 | if (companion->bus != pdev->bus || | 70 | if (companion->bus != pdev->bus || |
74 | PCI_SLOT(companion->devfn) != slot) | 71 | PCI_SLOT(companion->devfn) != slot) |
75 | continue; | 72 | continue; |
@@ -250,6 +247,9 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
250 | if (retval != 0) | 247 | if (retval != 0) |
251 | goto err4; | 248 | goto err4; |
252 | set_hs_companion(dev, hcd); | 249 | set_hs_companion(dev, hcd); |
250 | |||
251 | if (pci_dev_run_wake(dev)) | ||
252 | pm_runtime_put_noidle(&dev->dev); | ||
253 | return retval; | 253 | return retval; |
254 | 254 | ||
255 | err4: | 255 | err4: |
@@ -292,6 +292,17 @@ void usb_hcd_pci_remove(struct pci_dev *dev) | |||
292 | if (!hcd) | 292 | if (!hcd) |
293 | return; | 293 | return; |
294 | 294 | ||
295 | if (pci_dev_run_wake(dev)) | ||
296 | pm_runtime_get_noresume(&dev->dev); | ||
297 | |||
298 | /* Fake an interrupt request in order to give the driver a chance | ||
299 | * to test whether the controller hardware has been removed (e.g., | ||
300 | * cardbus physical eject). | ||
301 | */ | ||
302 | local_irq_disable(); | ||
303 | usb_hcd_irq(0, hcd); | ||
304 | local_irq_enable(); | ||
305 | |||
295 | usb_remove_hcd(hcd); | 306 | usb_remove_hcd(hcd); |
296 | if (hcd->driver->flags & HCD_MEMORY) { | 307 | if (hcd->driver->flags & HCD_MEMORY) { |
297 | iounmap(hcd->regs); | 308 | iounmap(hcd->regs); |
@@ -317,12 +328,34 @@ void usb_hcd_pci_shutdown(struct pci_dev *dev) | |||
317 | if (!hcd) | 328 | if (!hcd) |
318 | return; | 329 | return; |
319 | 330 | ||
320 | if (hcd->driver->shutdown) | 331 | if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && |
332 | hcd->driver->shutdown) | ||
321 | hcd->driver->shutdown(hcd); | 333 | hcd->driver->shutdown(hcd); |
322 | } | 334 | } |
323 | EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown); | 335 | EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown); |
324 | 336 | ||
325 | #ifdef CONFIG_PM_SLEEP | 337 | #ifdef CONFIG_PM_OPS |
338 | |||
339 | #ifdef CONFIG_PPC_PMAC | ||
340 | static void powermac_set_asic(struct pci_dev *pci_dev, int enable) | ||
341 | { | ||
342 | /* Enanble or disable ASIC clocks for USB */ | ||
343 | if (machine_is(powermac)) { | ||
344 | struct device_node *of_node; | ||
345 | |||
346 | of_node = pci_device_to_OF_node(pci_dev); | ||
347 | if (of_node) | ||
348 | pmac_call_feature(PMAC_FTR_USB_ENABLE, | ||
349 | of_node, 0, enable); | ||
350 | } | ||
351 | } | ||
352 | |||
353 | #else | ||
354 | |||
355 | static inline void powermac_set_asic(struct pci_dev *pci_dev, int enable) | ||
356 | {} | ||
357 | |||
358 | #endif /* CONFIG_PPC_PMAC */ | ||
326 | 359 | ||
327 | static int check_root_hub_suspended(struct device *dev) | 360 | static int check_root_hub_suspended(struct device *dev) |
328 | { | 361 | { |
@@ -337,7 +370,7 @@ static int check_root_hub_suspended(struct device *dev) | |||
337 | return 0; | 370 | return 0; |
338 | } | 371 | } |
339 | 372 | ||
340 | static int hcd_pci_suspend(struct device *dev) | 373 | static int suspend_common(struct device *dev, bool do_wakeup) |
341 | { | 374 | { |
342 | struct pci_dev *pci_dev = to_pci_dev(dev); | 375 | struct pci_dev *pci_dev = to_pci_dev(dev); |
343 | struct usb_hcd *hcd = pci_get_drvdata(pci_dev); | 376 | struct usb_hcd *hcd = pci_get_drvdata(pci_dev); |
@@ -352,13 +385,21 @@ static int hcd_pci_suspend(struct device *dev) | |||
352 | if (retval) | 385 | if (retval) |
353 | return retval; | 386 | return retval; |
354 | 387 | ||
355 | /* We might already be suspended (runtime PM -- not yet written) */ | ||
356 | if (pci_dev->current_state != PCI_D0) | ||
357 | return retval; | ||
358 | |||
359 | if (hcd->driver->pci_suspend) { | 388 | if (hcd->driver->pci_suspend) { |
360 | retval = hcd->driver->pci_suspend(hcd); | 389 | /* Optimization: Don't suspend if a root-hub wakeup is |
390 | * pending and it would cause the HCD to wake up anyway. | ||
391 | */ | ||
392 | if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) | ||
393 | return -EBUSY; | ||
394 | retval = hcd->driver->pci_suspend(hcd, do_wakeup); | ||
361 | suspend_report_result(hcd->driver->pci_suspend, retval); | 395 | suspend_report_result(hcd->driver->pci_suspend, retval); |
396 | |||
397 | /* Check again in case wakeup raced with pci_suspend */ | ||
398 | if (retval == 0 && do_wakeup && HCD_WAKEUP_PENDING(hcd)) { | ||
399 | if (hcd->driver->pci_resume) | ||
400 | hcd->driver->pci_resume(hcd, false); | ||
401 | retval = -EBUSY; | ||
402 | } | ||
362 | if (retval) | 403 | if (retval) |
363 | return retval; | 404 | return retval; |
364 | } | 405 | } |
@@ -374,6 +415,48 @@ static int hcd_pci_suspend(struct device *dev) | |||
374 | return retval; | 415 | return retval; |
375 | } | 416 | } |
376 | 417 | ||
418 | static int resume_common(struct device *dev, int event) | ||
419 | { | ||
420 | struct pci_dev *pci_dev = to_pci_dev(dev); | ||
421 | struct usb_hcd *hcd = pci_get_drvdata(pci_dev); | ||
422 | int retval; | ||
423 | |||
424 | if (hcd->state != HC_STATE_SUSPENDED) { | ||
425 | dev_dbg(dev, "can't resume, not suspended!\n"); | ||
426 | return 0; | ||
427 | } | ||
428 | |||
429 | retval = pci_enable_device(pci_dev); | ||
430 | if (retval < 0) { | ||
431 | dev_err(dev, "can't re-enable after resume, %d!\n", retval); | ||
432 | return retval; | ||
433 | } | ||
434 | |||
435 | pci_set_master(pci_dev); | ||
436 | |||
437 | clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); | ||
438 | |||
439 | if (hcd->driver->pci_resume) { | ||
440 | if (event != PM_EVENT_AUTO_RESUME) | ||
441 | wait_for_companions(pci_dev, hcd); | ||
442 | |||
443 | retval = hcd->driver->pci_resume(hcd, | ||
444 | event == PM_EVENT_RESTORE); | ||
445 | if (retval) { | ||
446 | dev_err(dev, "PCI post-resume error %d!\n", retval); | ||
447 | usb_hc_died(hcd); | ||
448 | } | ||
449 | } | ||
450 | return retval; | ||
451 | } | ||
452 | |||
453 | #ifdef CONFIG_PM_SLEEP | ||
454 | |||
455 | static int hcd_pci_suspend(struct device *dev) | ||
456 | { | ||
457 | return suspend_common(dev, device_may_wakeup(dev)); | ||
458 | } | ||
459 | |||
377 | static int hcd_pci_suspend_noirq(struct device *dev) | 460 | static int hcd_pci_suspend_noirq(struct device *dev) |
378 | { | 461 | { |
379 | struct pci_dev *pci_dev = to_pci_dev(dev); | 462 | struct pci_dev *pci_dev = to_pci_dev(dev); |
@@ -408,16 +491,7 @@ static int hcd_pci_suspend_noirq(struct device *dev) | |||
408 | return retval; | 491 | return retval; |
409 | } | 492 | } |
410 | 493 | ||
411 | #ifdef CONFIG_PPC_PMAC | 494 | powermac_set_asic(pci_dev, 0); |
412 | /* Disable ASIC clocks for USB */ | ||
413 | if (machine_is(powermac)) { | ||
414 | struct device_node *of_node; | ||
415 | |||
416 | of_node = pci_device_to_OF_node(pci_dev); | ||
417 | if (of_node) | ||
418 | pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); | ||
419 | } | ||
420 | #endif | ||
421 | return retval; | 495 | return retval; |
422 | } | 496 | } |
423 | 497 | ||
@@ -425,69 +499,63 @@ static int hcd_pci_resume_noirq(struct device *dev) | |||
425 | { | 499 | { |
426 | struct pci_dev *pci_dev = to_pci_dev(dev); | 500 | struct pci_dev *pci_dev = to_pci_dev(dev); |
427 | 501 | ||
428 | #ifdef CONFIG_PPC_PMAC | 502 | powermac_set_asic(pci_dev, 1); |
429 | /* Reenable ASIC clocks for USB */ | ||
430 | if (machine_is(powermac)) { | ||
431 | struct device_node *of_node; | ||
432 | |||
433 | of_node = pci_device_to_OF_node(pci_dev); | ||
434 | if (of_node) | ||
435 | pmac_call_feature(PMAC_FTR_USB_ENABLE, | ||
436 | of_node, 0, 1); | ||
437 | } | ||
438 | #endif | ||
439 | 503 | ||
440 | /* Go back to D0 and disable remote wakeup */ | 504 | /* Go back to D0 and disable remote wakeup */ |
441 | pci_back_from_sleep(pci_dev); | 505 | pci_back_from_sleep(pci_dev); |
442 | return 0; | 506 | return 0; |
443 | } | 507 | } |
444 | 508 | ||
445 | static int resume_common(struct device *dev, bool hibernated) | 509 | static int hcd_pci_resume(struct device *dev) |
446 | { | 510 | { |
447 | struct pci_dev *pci_dev = to_pci_dev(dev); | 511 | return resume_common(dev, PM_EVENT_RESUME); |
448 | struct usb_hcd *hcd = pci_get_drvdata(pci_dev); | 512 | } |
449 | int retval; | ||
450 | 513 | ||
451 | if (hcd->state != HC_STATE_SUSPENDED) { | 514 | static int hcd_pci_restore(struct device *dev) |
452 | dev_dbg(dev, "can't resume, not suspended!\n"); | 515 | { |
453 | return 0; | 516 | return resume_common(dev, PM_EVENT_RESTORE); |
454 | } | 517 | } |
455 | 518 | ||
456 | retval = pci_enable_device(pci_dev); | 519 | #else |
457 | if (retval < 0) { | ||
458 | dev_err(dev, "can't re-enable after resume, %d!\n", retval); | ||
459 | return retval; | ||
460 | } | ||
461 | 520 | ||
462 | pci_set_master(pci_dev); | 521 | #define hcd_pci_suspend NULL |
522 | #define hcd_pci_suspend_noirq NULL | ||
523 | #define hcd_pci_resume_noirq NULL | ||
524 | #define hcd_pci_resume NULL | ||
525 | #define hcd_pci_restore NULL | ||
463 | 526 | ||
464 | clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); | 527 | #endif /* CONFIG_PM_SLEEP */ |
465 | 528 | ||
466 | if (hcd->driver->pci_resume) { | 529 | #ifdef CONFIG_PM_RUNTIME |
467 | /* This call should be made only during system resume, | ||
468 | * not during runtime resume. | ||
469 | */ | ||
470 | wait_for_companions(pci_dev, hcd); | ||
471 | 530 | ||
472 | retval = hcd->driver->pci_resume(hcd, hibernated); | 531 | static int hcd_pci_runtime_suspend(struct device *dev) |
473 | if (retval) { | 532 | { |
474 | dev_err(dev, "PCI post-resume error %d!\n", retval); | 533 | int retval; |
475 | usb_hc_died(hcd); | 534 | |
476 | } | 535 | retval = suspend_common(dev, true); |
477 | } | 536 | if (retval == 0) |
537 | powermac_set_asic(to_pci_dev(dev), 0); | ||
538 | dev_dbg(dev, "hcd_pci_runtime_suspend: %d\n", retval); | ||
478 | return retval; | 539 | return retval; |
479 | } | 540 | } |
480 | 541 | ||
481 | static int hcd_pci_resume(struct device *dev) | 542 | static int hcd_pci_runtime_resume(struct device *dev) |
482 | { | 543 | { |
483 | return resume_common(dev, false); | 544 | int retval; |
484 | } | ||
485 | 545 | ||
486 | static int hcd_pci_restore(struct device *dev) | 546 | powermac_set_asic(to_pci_dev(dev), 1); |
487 | { | 547 | retval = resume_common(dev, PM_EVENT_AUTO_RESUME); |
488 | return resume_common(dev, true); | 548 | dev_dbg(dev, "hcd_pci_runtime_resume: %d\n", retval); |
549 | return retval; | ||
489 | } | 550 | } |
490 | 551 | ||
552 | #else | ||
553 | |||
554 | #define hcd_pci_runtime_suspend NULL | ||
555 | #define hcd_pci_runtime_resume NULL | ||
556 | |||
557 | #endif /* CONFIG_PM_RUNTIME */ | ||
558 | |||
491 | const struct dev_pm_ops usb_hcd_pci_pm_ops = { | 559 | const struct dev_pm_ops usb_hcd_pci_pm_ops = { |
492 | .suspend = hcd_pci_suspend, | 560 | .suspend = hcd_pci_suspend, |
493 | .suspend_noirq = hcd_pci_suspend_noirq, | 561 | .suspend_noirq = hcd_pci_suspend_noirq, |
@@ -501,7 +569,9 @@ const struct dev_pm_ops usb_hcd_pci_pm_ops = { | |||
501 | .poweroff_noirq = hcd_pci_suspend_noirq, | 569 | .poweroff_noirq = hcd_pci_suspend_noirq, |
502 | .restore_noirq = hcd_pci_resume_noirq, | 570 | .restore_noirq = hcd_pci_resume_noirq, |
503 | .restore = hcd_pci_restore, | 571 | .restore = hcd_pci_restore, |
572 | .runtime_suspend = hcd_pci_runtime_suspend, | ||
573 | .runtime_resume = hcd_pci_runtime_resume, | ||
504 | }; | 574 | }; |
505 | EXPORT_SYMBOL_GPL(usb_hcd_pci_pm_ops); | 575 | EXPORT_SYMBOL_GPL(usb_hcd_pci_pm_ops); |
506 | 576 | ||
507 | #endif /* CONFIG_PM_SLEEP */ | 577 | #endif /* CONFIG_PM_OPS */ |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 12742f152f43..5cca00a6d09d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -667,7 +667,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) | |||
667 | unsigned long flags; | 667 | unsigned long flags; |
668 | char buffer[6]; /* Any root hubs with > 31 ports? */ | 668 | char buffer[6]; /* Any root hubs with > 31 ports? */ |
669 | 669 | ||
670 | if (unlikely(!hcd->rh_registered)) | 670 | if (unlikely(!hcd->rh_pollable)) |
671 | return; | 671 | return; |
672 | if (!hcd->uses_new_polling && !hcd->status_urb) | 672 | if (!hcd->uses_new_polling && !hcd->status_urb) |
673 | return; | 673 | return; |
@@ -679,7 +679,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) | |||
679 | spin_lock_irqsave(&hcd_root_hub_lock, flags); | 679 | spin_lock_irqsave(&hcd_root_hub_lock, flags); |
680 | urb = hcd->status_urb; | 680 | urb = hcd->status_urb; |
681 | if (urb) { | 681 | if (urb) { |
682 | hcd->poll_pending = 0; | 682 | clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags); |
683 | hcd->status_urb = NULL; | 683 | hcd->status_urb = NULL; |
684 | urb->actual_length = length; | 684 | urb->actual_length = length; |
685 | memcpy(urb->transfer_buffer, buffer, length); | 685 | memcpy(urb->transfer_buffer, buffer, length); |
@@ -690,7 +690,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) | |||
690 | spin_lock(&hcd_root_hub_lock); | 690 | spin_lock(&hcd_root_hub_lock); |
691 | } else { | 691 | } else { |
692 | length = 0; | 692 | length = 0; |
693 | hcd->poll_pending = 1; | 693 | set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags); |
694 | } | 694 | } |
695 | spin_unlock_irqrestore(&hcd_root_hub_lock, flags); | 695 | spin_unlock_irqrestore(&hcd_root_hub_lock, flags); |
696 | } | 696 | } |
@@ -699,7 +699,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) | |||
699 | * exceed that limit if HZ is 100. The math is more clunky than | 699 | * exceed that limit if HZ is 100. The math is more clunky than |
700 | * maybe expected, this is to make sure that all timers for USB devices | 700 | * maybe expected, this is to make sure that all timers for USB devices |
701 | * fire at the same time to give the CPU a break inbetween */ | 701 | * fire at the same time to give the CPU a break inbetween */ |
702 | if (hcd->uses_new_polling ? hcd->poll_rh : | 702 | if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) : |
703 | (length == 0 && hcd->status_urb != NULL)) | 703 | (length == 0 && hcd->status_urb != NULL)) |
704 | mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); | 704 | mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); |
705 | } | 705 | } |
@@ -736,7 +736,7 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb) | |||
736 | mod_timer(&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); | 736 | mod_timer(&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); |
737 | 737 | ||
738 | /* If a status change has already occurred, report it ASAP */ | 738 | /* If a status change has already occurred, report it ASAP */ |
739 | else if (hcd->poll_pending) | 739 | else if (HCD_POLL_PENDING(hcd)) |
740 | mod_timer(&hcd->rh_timer, jiffies); | 740 | mod_timer(&hcd->rh_timer, jiffies); |
741 | retval = 0; | 741 | retval = 0; |
742 | done: | 742 | done: |
@@ -1150,8 +1150,7 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, | |||
1150 | * finish unlinking the initial failed usb_set_address() | 1150 | * finish unlinking the initial failed usb_set_address() |
1151 | * or device descriptor fetch. | 1151 | * or device descriptor fetch. |
1152 | */ | 1152 | */ |
1153 | if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) && | 1153 | if (!HCD_SAW_IRQ(hcd) && !is_root_hub(urb->dev)) { |
1154 | !is_root_hub(urb->dev)) { | ||
1155 | dev_warn(hcd->self.controller, "Unlink after no-IRQ? " | 1154 | dev_warn(hcd->self.controller, "Unlink after no-IRQ? " |
1156 | "Controller is probably using the wrong IRQ.\n"); | 1155 | "Controller is probably using the wrong IRQ.\n"); |
1157 | set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); | 1156 | set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); |
@@ -1219,6 +1218,11 @@ static int hcd_alloc_coherent(struct usb_bus *bus, | |||
1219 | { | 1218 | { |
1220 | unsigned char *vaddr; | 1219 | unsigned char *vaddr; |
1221 | 1220 | ||
1221 | if (*vaddr_handle == NULL) { | ||
1222 | WARN_ON_ONCE(1); | ||
1223 | return -EFAULT; | ||
1224 | } | ||
1225 | |||
1222 | vaddr = hcd_buffer_alloc(bus, size + sizeof(vaddr), | 1226 | vaddr = hcd_buffer_alloc(bus, size + sizeof(vaddr), |
1223 | mem_flags, dma_handle); | 1227 | mem_flags, dma_handle); |
1224 | if (!vaddr) | 1228 | if (!vaddr) |
@@ -1941,6 +1945,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) | |||
1941 | 1945 | ||
1942 | dev_dbg(&rhdev->dev, "usb %s%s\n", | 1946 | dev_dbg(&rhdev->dev, "usb %s%s\n", |
1943 | (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume"); | 1947 | (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume"); |
1948 | clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags); | ||
1944 | if (!hcd->driver->bus_resume) | 1949 | if (!hcd->driver->bus_resume) |
1945 | return -ENOENT; | 1950 | return -ENOENT; |
1946 | if (hcd->state == HC_STATE_RUNNING) | 1951 | if (hcd->state == HC_STATE_RUNNING) |
@@ -1994,8 +1999,10 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd) | |||
1994 | unsigned long flags; | 1999 | unsigned long flags; |
1995 | 2000 | ||
1996 | spin_lock_irqsave (&hcd_root_hub_lock, flags); | 2001 | spin_lock_irqsave (&hcd_root_hub_lock, flags); |
1997 | if (hcd->rh_registered) | 2002 | if (hcd->rh_registered) { |
2003 | set_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags); | ||
1998 | queue_work(pm_wq, &hcd->wakeup_work); | 2004 | queue_work(pm_wq, &hcd->wakeup_work); |
2005 | } | ||
1999 | spin_unlock_irqrestore (&hcd_root_hub_lock, flags); | 2006 | spin_unlock_irqrestore (&hcd_root_hub_lock, flags); |
2000 | } | 2007 | } |
2001 | EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub); | 2008 | EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub); |
@@ -2063,8 +2070,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd) | |||
2063 | */ | 2070 | */ |
2064 | local_irq_save(flags); | 2071 | local_irq_save(flags); |
2065 | 2072 | ||
2066 | if (unlikely(hcd->state == HC_STATE_HALT || | 2073 | if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) { |
2067 | !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { | ||
2068 | rc = IRQ_NONE; | 2074 | rc = IRQ_NONE; |
2069 | } else if (hcd->driver->irq(hcd) == IRQ_NONE) { | 2075 | } else if (hcd->driver->irq(hcd) == IRQ_NONE) { |
2070 | rc = IRQ_NONE; | 2076 | rc = IRQ_NONE; |
@@ -2079,6 +2085,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd) | |||
2079 | local_irq_restore(flags); | 2085 | local_irq_restore(flags); |
2080 | return rc; | 2086 | return rc; |
2081 | } | 2087 | } |
2088 | EXPORT_SYMBOL_GPL(usb_hcd_irq); | ||
2082 | 2089 | ||
2083 | /*-------------------------------------------------------------------------*/ | 2090 | /*-------------------------------------------------------------------------*/ |
2084 | 2091 | ||
@@ -2098,7 +2105,7 @@ void usb_hc_died (struct usb_hcd *hcd) | |||
2098 | 2105 | ||
2099 | spin_lock_irqsave (&hcd_root_hub_lock, flags); | 2106 | spin_lock_irqsave (&hcd_root_hub_lock, flags); |
2100 | if (hcd->rh_registered) { | 2107 | if (hcd->rh_registered) { |
2101 | hcd->poll_rh = 0; | 2108 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
2102 | 2109 | ||
2103 | /* make khubd clean up old urbs and devices */ | 2110 | /* make khubd clean up old urbs and devices */ |
2104 | usb_set_device_state (hcd->self.root_hub, | 2111 | usb_set_device_state (hcd->self.root_hub, |
@@ -2217,6 +2224,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2217 | retval = -ENOMEM; | 2224 | retval = -ENOMEM; |
2218 | goto err_allocate_root_hub; | 2225 | goto err_allocate_root_hub; |
2219 | } | 2226 | } |
2227 | hcd->self.root_hub = rhdev; | ||
2220 | 2228 | ||
2221 | switch (hcd->driver->flags & HCD_MASK) { | 2229 | switch (hcd->driver->flags & HCD_MASK) { |
2222 | case HCD_USB11: | 2230 | case HCD_USB11: |
@@ -2229,9 +2237,8 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2229 | rhdev->speed = USB_SPEED_SUPER; | 2237 | rhdev->speed = USB_SPEED_SUPER; |
2230 | break; | 2238 | break; |
2231 | default: | 2239 | default: |
2232 | goto err_allocate_root_hub; | 2240 | goto err_set_rh_speed; |
2233 | } | 2241 | } |
2234 | hcd->self.root_hub = rhdev; | ||
2235 | 2242 | ||
2236 | /* wakeup flag init defaults to "everything works" for root hubs, | 2243 | /* wakeup flag init defaults to "everything works" for root hubs, |
2237 | * but drivers can override it in reset() if needed, along with | 2244 | * but drivers can override it in reset() if needed, along with |
@@ -2246,6 +2253,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2246 | dev_err(hcd->self.controller, "can't setup\n"); | 2253 | dev_err(hcd->self.controller, "can't setup\n"); |
2247 | goto err_hcd_driver_setup; | 2254 | goto err_hcd_driver_setup; |
2248 | } | 2255 | } |
2256 | hcd->rh_pollable = 1; | ||
2249 | 2257 | ||
2250 | /* NOTE: root hub and controller capabilities may not be the same */ | 2258 | /* NOTE: root hub and controller capabilities may not be the same */ |
2251 | if (device_can_wakeup(hcd->self.controller) | 2259 | if (device_can_wakeup(hcd->self.controller) |
@@ -2300,23 +2308,38 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2300 | retval); | 2308 | retval); |
2301 | goto error_create_attr_group; | 2309 | goto error_create_attr_group; |
2302 | } | 2310 | } |
2303 | if (hcd->uses_new_polling && hcd->poll_rh) | 2311 | if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) |
2304 | usb_hcd_poll_rh_status(hcd); | 2312 | usb_hcd_poll_rh_status(hcd); |
2305 | return retval; | 2313 | return retval; |
2306 | 2314 | ||
2307 | error_create_attr_group: | 2315 | error_create_attr_group: |
2316 | if (HC_IS_RUNNING(hcd->state)) | ||
2317 | hcd->state = HC_STATE_QUIESCING; | ||
2318 | spin_lock_irq(&hcd_root_hub_lock); | ||
2319 | hcd->rh_registered = 0; | ||
2320 | spin_unlock_irq(&hcd_root_hub_lock); | ||
2321 | |||
2322 | #ifdef CONFIG_USB_SUSPEND | ||
2323 | cancel_work_sync(&hcd->wakeup_work); | ||
2324 | #endif | ||
2308 | mutex_lock(&usb_bus_list_lock); | 2325 | mutex_lock(&usb_bus_list_lock); |
2309 | usb_disconnect(&hcd->self.root_hub); | 2326 | usb_disconnect(&rhdev); /* Sets rhdev to NULL */ |
2310 | mutex_unlock(&usb_bus_list_lock); | 2327 | mutex_unlock(&usb_bus_list_lock); |
2311 | err_register_root_hub: | 2328 | err_register_root_hub: |
2329 | hcd->rh_pollable = 0; | ||
2330 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
2331 | del_timer_sync(&hcd->rh_timer); | ||
2312 | hcd->driver->stop(hcd); | 2332 | hcd->driver->stop(hcd); |
2333 | hcd->state = HC_STATE_HALT; | ||
2334 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
2335 | del_timer_sync(&hcd->rh_timer); | ||
2313 | err_hcd_driver_start: | 2336 | err_hcd_driver_start: |
2314 | if (hcd->irq >= 0) | 2337 | if (hcd->irq >= 0) |
2315 | free_irq(irqnum, hcd); | 2338 | free_irq(irqnum, hcd); |
2316 | err_request_irq: | 2339 | err_request_irq: |
2317 | err_hcd_driver_setup: | 2340 | err_hcd_driver_setup: |
2318 | hcd->self.root_hub = NULL; | 2341 | err_set_rh_speed: |
2319 | usb_put_dev(rhdev); | 2342 | usb_put_dev(hcd->self.root_hub); |
2320 | err_allocate_root_hub: | 2343 | err_allocate_root_hub: |
2321 | usb_deregister_bus(&hcd->self); | 2344 | usb_deregister_bus(&hcd->self); |
2322 | err_register_bus: | 2345 | err_register_bus: |
@@ -2335,8 +2358,13 @@ EXPORT_SYMBOL_GPL(usb_add_hcd); | |||
2335 | */ | 2358 | */ |
2336 | void usb_remove_hcd(struct usb_hcd *hcd) | 2359 | void usb_remove_hcd(struct usb_hcd *hcd) |
2337 | { | 2360 | { |
2361 | struct usb_device *rhdev = hcd->self.root_hub; | ||
2362 | |||
2338 | dev_info(hcd->self.controller, "remove, state %x\n", hcd->state); | 2363 | dev_info(hcd->self.controller, "remove, state %x\n", hcd->state); |
2339 | 2364 | ||
2365 | usb_get_dev(rhdev); | ||
2366 | sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group); | ||
2367 | |||
2340 | if (HC_IS_RUNNING (hcd->state)) | 2368 | if (HC_IS_RUNNING (hcd->state)) |
2341 | hcd->state = HC_STATE_QUIESCING; | 2369 | hcd->state = HC_STATE_QUIESCING; |
2342 | 2370 | ||
@@ -2349,19 +2377,30 @@ void usb_remove_hcd(struct usb_hcd *hcd) | |||
2349 | cancel_work_sync(&hcd->wakeup_work); | 2377 | cancel_work_sync(&hcd->wakeup_work); |
2350 | #endif | 2378 | #endif |
2351 | 2379 | ||
2352 | sysfs_remove_group(&hcd->self.root_hub->dev.kobj, &usb_bus_attr_group); | ||
2353 | mutex_lock(&usb_bus_list_lock); | 2380 | mutex_lock(&usb_bus_list_lock); |
2354 | usb_disconnect(&hcd->self.root_hub); | 2381 | usb_disconnect(&rhdev); /* Sets rhdev to NULL */ |
2355 | mutex_unlock(&usb_bus_list_lock); | 2382 | mutex_unlock(&usb_bus_list_lock); |
2356 | 2383 | ||
2384 | /* Prevent any more root-hub status calls from the timer. | ||
2385 | * The HCD might still restart the timer (if a port status change | ||
2386 | * interrupt occurs), but usb_hcd_poll_rh_status() won't invoke | ||
2387 | * the hub_status_data() callback. | ||
2388 | */ | ||
2389 | hcd->rh_pollable = 0; | ||
2390 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
2391 | del_timer_sync(&hcd->rh_timer); | ||
2392 | |||
2357 | hcd->driver->stop(hcd); | 2393 | hcd->driver->stop(hcd); |
2358 | hcd->state = HC_STATE_HALT; | 2394 | hcd->state = HC_STATE_HALT; |
2359 | 2395 | ||
2360 | hcd->poll_rh = 0; | 2396 | /* In case the HCD restarted the timer, stop it again. */ |
2397 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
2361 | del_timer_sync(&hcd->rh_timer); | 2398 | del_timer_sync(&hcd->rh_timer); |
2362 | 2399 | ||
2363 | if (hcd->irq >= 0) | 2400 | if (hcd->irq >= 0) |
2364 | free_irq(hcd->irq, hcd); | 2401 | free_irq(hcd->irq, hcd); |
2402 | |||
2403 | usb_put_dev(hcd->self.root_hub); | ||
2365 | usb_deregister_bus(&hcd->self); | 2404 | usb_deregister_bus(&hcd->self); |
2366 | hcd_buffer_destroy(hcd); | 2405 | hcd_buffer_destroy(hcd); |
2367 | } | 2406 | } |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 70cccc75a362..84c1897188d2 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/usb.h> | 20 | #include <linux/usb.h> |
21 | #include <linux/usbdevice_fs.h> | 21 | #include <linux/usbdevice_fs.h> |
22 | #include <linux/usb/hcd.h> | 22 | #include <linux/usb/hcd.h> |
23 | #include <linux/usb/quirks.h> | ||
23 | #include <linux/kthread.h> | 24 | #include <linux/kthread.h> |
24 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
25 | #include <linux/freezer.h> | 26 | #include <linux/freezer.h> |
@@ -1294,6 +1295,7 @@ descriptor_error: | |||
1294 | return -ENODEV; | 1295 | return -ENODEV; |
1295 | } | 1296 | } |
1296 | 1297 | ||
1298 | /* No BKL needed */ | ||
1297 | static int | 1299 | static int |
1298 | hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) | 1300 | hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) |
1299 | { | 1301 | { |
@@ -1801,7 +1803,6 @@ int usb_new_device(struct usb_device *udev) | |||
1801 | pm_runtime_set_active(&udev->dev); | 1803 | pm_runtime_set_active(&udev->dev); |
1802 | pm_runtime_enable(&udev->dev); | 1804 | pm_runtime_enable(&udev->dev); |
1803 | 1805 | ||
1804 | usb_detect_quirks(udev); | ||
1805 | err = usb_enumerate_device(udev); /* Read descriptors */ | 1806 | err = usb_enumerate_device(udev); /* Read descriptors */ |
1806 | if (err < 0) | 1807 | if (err < 0) |
1807 | goto fail; | 1808 | goto fail; |
@@ -2880,7 +2881,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2880 | } | 2881 | } |
2881 | 2882 | ||
2882 | retval = 0; | 2883 | retval = 0; |
2883 | 2884 | /* notify HCD that we have a device connected and addressed */ | |
2885 | if (hcd->driver->update_device) | ||
2886 | hcd->driver->update_device(hcd, udev); | ||
2884 | fail: | 2887 | fail: |
2885 | if (retval) { | 2888 | if (retval) { |
2886 | hub_port_disable(hub, port1, 0); | 2889 | hub_port_disable(hub, port1, 0); |
@@ -3111,6 +3114,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, | |||
3111 | if (status < 0) | 3114 | if (status < 0) |
3112 | goto loop; | 3115 | goto loop; |
3113 | 3116 | ||
3117 | usb_detect_quirks(udev); | ||
3118 | if (udev->quirks & USB_QUIRK_DELAY_INIT) | ||
3119 | msleep(1000); | ||
3120 | |||
3114 | /* consecutive bus-powered hubs aren't reliable; they can | 3121 | /* consecutive bus-powered hubs aren't reliable; they can |
3115 | * violate the voltage drop budget. if the new child has | 3122 | * violate the voltage drop budget. if the new child has |
3116 | * a "powered" LED, users should notice we didn't enable it | 3123 | * a "powered" LED, users should notice we didn't enable it |
@@ -3463,7 +3470,7 @@ static struct usb_driver hub_driver = { | |||
3463 | .reset_resume = hub_reset_resume, | 3470 | .reset_resume = hub_reset_resume, |
3464 | .pre_reset = hub_pre_reset, | 3471 | .pre_reset = hub_pre_reset, |
3465 | .post_reset = hub_post_reset, | 3472 | .post_reset = hub_post_reset, |
3466 | .ioctl = hub_ioctl, | 3473 | .unlocked_ioctl = hub_ioctl, |
3467 | .id_table = hub_id_table, | 3474 | .id_table = hub_id_table, |
3468 | .supports_autosuspend = 1, | 3475 | .supports_autosuspend = 1, |
3469 | }; | 3476 | }; |
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 1a27618b67d6..095fa5366690 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
@@ -265,13 +265,9 @@ static int remount(struct super_block *sb, int *flags, char *data) | |||
265 | return -EINVAL; | 265 | return -EINVAL; |
266 | } | 266 | } |
267 | 267 | ||
268 | lock_kernel(); | ||
269 | |||
270 | if (usbfs_mount && usbfs_mount->mnt_sb) | 268 | if (usbfs_mount && usbfs_mount->mnt_sb) |
271 | update_sb(usbfs_mount->mnt_sb); | 269 | update_sb(usbfs_mount->mnt_sb); |
272 | 270 | ||
273 | unlock_kernel(); | ||
274 | |||
275 | return 0; | 271 | return 0; |
276 | } | 272 | } |
277 | 273 | ||
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index db99c084df92..25719da45e33 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c | |||
@@ -38,6 +38,9 @@ static const struct usb_device_id usb_quirk_list[] = { | |||
38 | /* Creative SB Audigy 2 NX */ | 38 | /* Creative SB Audigy 2 NX */ |
39 | { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, | 39 | { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, |
40 | 40 | ||
41 | /* Logitech Harmony 700-series */ | ||
42 | { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, | ||
43 | |||
41 | /* Philips PSC805 audio device */ | 44 | /* Philips PSC805 audio device */ |
42 | { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, | 45 | { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, |
43 | 46 | ||
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 7c0555548ac8..419e6b34e2fe 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c | |||
@@ -137,6 +137,16 @@ void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor) | |||
137 | } | 137 | } |
138 | EXPORT_SYMBOL_GPL(usb_anchor_urb); | 138 | EXPORT_SYMBOL_GPL(usb_anchor_urb); |
139 | 139 | ||
140 | /* Callers must hold anchor->lock */ | ||
141 | static void __usb_unanchor_urb(struct urb *urb, struct usb_anchor *anchor) | ||
142 | { | ||
143 | urb->anchor = NULL; | ||
144 | list_del(&urb->anchor_list); | ||
145 | usb_put_urb(urb); | ||
146 | if (list_empty(&anchor->urb_list)) | ||
147 | wake_up(&anchor->wait); | ||
148 | } | ||
149 | |||
140 | /** | 150 | /** |
141 | * usb_unanchor_urb - unanchors an URB | 151 | * usb_unanchor_urb - unanchors an URB |
142 | * @urb: pointer to the urb to anchor | 152 | * @urb: pointer to the urb to anchor |
@@ -156,17 +166,14 @@ void usb_unanchor_urb(struct urb *urb) | |||
156 | return; | 166 | return; |
157 | 167 | ||
158 | spin_lock_irqsave(&anchor->lock, flags); | 168 | spin_lock_irqsave(&anchor->lock, flags); |
159 | if (unlikely(anchor != urb->anchor)) { | 169 | /* |
160 | /* we've lost the race to another thread */ | 170 | * At this point, we could be competing with another thread which |
161 | spin_unlock_irqrestore(&anchor->lock, flags); | 171 | * has the same intention. To protect the urb from being unanchored |
162 | return; | 172 | * twice, only the winner of the race gets the job. |
163 | } | 173 | */ |
164 | urb->anchor = NULL; | 174 | if (likely(anchor == urb->anchor)) |
165 | list_del(&urb->anchor_list); | 175 | __usb_unanchor_urb(urb, anchor); |
166 | spin_unlock_irqrestore(&anchor->lock, flags); | 176 | spin_unlock_irqrestore(&anchor->lock, flags); |
167 | usb_put_urb(urb); | ||
168 | if (list_empty(&anchor->urb_list)) | ||
169 | wake_up(&anchor->wait); | ||
170 | } | 177 | } |
171 | EXPORT_SYMBOL_GPL(usb_unanchor_urb); | 178 | EXPORT_SYMBOL_GPL(usb_unanchor_urb); |
172 | 179 | ||
@@ -749,20 +756,11 @@ EXPORT_SYMBOL_GPL(usb_unpoison_anchored_urbs); | |||
749 | void usb_unlink_anchored_urbs(struct usb_anchor *anchor) | 756 | void usb_unlink_anchored_urbs(struct usb_anchor *anchor) |
750 | { | 757 | { |
751 | struct urb *victim; | 758 | struct urb *victim; |
752 | unsigned long flags; | ||
753 | 759 | ||
754 | spin_lock_irqsave(&anchor->lock, flags); | 760 | while ((victim = usb_get_from_anchor(anchor)) != NULL) { |
755 | while (!list_empty(&anchor->urb_list)) { | ||
756 | victim = list_entry(anchor->urb_list.prev, struct urb, | ||
757 | anchor_list); | ||
758 | usb_get_urb(victim); | ||
759 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
760 | /* this will unanchor the URB */ | ||
761 | usb_unlink_urb(victim); | 761 | usb_unlink_urb(victim); |
762 | usb_put_urb(victim); | 762 | usb_put_urb(victim); |
763 | spin_lock_irqsave(&anchor->lock, flags); | ||
764 | } | 763 | } |
765 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
766 | } | 764 | } |
767 | EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs); | 765 | EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs); |
768 | 766 | ||
@@ -799,12 +797,11 @@ struct urb *usb_get_from_anchor(struct usb_anchor *anchor) | |||
799 | victim = list_entry(anchor->urb_list.next, struct urb, | 797 | victim = list_entry(anchor->urb_list.next, struct urb, |
800 | anchor_list); | 798 | anchor_list); |
801 | usb_get_urb(victim); | 799 | usb_get_urb(victim); |
802 | spin_unlock_irqrestore(&anchor->lock, flags); | 800 | __usb_unanchor_urb(victim, anchor); |
803 | usb_unanchor_urb(victim); | ||
804 | } else { | 801 | } else { |
805 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
806 | victim = NULL; | 802 | victim = NULL; |
807 | } | 803 | } |
804 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
808 | 805 | ||
809 | return victim; | 806 | return victim; |
810 | } | 807 | } |
@@ -826,12 +823,7 @@ void usb_scuttle_anchored_urbs(struct usb_anchor *anchor) | |||
826 | while (!list_empty(&anchor->urb_list)) { | 823 | while (!list_empty(&anchor->urb_list)) { |
827 | victim = list_entry(anchor->urb_list.prev, struct urb, | 824 | victim = list_entry(anchor->urb_list.prev, struct urb, |
828 | anchor_list); | 825 | anchor_list); |
829 | usb_get_urb(victim); | 826 | __usb_unanchor_urb(victim, anchor); |
830 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
831 | /* this may free the URB */ | ||
832 | usb_unanchor_urb(victim); | ||
833 | usb_put_urb(victim); | ||
834 | spin_lock_irqsave(&anchor->lock, flags); | ||
835 | } | 827 | } |
836 | spin_unlock_irqrestore(&anchor->lock, flags); | 828 | spin_unlock_irqrestore(&anchor->lock, flags); |
837 | } | 829 | } |
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 5ae14f6c1e7a..fdd4130fbb7d 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -317,10 +317,6 @@ static const struct dev_pm_ops usb_device_pm_ops = { | |||
317 | .restore = usb_dev_restore, | 317 | .restore = usb_dev_restore, |
318 | }; | 318 | }; |
319 | 319 | ||
320 | #else | ||
321 | |||
322 | #define usb_device_pm_ops (*(struct dev_pm_ops *) NULL) | ||
323 | |||
324 | #endif /* CONFIG_PM */ | 320 | #endif /* CONFIG_PM */ |
325 | 321 | ||
326 | 322 | ||
@@ -338,7 +334,9 @@ struct device_type usb_device_type = { | |||
338 | .release = usb_release_dev, | 334 | .release = usb_release_dev, |
339 | .uevent = usb_dev_uevent, | 335 | .uevent = usb_dev_uevent, |
340 | .devnode = usb_devnode, | 336 | .devnode = usb_devnode, |
337 | #ifdef CONFIG_PM | ||
341 | .pm = &usb_device_pm_ops, | 338 | .pm = &usb_device_pm_ops, |
339 | #endif | ||
342 | }; | 340 | }; |
343 | 341 | ||
344 | 342 | ||
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 591ae9fde199..cd27f9bde2c8 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -714,6 +714,7 @@ config USB_GADGETFS | |||
714 | config USB_FUNCTIONFS | 714 | config USB_FUNCTIONFS |
715 | tristate "Function Filesystem (EXPERIMENTAL)" | 715 | tristate "Function Filesystem (EXPERIMENTAL)" |
716 | depends on EXPERIMENTAL | 716 | depends on EXPERIMENTAL |
717 | select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS) | ||
717 | help | 718 | help |
718 | The Function Filesystem (FunctioFS) lets one create USB | 719 | The Function Filesystem (FunctioFS) lets one create USB |
719 | composite functions in user space in the same way as GadgetFS | 720 | composite functions in user space in the same way as GadgetFS |
@@ -722,31 +723,31 @@ config USB_FUNCTIONFS | |||
722 | implemented in kernel space (for instance Ethernet, serial or | 723 | implemented in kernel space (for instance Ethernet, serial or |
723 | mass storage) and other are implemented in user space. | 724 | mass storage) and other are implemented in user space. |
724 | 725 | ||
726 | If you say "y" or "m" here you will be able what kind of | ||
727 | configurations the gadget will provide. | ||
728 | |||
725 | Say "y" to link the driver statically, or "m" to build | 729 | Say "y" to link the driver statically, or "m" to build |
726 | a dynamically linked module called "g_ffs". | 730 | a dynamically linked module called "g_ffs". |
727 | 731 | ||
728 | config USB_FUNCTIONFS_ETH | 732 | config USB_FUNCTIONFS_ETH |
729 | bool "Include CDC ECM (Ethernet) function" | 733 | bool "Include configuration with CDC ECM (Ethernet)" |
730 | depends on USB_FUNCTIONFS && NET | 734 | depends on USB_FUNCTIONFS && NET |
731 | help | 735 | help |
732 | Include an CDC ECM (Ethernet) funcion in the CDC ECM (Funcion) | 736 | Include a configuration with CDC ECM funcion (Ethernet) and the |
733 | Filesystem. If you also say "y" to the RNDIS query below the | 737 | Funcion Filesystem. |
734 | gadget will have two configurations. | ||
735 | 738 | ||
736 | config USB_FUNCTIONFS_RNDIS | 739 | config USB_FUNCTIONFS_RNDIS |
737 | bool "Include RNDIS (Ethernet) function" | 740 | bool "Include configuration with RNDIS (Ethernet)" |
738 | depends on USB_FUNCTIONFS && NET | 741 | depends on USB_FUNCTIONFS && NET |
739 | help | 742 | help |
740 | Include an RNDIS (Ethernet) funcion in the Funcion Filesystem. | 743 | Include a configuration with RNDIS funcion (Ethernet) and the Filesystem. |
741 | If you also say "y" to the CDC ECM query above the gadget will | ||
742 | have two configurations. | ||
743 | 744 | ||
744 | config USB_FUNCTIONFS_GENERIC | 745 | config USB_FUNCTIONFS_GENERIC |
745 | bool "Include 'pure' configuration" | 746 | bool "Include 'pure' configuration" |
746 | depends on USB_FUNCTIONFS && (USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS) | 747 | depends on USB_FUNCTIONFS |
747 | help | 748 | help |
748 | Include a configuration with FunctionFS and no Ethernet | 749 | Include a configuration with the Function Filesystem alone with |
749 | configuration. | 750 | no Ethernet interface. |
750 | 751 | ||
751 | config USB_FILE_STORAGE | 752 | config USB_FILE_STORAGE |
752 | tristate "File-backed Storage Gadget" | 753 | tristate "File-backed Storage Gadget" |
@@ -863,6 +864,7 @@ config USB_G_NOKIA | |||
863 | config USB_G_MULTI | 864 | config USB_G_MULTI |
864 | tristate "Multifunction Composite Gadget (EXPERIMENTAL)" | 865 | tristate "Multifunction Composite Gadget (EXPERIMENTAL)" |
865 | depends on BLOCK && NET | 866 | depends on BLOCK && NET |
867 | select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS | ||
866 | help | 868 | help |
867 | The Multifunction Composite Gadget provides Ethernet (RNDIS | 869 | The Multifunction Composite Gadget provides Ethernet (RNDIS |
868 | and/or CDC Ethernet), mass storage and ACM serial link | 870 | and/or CDC Ethernet), mass storage and ACM serial link |
@@ -913,6 +915,34 @@ config USB_G_HID | |||
913 | Say "y" to link the driver statically, or "m" to build a | 915 | Say "y" to link the driver statically, or "m" to build a |
914 | dynamically linked module called "g_hid". | 916 | dynamically linked module called "g_hid". |
915 | 917 | ||
918 | config USB_G_DBGP | ||
919 | tristate "EHCI Debug Device Gadget" | ||
920 | help | ||
921 | This gadget emulates an EHCI Debug device. This is useful when you want | ||
922 | to interact with an EHCI Debug Port. | ||
923 | |||
924 | Say "y" to link the driver statically, or "m" to build a | ||
925 | dynamically linked module called "g_dbgp". | ||
926 | |||
927 | if USB_G_DBGP | ||
928 | choice | ||
929 | prompt "EHCI Debug Device mode" | ||
930 | default USB_G_DBGP_SERIAL | ||
931 | |||
932 | config USB_G_DBGP_PRINTK | ||
933 | depends on USB_G_DBGP | ||
934 | bool "printk" | ||
935 | help | ||
936 | Directly printk() received data. No interaction. | ||
937 | |||
938 | config USB_G_DBGP_SERIAL | ||
939 | depends on USB_G_DBGP | ||
940 | bool "serial" | ||
941 | help | ||
942 | Userland can interact using /dev/ttyGSxxx. | ||
943 | endchoice | ||
944 | endif | ||
945 | |||
916 | # put drivers that need isochronous transfer support (for audio | 946 | # put drivers that need isochronous transfer support (for audio |
917 | # or video class gadget drivers), or specific hardware, here. | 947 | # or video class gadget drivers), or specific hardware, here. |
918 | config USB_G_WEBCAM | 948 | config USB_G_WEBCAM |
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 9bcde110feb1..27283df37d09 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile | |||
@@ -44,6 +44,7 @@ g_printer-objs := printer.o | |||
44 | g_cdc-objs := cdc2.o | 44 | g_cdc-objs := cdc2.o |
45 | g_multi-objs := multi.o | 45 | g_multi-objs := multi.o |
46 | g_hid-objs := hid.o | 46 | g_hid-objs := hid.o |
47 | g_dbgp-objs := dbgp.o | ||
47 | g_nokia-objs := nokia.o | 48 | g_nokia-objs := nokia.o |
48 | g_webcam-objs := webcam.o | 49 | g_webcam-objs := webcam.o |
49 | 50 | ||
@@ -52,7 +53,6 @@ obj-$(CONFIG_USB_AUDIO) += g_audio.o | |||
52 | obj-$(CONFIG_USB_ETH) += g_ether.o | 53 | obj-$(CONFIG_USB_ETH) += g_ether.o |
53 | obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o | 54 | obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o |
54 | obj-$(CONFIG_USB_FUNCTIONFS) += g_ffs.o | 55 | obj-$(CONFIG_USB_FUNCTIONFS) += g_ffs.o |
55 | obj-$(CONFIG_USB_ETH_FUNCTIONFS) += g_eth_ffs.o | ||
56 | obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o | 56 | obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o |
57 | obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o | 57 | obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o |
58 | obj-$(CONFIG_USB_G_SERIAL) += g_serial.o | 58 | obj-$(CONFIG_USB_G_SERIAL) += g_serial.o |
@@ -60,6 +60,7 @@ obj-$(CONFIG_USB_G_PRINTER) += g_printer.o | |||
60 | obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o | 60 | obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o |
61 | obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o | 61 | obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o |
62 | obj-$(CONFIG_USB_G_HID) += g_hid.o | 62 | obj-$(CONFIG_USB_G_HID) += g_hid.o |
63 | obj-$(CONFIG_USB_G_DBGP) += g_dbgp.o | ||
63 | obj-$(CONFIG_USB_G_MULTI) += g_multi.o | 64 | obj-$(CONFIG_USB_G_MULTI) += g_multi.o |
64 | obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o | 65 | obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o |
65 | obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o | 66 | obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o |
diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index a62af7b59094..b744ccd0f34d 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c | |||
@@ -89,7 +89,7 @@ static const struct usb_descriptor_header *otg_desc[] = { | |||
89 | 89 | ||
90 | /*-------------------------------------------------------------------------*/ | 90 | /*-------------------------------------------------------------------------*/ |
91 | 91 | ||
92 | static int __init audio_do_config(struct usb_configuration *c) | 92 | static int __ref audio_do_config(struct usb_configuration *c) |
93 | { | 93 | { |
94 | /* FIXME alloc iConfiguration string, set it in c->strings */ | 94 | /* FIXME alloc iConfiguration string, set it in c->strings */ |
95 | 95 | ||
@@ -113,7 +113,7 @@ static struct usb_configuration audio_config_driver = { | |||
113 | 113 | ||
114 | /*-------------------------------------------------------------------------*/ | 114 | /*-------------------------------------------------------------------------*/ |
115 | 115 | ||
116 | static int __init audio_bind(struct usb_composite_dev *cdev) | 116 | static int __ref audio_bind(struct usb_composite_dev *cdev) |
117 | { | 117 | { |
118 | int gcnum; | 118 | int gcnum; |
119 | int status; | 119 | int status; |
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 928137d3dbdc..1f5ba2fd4c1f 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c | |||
@@ -129,7 +129,7 @@ static u8 hostaddr[ETH_ALEN]; | |||
129 | /* | 129 | /* |
130 | * We _always_ have both CDC ECM and CDC ACM functions. | 130 | * We _always_ have both CDC ECM and CDC ACM functions. |
131 | */ | 131 | */ |
132 | static int __init cdc_do_config(struct usb_configuration *c) | 132 | static int __ref cdc_do_config(struct usb_configuration *c) |
133 | { | 133 | { |
134 | int status; | 134 | int status; |
135 | 135 | ||
@@ -159,7 +159,7 @@ static struct usb_configuration cdc_config_driver = { | |||
159 | 159 | ||
160 | /*-------------------------------------------------------------------------*/ | 160 | /*-------------------------------------------------------------------------*/ |
161 | 161 | ||
162 | static int __init cdc_bind(struct usb_composite_dev *cdev) | 162 | static int __ref cdc_bind(struct usb_composite_dev *cdev) |
163 | { | 163 | { |
164 | int gcnum; | 164 | int gcnum; |
165 | struct usb_gadget *gadget = cdev->gadget; | 165 | struct usb_gadget *gadget = cdev->gadget; |
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 391d169f8d07..e483f80822d2 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c | |||
@@ -673,20 +673,83 @@ static int get_string(struct usb_composite_dev *cdev, | |||
673 | * string IDs. Drivers for functions, configurations, or gadgets will | 673 | * string IDs. Drivers for functions, configurations, or gadgets will |
674 | * then store that ID in the appropriate descriptors and string table. | 674 | * then store that ID in the appropriate descriptors and string table. |
675 | * | 675 | * |
676 | * All string identifier should be allocated using this routine, to | 676 | * All string identifier should be allocated using this, |
677 | * ensure that for example different functions don't wrongly assign | 677 | * @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure |
678 | * different meanings to the same identifier. | 678 | * that for example different functions don't wrongly assign different |
679 | * meanings to the same identifier. | ||
679 | */ | 680 | */ |
680 | int usb_string_id(struct usb_composite_dev *cdev) | 681 | int usb_string_id(struct usb_composite_dev *cdev) |
681 | { | 682 | { |
682 | if (cdev->next_string_id < 254) { | 683 | if (cdev->next_string_id < 254) { |
683 | /* string id 0 is reserved */ | 684 | /* string id 0 is reserved by USB spec for list of |
685 | * supported languages */ | ||
686 | /* 255 reserved as well? -- mina86 */ | ||
684 | cdev->next_string_id++; | 687 | cdev->next_string_id++; |
685 | return cdev->next_string_id; | 688 | return cdev->next_string_id; |
686 | } | 689 | } |
687 | return -ENODEV; | 690 | return -ENODEV; |
688 | } | 691 | } |
689 | 692 | ||
693 | /** | ||
694 | * usb_string_ids() - allocate unused string IDs in batch | ||
695 | * @cdev: the device whose string descriptor IDs are being allocated | ||
696 | * @str: an array of usb_string objects to assign numbers to | ||
697 | * Context: single threaded during gadget setup | ||
698 | * | ||
699 | * @usb_string_ids() is called from bind() callbacks to allocate | ||
700 | * string IDs. Drivers for functions, configurations, or gadgets will | ||
701 | * then copy IDs from the string table to the appropriate descriptors | ||
702 | * and string table for other languages. | ||
703 | * | ||
704 | * All string identifier should be allocated using this, | ||
705 | * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for | ||
706 | * example different functions don't wrongly assign different meanings | ||
707 | * to the same identifier. | ||
708 | */ | ||
709 | int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str) | ||
710 | { | ||
711 | int next = cdev->next_string_id; | ||
712 | |||
713 | for (; str->s; ++str) { | ||
714 | if (unlikely(next >= 254)) | ||
715 | return -ENODEV; | ||
716 | str->id = ++next; | ||
717 | } | ||
718 | |||
719 | cdev->next_string_id = next; | ||
720 | |||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | /** | ||
725 | * usb_string_ids_n() - allocate unused string IDs in batch | ||
726 | * @cdev: the device whose string descriptor IDs are being allocated | ||
727 | * @n: number of string IDs to allocate | ||
728 | * Context: single threaded during gadget setup | ||
729 | * | ||
730 | * Returns the first requested ID. This ID and next @n-1 IDs are now | ||
731 | * valid IDs. At least providind that @n is non zore because if it | ||
732 | * is, returns last requested ID which is now very useful information. | ||
733 | * | ||
734 | * @usb_string_ids_n() is called from bind() callbacks to allocate | ||
735 | * string IDs. Drivers for functions, configurations, or gadgets will | ||
736 | * then store that ID in the appropriate descriptors and string table. | ||
737 | * | ||
738 | * All string identifier should be allocated using this, | ||
739 | * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for | ||
740 | * example different functions don't wrongly assign different meanings | ||
741 | * to the same identifier. | ||
742 | */ | ||
743 | int usb_string_ids_n(struct usb_composite_dev *c, unsigned n) | ||
744 | { | ||
745 | unsigned next = c->next_string_id; | ||
746 | if (unlikely(n > 254 || (unsigned)next + n > 254)) | ||
747 | return -ENODEV; | ||
748 | c->next_string_id += n; | ||
749 | return next + 1; | ||
750 | } | ||
751 | |||
752 | |||
690 | /*-------------------------------------------------------------------------*/ | 753 | /*-------------------------------------------------------------------------*/ |
691 | 754 | ||
692 | static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req) | 755 | static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req) |
@@ -893,6 +956,8 @@ static void composite_disconnect(struct usb_gadget *gadget) | |||
893 | spin_lock_irqsave(&cdev->lock, flags); | 956 | spin_lock_irqsave(&cdev->lock, flags); |
894 | if (cdev->config) | 957 | if (cdev->config) |
895 | reset_config(cdev); | 958 | reset_config(cdev); |
959 | if (composite->disconnect) | ||
960 | composite->disconnect(cdev); | ||
896 | spin_unlock_irqrestore(&cdev->lock, flags); | 961 | spin_unlock_irqrestore(&cdev->lock, flags); |
897 | } | 962 | } |
898 | 963 | ||
diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/dbgp.c new file mode 100644 index 000000000000..0ed50a2c0a36 --- /dev/null +++ b/drivers/usb/gadget/dbgp.c | |||
@@ -0,0 +1,434 @@ | |||
1 | /* | ||
2 | * dbgp.c -- EHCI Debug Port device gadget | ||
3 | * | ||
4 | * Copyright (C) 2010 Stephane Duverger | ||
5 | * | ||
6 | * Released under the GPLv2. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | /* verbose messages */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/usb/ch9.h> | ||
14 | #include <linux/usb/gadget.h> | ||
15 | |||
16 | /* See comments in "zero.c" */ | ||
17 | #include "epautoconf.c" | ||
18 | |||
19 | #ifdef CONFIG_USB_G_DBGP_SERIAL | ||
20 | #include "u_serial.c" | ||
21 | #endif | ||
22 | |||
23 | #define DRIVER_VENDOR_ID 0x0525 /* NetChip */ | ||
24 | #define DRIVER_PRODUCT_ID 0xc0de /* undefined */ | ||
25 | |||
26 | #define USB_DEBUG_MAX_PACKET_SIZE 8 | ||
27 | #define DBGP_REQ_EP0_LEN 128 | ||
28 | #define DBGP_REQ_LEN 512 | ||
29 | |||
30 | static struct dbgp { | ||
31 | struct usb_gadget *gadget; | ||
32 | struct usb_request *req; | ||
33 | struct usb_ep *i_ep; | ||
34 | struct usb_ep *o_ep; | ||
35 | #ifdef CONFIG_USB_G_DBGP_SERIAL | ||
36 | struct gserial *serial; | ||
37 | #endif | ||
38 | } dbgp; | ||
39 | |||
40 | static struct usb_device_descriptor device_desc = { | ||
41 | .bLength = sizeof device_desc, | ||
42 | .bDescriptorType = USB_DT_DEVICE, | ||
43 | .bcdUSB = __constant_cpu_to_le16(0x0200), | ||
44 | .bDeviceClass = USB_CLASS_VENDOR_SPEC, | ||
45 | .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID), | ||
46 | .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID), | ||
47 | .bNumConfigurations = 1, | ||
48 | }; | ||
49 | |||
50 | static struct usb_debug_descriptor dbg_desc = { | ||
51 | .bLength = sizeof dbg_desc, | ||
52 | .bDescriptorType = USB_DT_DEBUG, | ||
53 | }; | ||
54 | |||
55 | static struct usb_endpoint_descriptor i_desc = { | ||
56 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
57 | .bDescriptorType = USB_DT_ENDPOINT, | ||
58 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
59 | .bEndpointAddress = USB_DIR_IN, | ||
60 | }; | ||
61 | |||
62 | static struct usb_endpoint_descriptor o_desc = { | ||
63 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
64 | .bDescriptorType = USB_DT_ENDPOINT, | ||
65 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
66 | .bEndpointAddress = USB_DIR_OUT, | ||
67 | }; | ||
68 | |||
69 | #ifdef CONFIG_USB_G_DBGP_PRINTK | ||
70 | static int dbgp_consume(char *buf, unsigned len) | ||
71 | { | ||
72 | char c; | ||
73 | |||
74 | if (!len) | ||
75 | return 0; | ||
76 | |||
77 | c = buf[len-1]; | ||
78 | if (c != 0) | ||
79 | buf[len-1] = 0; | ||
80 | |||
81 | printk(KERN_NOTICE "%s%c", buf, c); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static void __disable_ep(struct usb_ep *ep) | ||
86 | { | ||
87 | if (ep && ep->driver_data == dbgp.gadget) { | ||
88 | usb_ep_disable(ep); | ||
89 | ep->driver_data = NULL; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | static void dbgp_disable_ep(void) | ||
94 | { | ||
95 | __disable_ep(dbgp.i_ep); | ||
96 | __disable_ep(dbgp.o_ep); | ||
97 | } | ||
98 | |||
99 | static void dbgp_complete(struct usb_ep *ep, struct usb_request *req) | ||
100 | { | ||
101 | int stp; | ||
102 | int err = 0; | ||
103 | int status = req->status; | ||
104 | |||
105 | if (ep == dbgp.i_ep) { | ||
106 | stp = 1; | ||
107 | goto fail; | ||
108 | } | ||
109 | |||
110 | if (status != 0) { | ||
111 | stp = 2; | ||
112 | goto release_req; | ||
113 | } | ||
114 | |||
115 | dbgp_consume(req->buf, req->actual); | ||
116 | |||
117 | req->length = DBGP_REQ_LEN; | ||
118 | err = usb_ep_queue(ep, req, GFP_ATOMIC); | ||
119 | if (err < 0) { | ||
120 | stp = 3; | ||
121 | goto release_req; | ||
122 | } | ||
123 | |||
124 | return; | ||
125 | |||
126 | release_req: | ||
127 | kfree(req->buf); | ||
128 | usb_ep_free_request(dbgp.o_ep, req); | ||
129 | dbgp_disable_ep(); | ||
130 | fail: | ||
131 | dev_dbg(&dbgp.gadget->dev, | ||
132 | "complete: failure (%d:%d) ==> %d\n", stp, err, status); | ||
133 | } | ||
134 | |||
135 | static int dbgp_enable_ep_req(struct usb_ep *ep) | ||
136 | { | ||
137 | int err, stp; | ||
138 | struct usb_request *req; | ||
139 | |||
140 | req = usb_ep_alloc_request(ep, GFP_KERNEL); | ||
141 | if (!req) { | ||
142 | err = -ENOMEM; | ||
143 | stp = 1; | ||
144 | goto fail_1; | ||
145 | } | ||
146 | |||
147 | req->buf = kmalloc(DBGP_REQ_LEN, GFP_KERNEL); | ||
148 | if (!req->buf) { | ||
149 | err = -ENOMEM; | ||
150 | stp = 2; | ||
151 | goto fail_2; | ||
152 | } | ||
153 | |||
154 | req->complete = dbgp_complete; | ||
155 | req->length = DBGP_REQ_LEN; | ||
156 | err = usb_ep_queue(ep, req, GFP_ATOMIC); | ||
157 | if (err < 0) { | ||
158 | stp = 3; | ||
159 | goto fail_3; | ||
160 | } | ||
161 | |||
162 | return 0; | ||
163 | |||
164 | fail_3: | ||
165 | kfree(req->buf); | ||
166 | fail_2: | ||
167 | usb_ep_free_request(dbgp.o_ep, req); | ||
168 | fail_1: | ||
169 | dev_dbg(&dbgp.gadget->dev, | ||
170 | "enable ep req: failure (%d:%d)\n", stp, err); | ||
171 | return err; | ||
172 | } | ||
173 | |||
174 | static int __enable_ep(struct usb_ep *ep, struct usb_endpoint_descriptor *desc) | ||
175 | { | ||
176 | int err = usb_ep_enable(ep, desc); | ||
177 | ep->driver_data = dbgp.gadget; | ||
178 | return err; | ||
179 | } | ||
180 | |||
181 | static int dbgp_enable_ep(void) | ||
182 | { | ||
183 | int err, stp; | ||
184 | |||
185 | err = __enable_ep(dbgp.i_ep, &i_desc); | ||
186 | if (err < 0) { | ||
187 | stp = 1; | ||
188 | goto fail_1; | ||
189 | } | ||
190 | |||
191 | err = __enable_ep(dbgp.o_ep, &o_desc); | ||
192 | if (err < 0) { | ||
193 | stp = 2; | ||
194 | goto fail_2; | ||
195 | } | ||
196 | |||
197 | err = dbgp_enable_ep_req(dbgp.o_ep); | ||
198 | if (err < 0) { | ||
199 | stp = 3; | ||
200 | goto fail_3; | ||
201 | } | ||
202 | |||
203 | return 0; | ||
204 | |||
205 | fail_3: | ||
206 | __disable_ep(dbgp.o_ep); | ||
207 | fail_2: | ||
208 | __disable_ep(dbgp.i_ep); | ||
209 | fail_1: | ||
210 | dev_dbg(&dbgp.gadget->dev, "enable ep: failure (%d:%d)\n", stp, err); | ||
211 | return err; | ||
212 | } | ||
213 | #endif | ||
214 | |||
215 | static void dbgp_disconnect(struct usb_gadget *gadget) | ||
216 | { | ||
217 | #ifdef CONFIG_USB_G_DBGP_PRINTK | ||
218 | dbgp_disable_ep(); | ||
219 | #else | ||
220 | gserial_disconnect(dbgp.serial); | ||
221 | #endif | ||
222 | } | ||
223 | |||
224 | static void dbgp_unbind(struct usb_gadget *gadget) | ||
225 | { | ||
226 | #ifdef CONFIG_USB_G_DBGP_SERIAL | ||
227 | kfree(dbgp.serial); | ||
228 | #endif | ||
229 | if (dbgp.req) { | ||
230 | kfree(dbgp.req->buf); | ||
231 | usb_ep_free_request(gadget->ep0, dbgp.req); | ||
232 | } | ||
233 | |||
234 | gadget->ep0->driver_data = NULL; | ||
235 | } | ||
236 | |||
237 | static int __init dbgp_configure_endpoints(struct usb_gadget *gadget) | ||
238 | { | ||
239 | int stp; | ||
240 | |||
241 | usb_ep_autoconfig_reset(gadget); | ||
242 | |||
243 | dbgp.i_ep = usb_ep_autoconfig(gadget, &i_desc); | ||
244 | if (!dbgp.i_ep) { | ||
245 | stp = 1; | ||
246 | goto fail_1; | ||
247 | } | ||
248 | |||
249 | dbgp.i_ep->driver_data = gadget; | ||
250 | i_desc.wMaxPacketSize = | ||
251 | __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE); | ||
252 | |||
253 | dbgp.o_ep = usb_ep_autoconfig(gadget, &o_desc); | ||
254 | if (!dbgp.o_ep) { | ||
255 | dbgp.i_ep->driver_data = NULL; | ||
256 | stp = 2; | ||
257 | goto fail_2; | ||
258 | } | ||
259 | |||
260 | dbgp.o_ep->driver_data = gadget; | ||
261 | o_desc.wMaxPacketSize = | ||
262 | __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE); | ||
263 | |||
264 | dbg_desc.bDebugInEndpoint = i_desc.bEndpointAddress & 0x7f; | ||
265 | dbg_desc.bDebugOutEndpoint = o_desc.bEndpointAddress & 0x7f; | ||
266 | |||
267 | #ifdef CONFIG_USB_G_DBGP_SERIAL | ||
268 | dbgp.serial->in = dbgp.i_ep; | ||
269 | dbgp.serial->out = dbgp.o_ep; | ||
270 | |||
271 | dbgp.serial->in_desc = &i_desc; | ||
272 | dbgp.serial->out_desc = &o_desc; | ||
273 | |||
274 | if (gserial_setup(gadget, 1) < 0) { | ||
275 | stp = 3; | ||
276 | goto fail_3; | ||
277 | } | ||
278 | |||
279 | return 0; | ||
280 | |||
281 | fail_3: | ||
282 | dbgp.o_ep->driver_data = NULL; | ||
283 | #else | ||
284 | return 0; | ||
285 | #endif | ||
286 | fail_2: | ||
287 | dbgp.i_ep->driver_data = NULL; | ||
288 | fail_1: | ||
289 | dev_dbg(&dbgp.gadget->dev, "ep config: failure (%d)\n", stp); | ||
290 | return -ENODEV; | ||
291 | } | ||
292 | |||
293 | static int __init dbgp_bind(struct usb_gadget *gadget) | ||
294 | { | ||
295 | int err, stp; | ||
296 | |||
297 | dbgp.gadget = gadget; | ||
298 | |||
299 | dbgp.req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); | ||
300 | if (!dbgp.req) { | ||
301 | err = -ENOMEM; | ||
302 | stp = 1; | ||
303 | goto fail; | ||
304 | } | ||
305 | |||
306 | dbgp.req->buf = kmalloc(DBGP_REQ_EP0_LEN, GFP_KERNEL); | ||
307 | if (!dbgp.req->buf) { | ||
308 | err = -ENOMEM; | ||
309 | stp = 2; | ||
310 | goto fail; | ||
311 | } | ||
312 | |||
313 | dbgp.req->length = DBGP_REQ_EP0_LEN; | ||
314 | gadget->ep0->driver_data = gadget; | ||
315 | |||
316 | #ifdef CONFIG_USB_G_DBGP_SERIAL | ||
317 | dbgp.serial = kzalloc(sizeof(struct gserial), GFP_KERNEL); | ||
318 | if (!dbgp.serial) { | ||
319 | stp = 3; | ||
320 | err = -ENOMEM; | ||
321 | goto fail; | ||
322 | } | ||
323 | #endif | ||
324 | err = dbgp_configure_endpoints(gadget); | ||
325 | if (err < 0) { | ||
326 | stp = 4; | ||
327 | goto fail; | ||
328 | } | ||
329 | |||
330 | dev_dbg(&dbgp.gadget->dev, "bind: success\n"); | ||
331 | return 0; | ||
332 | |||
333 | fail: | ||
334 | dev_dbg(&gadget->dev, "bind: failure (%d:%d)\n", stp, err); | ||
335 | dbgp_unbind(gadget); | ||
336 | return err; | ||
337 | } | ||
338 | |||
339 | static void dbgp_setup_complete(struct usb_ep *ep, | ||
340 | struct usb_request *req) | ||
341 | { | ||
342 | dev_dbg(&dbgp.gadget->dev, "setup complete: %d, %d/%d\n", | ||
343 | req->status, req->actual, req->length); | ||
344 | } | ||
345 | |||
346 | static int dbgp_setup(struct usb_gadget *gadget, | ||
347 | const struct usb_ctrlrequest *ctrl) | ||
348 | { | ||
349 | struct usb_request *req = dbgp.req; | ||
350 | u8 request = ctrl->bRequest; | ||
351 | u16 value = le16_to_cpu(ctrl->wValue); | ||
352 | u16 length = le16_to_cpu(ctrl->wLength); | ||
353 | int err = 0; | ||
354 | void *data; | ||
355 | u16 len; | ||
356 | |||
357 | gadget->ep0->driver_data = gadget; | ||
358 | |||
359 | if (request == USB_REQ_GET_DESCRIPTOR) { | ||
360 | switch (value>>8) { | ||
361 | case USB_DT_DEVICE: | ||
362 | dev_dbg(&dbgp.gadget->dev, "setup: desc device\n"); | ||
363 | len = sizeof device_desc; | ||
364 | data = &device_desc; | ||
365 | break; | ||
366 | case USB_DT_DEBUG: | ||
367 | dev_dbg(&dbgp.gadget->dev, "setup: desc debug\n"); | ||
368 | len = sizeof dbg_desc; | ||
369 | data = &dbg_desc; | ||
370 | break; | ||
371 | default: | ||
372 | goto fail; | ||
373 | } | ||
374 | } else if (request == USB_REQ_SET_FEATURE && | ||
375 | value == USB_DEVICE_DEBUG_MODE) { | ||
376 | len = 0; | ||
377 | data = NULL; | ||
378 | dev_dbg(&dbgp.gadget->dev, "setup: feat debug\n"); | ||
379 | #ifdef CONFIG_USB_G_DBGP_PRINTK | ||
380 | err = dbgp_enable_ep(); | ||
381 | #else | ||
382 | err = gserial_connect(dbgp.serial, 0); | ||
383 | #endif | ||
384 | if (err < 0) | ||
385 | goto fail; | ||
386 | } else | ||
387 | goto fail; | ||
388 | |||
389 | if (len >= 0) { | ||
390 | req->length = min(length, len); | ||
391 | req->zero = len < req->length; | ||
392 | if (data && req->length) | ||
393 | memcpy(req->buf, data, req->length); | ||
394 | |||
395 | req->complete = dbgp_setup_complete; | ||
396 | return usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); | ||
397 | } | ||
398 | |||
399 | fail: | ||
400 | dev_dbg(&dbgp.gadget->dev, | ||
401 | "setup: failure req %x v %x\n", request, value); | ||
402 | return err; | ||
403 | } | ||
404 | |||
405 | static struct usb_gadget_driver dbgp_driver = { | ||
406 | .function = "dbgp", | ||
407 | .speed = USB_SPEED_HIGH, | ||
408 | .bind = dbgp_bind, | ||
409 | .unbind = dbgp_unbind, | ||
410 | .setup = dbgp_setup, | ||
411 | .disconnect = dbgp_disconnect, | ||
412 | .driver = { | ||
413 | .owner = THIS_MODULE, | ||
414 | .name = "dbgp" | ||
415 | }, | ||
416 | }; | ||
417 | |||
418 | static int __init dbgp_init(void) | ||
419 | { | ||
420 | return usb_gadget_register_driver(&dbgp_driver); | ||
421 | } | ||
422 | |||
423 | static void __exit dbgp_exit(void) | ||
424 | { | ||
425 | usb_gadget_unregister_driver(&dbgp_driver); | ||
426 | #ifdef CONFIG_USB_G_DBGP_SERIAL | ||
427 | gserial_cleanup(); | ||
428 | #endif | ||
429 | } | ||
430 | |||
431 | MODULE_AUTHOR("Stephane Duverger"); | ||
432 | MODULE_LICENSE("GPL"); | ||
433 | module_init(dbgp_init); | ||
434 | module_exit(dbgp_exit); | ||
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 4f9e578cde9d..dc6546248ed9 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -1542,7 +1542,7 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf) | |||
1542 | dum = hcd_to_dummy (hcd); | 1542 | dum = hcd_to_dummy (hcd); |
1543 | 1543 | ||
1544 | spin_lock_irqsave (&dum->lock, flags); | 1544 | spin_lock_irqsave (&dum->lock, flags); |
1545 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) | 1545 | if (!HCD_HW_ACCESSIBLE(hcd)) |
1546 | goto done; | 1546 | goto done; |
1547 | 1547 | ||
1548 | if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) { | 1548 | if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) { |
@@ -1588,7 +1588,7 @@ static int dummy_hub_control ( | |||
1588 | int retval = 0; | 1588 | int retval = 0; |
1589 | unsigned long flags; | 1589 | unsigned long flags; |
1590 | 1590 | ||
1591 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) | 1591 | if (!HCD_HW_ACCESSIBLE(hcd)) |
1592 | return -ETIMEDOUT; | 1592 | return -ETIMEDOUT; |
1593 | 1593 | ||
1594 | dum = hcd_to_dummy (hcd); | 1594 | dum = hcd_to_dummy (hcd); |
@@ -1739,7 +1739,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd) | |||
1739 | dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__); | 1739 | dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__); |
1740 | 1740 | ||
1741 | spin_lock_irq (&dum->lock); | 1741 | spin_lock_irq (&dum->lock); |
1742 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | 1742 | if (!HCD_HW_ACCESSIBLE(hcd)) { |
1743 | rc = -ESHUTDOWN; | 1743 | rc = -ESHUTDOWN; |
1744 | } else { | 1744 | } else { |
1745 | dum->rh_state = DUMMY_RH_RUNNING; | 1745 | dum->rh_state = DUMMY_RH_RUNNING; |
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 400f80372d93..114fa024c22c 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
@@ -237,7 +237,7 @@ static u8 hostaddr[ETH_ALEN]; | |||
237 | * the first one present. That's to make Microsoft's drivers happy, | 237 | * the first one present. That's to make Microsoft's drivers happy, |
238 | * and to follow DOCSIS 1.0 (cable modem standard). | 238 | * and to follow DOCSIS 1.0 (cable modem standard). |
239 | */ | 239 | */ |
240 | static int __init rndis_do_config(struct usb_configuration *c) | 240 | static int __ref rndis_do_config(struct usb_configuration *c) |
241 | { | 241 | { |
242 | /* FIXME alloc iConfiguration string, set it in c->strings */ | 242 | /* FIXME alloc iConfiguration string, set it in c->strings */ |
243 | 243 | ||
@@ -270,7 +270,7 @@ MODULE_PARM_DESC(use_eem, "use CDC EEM mode"); | |||
270 | /* | 270 | /* |
271 | * We _always_ have an ECM, CDC Subset, or EEM configuration. | 271 | * We _always_ have an ECM, CDC Subset, or EEM configuration. |
272 | */ | 272 | */ |
273 | static int __init eth_do_config(struct usb_configuration *c) | 273 | static int __ref eth_do_config(struct usb_configuration *c) |
274 | { | 274 | { |
275 | /* FIXME alloc iConfiguration string, set it in c->strings */ | 275 | /* FIXME alloc iConfiguration string, set it in c->strings */ |
276 | 276 | ||
@@ -297,7 +297,7 @@ static struct usb_configuration eth_config_driver = { | |||
297 | 297 | ||
298 | /*-------------------------------------------------------------------------*/ | 298 | /*-------------------------------------------------------------------------*/ |
299 | 299 | ||
300 | static int __init eth_bind(struct usb_composite_dev *cdev) | 300 | static int __ref eth_bind(struct usb_composite_dev *cdev) |
301 | { | 301 | { |
302 | int gcnum; | 302 | int gcnum; |
303 | struct usb_gadget *gadget = cdev->gadget; | 303 | struct usb_gadget *gadget = cdev->gadget; |
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 2aaa0f75c6cf..e4f595055208 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c | |||
@@ -714,9 +714,7 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value) | |||
714 | struct ffs_function *func = ffs->func; | 714 | struct ffs_function *func = ffs->func; |
715 | ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV; | 715 | ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV; |
716 | } else if (gadget->ops->ioctl) { | 716 | } else if (gadget->ops->ioctl) { |
717 | lock_kernel(); | ||
718 | ret = gadget->ops->ioctl(gadget, code, value); | 717 | ret = gadget->ops->ioctl(gadget, code, value); |
719 | unlock_kernel(); | ||
720 | } else { | 718 | } else { |
721 | ret = -ENOTTY; | 719 | ret = -ENOTTY; |
722 | } | 720 | } |
@@ -1377,7 +1375,8 @@ static void ffs_data_reset(struct ffs_data *ffs) | |||
1377 | 1375 | ||
1378 | static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) | 1376 | static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) |
1379 | { | 1377 | { |
1380 | unsigned i, count; | 1378 | struct usb_gadget_strings **lang; |
1379 | int first_id; | ||
1381 | 1380 | ||
1382 | ENTER(); | 1381 | ENTER(); |
1383 | 1382 | ||
@@ -1385,7 +1384,9 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) | |||
1385 | || test_and_set_bit(FFS_FL_BOUND, &ffs->flags))) | 1384 | || test_and_set_bit(FFS_FL_BOUND, &ffs->flags))) |
1386 | return -EBADFD; | 1385 | return -EBADFD; |
1387 | 1386 | ||
1388 | ffs_data_get(ffs); | 1387 | first_id = usb_string_ids_n(cdev, ffs->strings_count); |
1388 | if (unlikely(first_id < 0)) | ||
1389 | return first_id; | ||
1389 | 1390 | ||
1390 | ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); | 1391 | ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); |
1391 | if (unlikely(!ffs->ep0req)) | 1392 | if (unlikely(!ffs->ep0req)) |
@@ -1393,25 +1394,16 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) | |||
1393 | ffs->ep0req->complete = ffs_ep0_complete; | 1394 | ffs->ep0req->complete = ffs_ep0_complete; |
1394 | ffs->ep0req->context = ffs; | 1395 | ffs->ep0req->context = ffs; |
1395 | 1396 | ||
1396 | /* Get strings identifiers */ | 1397 | lang = ffs->stringtabs; |
1397 | for (count = ffs->strings_count, i = 0; i < count; ++i) { | 1398 | for (lang = ffs->stringtabs; *lang; ++lang) { |
1398 | struct usb_gadget_strings **lang; | 1399 | struct usb_string *str = (*lang)->strings; |
1399 | 1400 | int id = first_id; | |
1400 | int id = usb_string_id(cdev); | 1401 | for (; str->s; ++id, ++str) |
1401 | if (unlikely(id < 0)) { | 1402 | str->id = id; |
1402 | usb_ep_free_request(cdev->gadget->ep0, ffs->ep0req); | ||
1403 | ffs->ep0req = NULL; | ||
1404 | return id; | ||
1405 | } | ||
1406 | |||
1407 | lang = ffs->stringtabs; | ||
1408 | do { | ||
1409 | (*lang)->strings[i].id = id; | ||
1410 | ++lang; | ||
1411 | } while (*lang); | ||
1412 | } | 1403 | } |
1413 | 1404 | ||
1414 | ffs->gadget = cdev->gadget; | 1405 | ffs->gadget = cdev->gadget; |
1406 | ffs_data_get(ffs); | ||
1415 | return 0; | 1407 | return 0; |
1416 | } | 1408 | } |
1417 | 1409 | ||
@@ -1480,9 +1472,9 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) | |||
1480 | } | 1472 | } |
1481 | 1473 | ||
1482 | 1474 | ||
1483 | static int functionfs_add(struct usb_composite_dev *cdev, | 1475 | static int functionfs_bind_config(struct usb_composite_dev *cdev, |
1484 | struct usb_configuration *c, | 1476 | struct usb_configuration *c, |
1485 | struct ffs_data *ffs) | 1477 | struct ffs_data *ffs) |
1486 | { | 1478 | { |
1487 | struct ffs_function *func; | 1479 | struct ffs_function *func; |
1488 | int ret; | 1480 | int ret; |
diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c index 1e00ff9866af..53e120208e99 100644 --- a/drivers/usb/gadget/f_hid.c +++ b/drivers/usb/gadget/f_hid.c | |||
@@ -142,7 +142,7 @@ static struct usb_descriptor_header *hidg_fs_descriptors[] = { | |||
142 | static ssize_t f_hidg_read(struct file *file, char __user *buffer, | 142 | static ssize_t f_hidg_read(struct file *file, char __user *buffer, |
143 | size_t count, loff_t *ptr) | 143 | size_t count, loff_t *ptr) |
144 | { | 144 | { |
145 | struct f_hidg *hidg = (struct f_hidg *)file->private_data; | 145 | struct f_hidg *hidg = file->private_data; |
146 | char *tmp_buff = NULL; | 146 | char *tmp_buff = NULL; |
147 | unsigned long flags; | 147 | unsigned long flags; |
148 | 148 | ||
@@ -200,7 +200,7 @@ static void f_hidg_req_complete(struct usb_ep *ep, struct usb_request *req) | |||
200 | static ssize_t f_hidg_write(struct file *file, const char __user *buffer, | 200 | static ssize_t f_hidg_write(struct file *file, const char __user *buffer, |
201 | size_t count, loff_t *offp) | 201 | size_t count, loff_t *offp) |
202 | { | 202 | { |
203 | struct f_hidg *hidg = (struct f_hidg *)file->private_data; | 203 | struct f_hidg *hidg = file->private_data; |
204 | ssize_t status = -ENOMEM; | 204 | ssize_t status = -ENOMEM; |
205 | 205 | ||
206 | if (!access_ok(VERIFY_READ, buffer, count)) | 206 | if (!access_ok(VERIFY_READ, buffer, count)) |
@@ -257,7 +257,7 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, | |||
257 | 257 | ||
258 | static unsigned int f_hidg_poll(struct file *file, poll_table *wait) | 258 | static unsigned int f_hidg_poll(struct file *file, poll_table *wait) |
259 | { | 259 | { |
260 | struct f_hidg *hidg = (struct f_hidg *)file->private_data; | 260 | struct f_hidg *hidg = file->private_data; |
261 | unsigned int ret = 0; | 261 | unsigned int ret = 0; |
262 | 262 | ||
263 | poll_wait(file, &hidg->read_queue, wait); | 263 | poll_wait(file, &hidg->read_queue, wait); |
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index e91d1b16d9be..43225879c3cd 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c | |||
@@ -324,7 +324,7 @@ static void loopback_disable(struct usb_function *f) | |||
324 | 324 | ||
325 | /*-------------------------------------------------------------------------*/ | 325 | /*-------------------------------------------------------------------------*/ |
326 | 326 | ||
327 | static int __init loopback_bind_config(struct usb_configuration *c) | 327 | static int __ref loopback_bind_config(struct usb_configuration *c) |
328 | { | 328 | { |
329 | struct f_loopback *loop; | 329 | struct f_loopback *loop; |
330 | int status; | 330 | int status; |
@@ -346,7 +346,7 @@ static int __init loopback_bind_config(struct usb_configuration *c) | |||
346 | return status; | 346 | return status; |
347 | } | 347 | } |
348 | 348 | ||
349 | static struct usb_configuration loopback_driver = { | 349 | static struct usb_configuration loopback_driver = { |
350 | .label = "loopback", | 350 | .label = "loopback", |
351 | .strings = loopback_strings, | 351 | .strings = loopback_strings, |
352 | .bind = loopback_bind_config, | 352 | .bind = loopback_bind_config, |
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 4ce899c9b165..32cce029f65c 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c | |||
@@ -316,6 +316,27 @@ static const char fsg_string_interface[] = "Mass Storage"; | |||
316 | /*-------------------------------------------------------------------------*/ | 316 | /*-------------------------------------------------------------------------*/ |
317 | 317 | ||
318 | struct fsg_dev; | 318 | struct fsg_dev; |
319 | struct fsg_common; | ||
320 | |||
321 | /* FSF callback functions */ | ||
322 | struct fsg_operations { | ||
323 | /* Callback function to call when thread exits. If no | ||
324 | * callback is set or it returns value lower then zero MSF | ||
325 | * will force eject all LUNs it operates on (including those | ||
326 | * marked as non-removable or with prevent_medium_removal flag | ||
327 | * set). */ | ||
328 | int (*thread_exits)(struct fsg_common *common); | ||
329 | |||
330 | /* Called prior to ejection. Negative return means error, | ||
331 | * zero means to continue with ejection, positive means not to | ||
332 | * eject. */ | ||
333 | int (*pre_eject)(struct fsg_common *common, | ||
334 | struct fsg_lun *lun, int num); | ||
335 | /* Called after ejection. Negative return means error, zero | ||
336 | * or positive is just a success. */ | ||
337 | int (*post_eject)(struct fsg_common *common, | ||
338 | struct fsg_lun *lun, int num); | ||
339 | }; | ||
319 | 340 | ||
320 | 341 | ||
321 | /* Data shared by all the FSG instances. */ | 342 | /* Data shared by all the FSG instances. */ |
@@ -333,7 +354,6 @@ struct fsg_common { | |||
333 | struct usb_ep *ep0; /* Copy of gadget->ep0 */ | 354 | struct usb_ep *ep0; /* Copy of gadget->ep0 */ |
334 | struct usb_request *ep0req; /* Copy of cdev->req */ | 355 | struct usb_request *ep0req; /* Copy of cdev->req */ |
335 | unsigned int ep0_req_tag; | 356 | unsigned int ep0_req_tag; |
336 | const char *ep0req_name; | ||
337 | 357 | ||
338 | struct fsg_buffhd *next_buffhd_to_fill; | 358 | struct fsg_buffhd *next_buffhd_to_fill; |
339 | struct fsg_buffhd *next_buffhd_to_drain; | 359 | struct fsg_buffhd *next_buffhd_to_drain; |
@@ -369,8 +389,8 @@ struct fsg_common { | |||
369 | struct completion thread_notifier; | 389 | struct completion thread_notifier; |
370 | struct task_struct *thread_task; | 390 | struct task_struct *thread_task; |
371 | 391 | ||
372 | /* Callback function to call when thread exits. */ | 392 | /* Callback functions. */ |
373 | int (*thread_exits)(struct fsg_common *common); | 393 | const struct fsg_operations *ops; |
374 | /* Gadget's private data. */ | 394 | /* Gadget's private data. */ |
375 | void *private_data; | 395 | void *private_data; |
376 | 396 | ||
@@ -394,12 +414,8 @@ struct fsg_config { | |||
394 | const char *lun_name_format; | 414 | const char *lun_name_format; |
395 | const char *thread_name; | 415 | const char *thread_name; |
396 | 416 | ||
397 | /* Callback function to call when thread exits. If no | 417 | /* Callback functions. */ |
398 | * callback is set or it returns value lower then zero MSF | 418 | const struct fsg_operations *ops; |
399 | * will force eject all LUNs it operates on (including those | ||
400 | * marked as non-removable or with prevent_medium_removal flag | ||
401 | * set). */ | ||
402 | int (*thread_exits)(struct fsg_common *common); | ||
403 | /* Gadget's private data. */ | 419 | /* Gadget's private data. */ |
404 | void *private_data; | 420 | void *private_data; |
405 | 421 | ||
@@ -435,6 +451,7 @@ static inline int __fsg_is_set(struct fsg_common *common, | |||
435 | if (common->fsg) | 451 | if (common->fsg) |
436 | return 1; | 452 | return 1; |
437 | ERROR(common, "common->fsg is NULL in %s at %u\n", func, line); | 453 | ERROR(common, "common->fsg is NULL in %s at %u\n", func, line); |
454 | WARN_ON(1); | ||
438 | return 0; | 455 | return 0; |
439 | } | 456 | } |
440 | 457 | ||
@@ -623,8 +640,6 @@ static int fsg_setup(struct usb_function *f, | |||
623 | 640 | ||
624 | /* Respond with data/status */ | 641 | /* Respond with data/status */ |
625 | req->length = min((u16)1, w_length); | 642 | req->length = min((u16)1, w_length); |
626 | fsg->common->ep0req_name = | ||
627 | ctrl->bRequestType & USB_DIR_IN ? "ep0-in" : "ep0-out"; | ||
628 | return ep0_queue(fsg->common); | 643 | return ep0_queue(fsg->common); |
629 | } | 644 | } |
630 | 645 | ||
@@ -1395,43 +1410,55 @@ static int do_start_stop(struct fsg_common *common) | |||
1395 | } else if (!curlun->removable) { | 1410 | } else if (!curlun->removable) { |
1396 | curlun->sense_data = SS_INVALID_COMMAND; | 1411 | curlun->sense_data = SS_INVALID_COMMAND; |
1397 | return -EINVAL; | 1412 | return -EINVAL; |
1398 | } | 1413 | } else if ((common->cmnd[1] & ~0x01) != 0 || /* Mask away Immed */ |
1399 | 1414 | (common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */ | |
1400 | loej = common->cmnd[4] & 0x02; | ||
1401 | start = common->cmnd[4] & 0x01; | ||
1402 | |||
1403 | /* eject code from file_storage.c:do_start_stop() */ | ||
1404 | |||
1405 | if ((common->cmnd[1] & ~0x01) != 0 || /* Mask away Immed */ | ||
1406 | (common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */ | ||
1407 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | 1415 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; |
1408 | return -EINVAL; | 1416 | return -EINVAL; |
1409 | } | 1417 | } |
1410 | 1418 | ||
1411 | if (!start) { | 1419 | loej = common->cmnd[4] & 0x02; |
1412 | /* Are we allowed to unload the media? */ | 1420 | start = common->cmnd[4] & 0x01; |
1413 | if (curlun->prevent_medium_removal) { | ||
1414 | LDBG(curlun, "unload attempt prevented\n"); | ||
1415 | curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED; | ||
1416 | return -EINVAL; | ||
1417 | } | ||
1418 | if (loej) { /* Simulate an unload/eject */ | ||
1419 | up_read(&common->filesem); | ||
1420 | down_write(&common->filesem); | ||
1421 | fsg_lun_close(curlun); | ||
1422 | up_write(&common->filesem); | ||
1423 | down_read(&common->filesem); | ||
1424 | } | ||
1425 | } else { | ||
1426 | 1421 | ||
1427 | /* Our emulation doesn't support mounting; the medium is | 1422 | /* Our emulation doesn't support mounting; the medium is |
1428 | * available for use as soon as it is loaded. */ | 1423 | * available for use as soon as it is loaded. */ |
1424 | if (start) { | ||
1429 | if (!fsg_lun_is_open(curlun)) { | 1425 | if (!fsg_lun_is_open(curlun)) { |
1430 | curlun->sense_data = SS_MEDIUM_NOT_PRESENT; | 1426 | curlun->sense_data = SS_MEDIUM_NOT_PRESENT; |
1431 | return -EINVAL; | 1427 | return -EINVAL; |
1432 | } | 1428 | } |
1429 | return 0; | ||
1433 | } | 1430 | } |
1434 | return 0; | 1431 | |
1432 | /* Are we allowed to unload the media? */ | ||
1433 | if (curlun->prevent_medium_removal) { | ||
1434 | LDBG(curlun, "unload attempt prevented\n"); | ||
1435 | curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED; | ||
1436 | return -EINVAL; | ||
1437 | } | ||
1438 | |||
1439 | if (!loej) | ||
1440 | return 0; | ||
1441 | |||
1442 | /* Simulate an unload/eject */ | ||
1443 | if (common->ops && common->ops->pre_eject) { | ||
1444 | int r = common->ops->pre_eject(common, curlun, | ||
1445 | curlun - common->luns); | ||
1446 | if (unlikely(r < 0)) | ||
1447 | return r; | ||
1448 | else if (r) | ||
1449 | return 0; | ||
1450 | } | ||
1451 | |||
1452 | up_read(&common->filesem); | ||
1453 | down_write(&common->filesem); | ||
1454 | fsg_lun_close(curlun); | ||
1455 | up_write(&common->filesem); | ||
1456 | down_read(&common->filesem); | ||
1457 | |||
1458 | return common->ops && common->ops->post_eject | ||
1459 | ? min(0, common->ops->post_eject(common, curlun, | ||
1460 | curlun - common->luns)) | ||
1461 | : 0; | ||
1435 | } | 1462 | } |
1436 | 1463 | ||
1437 | 1464 | ||
@@ -2610,7 +2637,8 @@ static int fsg_main_thread(void *common_) | |||
2610 | common->thread_task = NULL; | 2637 | common->thread_task = NULL; |
2611 | spin_unlock_irq(&common->lock); | 2638 | spin_unlock_irq(&common->lock); |
2612 | 2639 | ||
2613 | if (!common->thread_exits || common->thread_exits(common) < 0) { | 2640 | if (!common->ops || !common->ops->thread_exits |
2641 | || common->ops->thread_exits(common) < 0) { | ||
2614 | struct fsg_lun *curlun = common->luns; | 2642 | struct fsg_lun *curlun = common->luns; |
2615 | unsigned i = common->nluns; | 2643 | unsigned i = common->nluns; |
2616 | 2644 | ||
@@ -2686,6 +2714,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, | |||
2686 | common->free_storage_on_release = 0; | 2714 | common->free_storage_on_release = 0; |
2687 | } | 2715 | } |
2688 | 2716 | ||
2717 | common->ops = cfg->ops; | ||
2689 | common->private_data = cfg->private_data; | 2718 | common->private_data = cfg->private_data; |
2690 | 2719 | ||
2691 | common->gadget = gadget; | 2720 | common->gadget = gadget; |
@@ -2807,7 +2836,6 @@ buffhds_first_it: | |||
2807 | 2836 | ||
2808 | 2837 | ||
2809 | /* Tell the thread to start working */ | 2838 | /* Tell the thread to start working */ |
2810 | common->thread_exits = cfg->thread_exits; | ||
2811 | common->thread_task = | 2839 | common->thread_task = |
2812 | kthread_create(fsg_main_thread, common, | 2840 | kthread_create(fsg_main_thread, common, |
2813 | OR(cfg->thread_name, "file-storage")); | 2841 | OR(cfg->thread_name, "file-storage")); |
@@ -2990,9 +3018,9 @@ static struct usb_gadget_strings *fsg_strings_array[] = { | |||
2990 | NULL, | 3018 | NULL, |
2991 | }; | 3019 | }; |
2992 | 3020 | ||
2993 | static int fsg_add(struct usb_composite_dev *cdev, | 3021 | static int fsg_bind_config(struct usb_composite_dev *cdev, |
2994 | struct usb_configuration *c, | 3022 | struct usb_configuration *c, |
2995 | struct fsg_common *common) | 3023 | struct fsg_common *common) |
2996 | { | 3024 | { |
2997 | struct fsg_dev *fsg; | 3025 | struct fsg_dev *fsg; |
2998 | int rc; | 3026 | int rc; |
@@ -3024,6 +3052,13 @@ static int fsg_add(struct usb_composite_dev *cdev, | |||
3024 | return rc; | 3052 | return rc; |
3025 | } | 3053 | } |
3026 | 3054 | ||
3055 | static inline int __deprecated __maybe_unused | ||
3056 | fsg_add(struct usb_composite_dev *cdev, | ||
3057 | struct usb_configuration *c, | ||
3058 | struct fsg_common *common) | ||
3059 | { | ||
3060 | return fsg_bind_config(cdev, c, common); | ||
3061 | } | ||
3027 | 3062 | ||
3028 | 3063 | ||
3029 | /************************* Module parameters *************************/ | 3064 | /************************* Module parameters *************************/ |
@@ -3096,8 +3131,8 @@ fsg_config_from_params(struct fsg_config *cfg, | |||
3096 | cfg->product_name = 0; | 3131 | cfg->product_name = 0; |
3097 | cfg->release = 0xffff; | 3132 | cfg->release = 0xffff; |
3098 | 3133 | ||
3099 | cfg->thread_exits = 0; | 3134 | cfg->ops = NULL; |
3100 | cfg->private_data = 0; | 3135 | cfg->private_data = NULL; |
3101 | 3136 | ||
3102 | /* Finalise */ | 3137 | /* Finalise */ |
3103 | cfg->can_stall = params->stall; | 3138 | cfg->can_stall = params->stall; |
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 6d3cc443d914..685d768f336e 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c | |||
@@ -404,7 +404,7 @@ static void sourcesink_disable(struct usb_function *f) | |||
404 | 404 | ||
405 | /*-------------------------------------------------------------------------*/ | 405 | /*-------------------------------------------------------------------------*/ |
406 | 406 | ||
407 | static int __init sourcesink_bind_config(struct usb_configuration *c) | 407 | static int __ref sourcesink_bind_config(struct usb_configuration *c) |
408 | { | 408 | { |
409 | struct f_sourcesink *ss; | 409 | struct f_sourcesink *ss; |
410 | int status; | 410 | int status; |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index b49d86e3e45b..a857b7ac238c 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -56,7 +56,7 @@ | |||
56 | * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03), | 56 | * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03), |
57 | * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by | 57 | * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by |
58 | * the optional "protocol" module parameter. In addition, the default | 58 | * the optional "protocol" module parameter. In addition, the default |
59 | * Vendor ID, Product ID, and release number can be overridden. | 59 | * Vendor ID, Product ID, release number and serial number can be overridden. |
60 | * | 60 | * |
61 | * There is support for multiple logical units (LUNs), each of which has | 61 | * There is support for multiple logical units (LUNs), each of which has |
62 | * its own backing file. The number of LUNs can be set using the optional | 62 | * its own backing file. The number of LUNs can be set using the optional |
@@ -93,6 +93,8 @@ | |||
93 | * removable Default false, boolean for removable media | 93 | * removable Default false, boolean for removable media |
94 | * luns=N Default N = number of filenames, number of | 94 | * luns=N Default N = number of filenames, number of |
95 | * LUNs to support | 95 | * LUNs to support |
96 | * nofua=b[,b...] Default false, booleans for ignore FUA flag | ||
97 | * in SCSI WRITE(10,12) commands | ||
96 | * stall Default determined according to the type of | 98 | * stall Default determined according to the type of |
97 | * USB device controller (usually true), | 99 | * USB device controller (usually true), |
98 | * boolean to permit the driver to halt | 100 | * boolean to permit the driver to halt |
@@ -106,17 +108,18 @@ | |||
106 | * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID | 108 | * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID |
107 | * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID | 109 | * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID |
108 | * release=0xRRRR Override the USB release number (bcdDevice) | 110 | * release=0xRRRR Override the USB release number (bcdDevice) |
111 | * serial=HHHH... Override serial number (string of hex chars) | ||
109 | * buflen=N Default N=16384, buffer size used (will be | 112 | * buflen=N Default N=16384, buffer size used (will be |
110 | * rounded down to a multiple of | 113 | * rounded down to a multiple of |
111 | * PAGE_CACHE_SIZE) | 114 | * PAGE_CACHE_SIZE) |
112 | * | 115 | * |
113 | * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", | 116 | * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", |
114 | * "removable", "luns", "stall", and "cdrom" options are available; default | 117 | * "removable", "luns", "nofua", "stall", and "cdrom" options are available; |
115 | * values are used for everything else. | 118 | * default values are used for everything else. |
116 | * | 119 | * |
117 | * The pathnames of the backing files and the ro settings are available in | 120 | * The pathnames of the backing files and the ro settings are available in |
118 | * the attribute files "file" and "ro" in the lun<n> subdirectory of the | 121 | * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of |
119 | * gadget's sysfs directory. If the "removable" option is set, writing to | 122 | * the gadget's sysfs directory. If the "removable" option is set, writing to |
120 | * these files will simulate ejecting/loading the medium (writing an empty | 123 | * these files will simulate ejecting/loading the medium (writing an empty |
121 | * line means eject) and adjusting a write-enable tab. Changes to the ro | 124 | * line means eject) and adjusting a write-enable tab. Changes to the ro |
122 | * setting are not allowed when the medium is loaded or if CD-ROM emulation | 125 | * setting are not allowed when the medium is loaded or if CD-ROM emulation |
@@ -270,6 +273,8 @@ | |||
270 | 273 | ||
271 | #define DRIVER_DESC "File-backed Storage Gadget" | 274 | #define DRIVER_DESC "File-backed Storage Gadget" |
272 | #define DRIVER_NAME "g_file_storage" | 275 | #define DRIVER_NAME "g_file_storage" |
276 | /* DRIVER_VERSION must be at least 6 characters long, as it is used | ||
277 | * to generate a fallback serial number. */ | ||
273 | #define DRIVER_VERSION "20 November 2008" | 278 | #define DRIVER_VERSION "20 November 2008" |
274 | 279 | ||
275 | static char fsg_string_manufacturer[64]; | 280 | static char fsg_string_manufacturer[64]; |
@@ -301,8 +306,10 @@ MODULE_LICENSE("Dual BSD/GPL"); | |||
301 | static struct { | 306 | static struct { |
302 | char *file[FSG_MAX_LUNS]; | 307 | char *file[FSG_MAX_LUNS]; |
303 | int ro[FSG_MAX_LUNS]; | 308 | int ro[FSG_MAX_LUNS]; |
309 | int nofua[FSG_MAX_LUNS]; | ||
304 | unsigned int num_filenames; | 310 | unsigned int num_filenames; |
305 | unsigned int num_ros; | 311 | unsigned int num_ros; |
312 | unsigned int num_nofuas; | ||
306 | unsigned int nluns; | 313 | unsigned int nluns; |
307 | 314 | ||
308 | int removable; | 315 | int removable; |
@@ -314,6 +321,7 @@ static struct { | |||
314 | unsigned short vendor; | 321 | unsigned short vendor; |
315 | unsigned short product; | 322 | unsigned short product; |
316 | unsigned short release; | 323 | unsigned short release; |
324 | char *serial; | ||
317 | unsigned int buflen; | 325 | unsigned int buflen; |
318 | 326 | ||
319 | int transport_type; | 327 | int transport_type; |
@@ -341,6 +349,10 @@ MODULE_PARM_DESC(file, "names of backing files or devices"); | |||
341 | module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO); | 349 | module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO); |
342 | MODULE_PARM_DESC(ro, "true to force read-only"); | 350 | MODULE_PARM_DESC(ro, "true to force read-only"); |
343 | 351 | ||
352 | module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas, | ||
353 | S_IRUGO); | ||
354 | MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit"); | ||
355 | |||
344 | module_param_named(luns, mod_data.nluns, uint, S_IRUGO); | 356 | module_param_named(luns, mod_data.nluns, uint, S_IRUGO); |
345 | MODULE_PARM_DESC(luns, "number of LUNs"); | 357 | MODULE_PARM_DESC(luns, "number of LUNs"); |
346 | 358 | ||
@@ -353,6 +365,8 @@ MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); | |||
353 | module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO); | 365 | module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO); |
354 | MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk"); | 366 | MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk"); |
355 | 367 | ||
368 | module_param_named(serial, mod_data.serial, charp, S_IRUGO); | ||
369 | MODULE_PARM_DESC(serial, "USB serial number"); | ||
356 | 370 | ||
357 | /* In the non-TEST version, only the module parameters listed above | 371 | /* In the non-TEST version, only the module parameters listed above |
358 | * are available. */ | 372 | * are available. */ |
@@ -1272,7 +1286,8 @@ static int do_write(struct fsg_dev *fsg) | |||
1272 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | 1286 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; |
1273 | return -EINVAL; | 1287 | return -EINVAL; |
1274 | } | 1288 | } |
1275 | if (fsg->cmnd[1] & 0x08) { // FUA | 1289 | /* FUA */ |
1290 | if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) { | ||
1276 | spin_lock(&curlun->filp->f_lock); | 1291 | spin_lock(&curlun->filp->f_lock); |
1277 | curlun->filp->f_flags |= O_DSYNC; | 1292 | curlun->filp->f_flags |= O_DSYNC; |
1278 | spin_unlock(&curlun->filp->f_lock); | 1293 | spin_unlock(&curlun->filp->f_lock); |
@@ -3126,6 +3141,7 @@ static int fsg_main_thread(void *fsg_) | |||
3126 | 3141 | ||
3127 | /* The write permissions and store_xxx pointers are set in fsg_bind() */ | 3142 | /* The write permissions and store_xxx pointers are set in fsg_bind() */ |
3128 | static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL); | 3143 | static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL); |
3144 | static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL); | ||
3129 | static DEVICE_ATTR(file, 0444, fsg_show_file, NULL); | 3145 | static DEVICE_ATTR(file, 0444, fsg_show_file, NULL); |
3130 | 3146 | ||
3131 | 3147 | ||
@@ -3197,6 +3213,7 @@ static int __init check_parameters(struct fsg_dev *fsg) | |||
3197 | { | 3213 | { |
3198 | int prot; | 3214 | int prot; |
3199 | int gcnum; | 3215 | int gcnum; |
3216 | int i; | ||
3200 | 3217 | ||
3201 | /* Store the default values */ | 3218 | /* Store the default values */ |
3202 | mod_data.transport_type = USB_PR_BULK; | 3219 | mod_data.transport_type = USB_PR_BULK; |
@@ -3272,13 +3289,65 @@ static int __init check_parameters(struct fsg_dev *fsg) | |||
3272 | ERROR(fsg, "invalid buflen\n"); | 3289 | ERROR(fsg, "invalid buflen\n"); |
3273 | return -ETOOSMALL; | 3290 | return -ETOOSMALL; |
3274 | } | 3291 | } |
3292 | |||
3275 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ | 3293 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ |
3276 | 3294 | ||
3295 | /* Serial string handling. | ||
3296 | * On a real device, the serial string would be loaded | ||
3297 | * from permanent storage. */ | ||
3298 | if (mod_data.serial) { | ||
3299 | const char *ch; | ||
3300 | unsigned len = 0; | ||
3301 | |||
3302 | /* Sanity check : | ||
3303 | * The CB[I] specification limits the serial string to | ||
3304 | * 12 uppercase hexadecimal characters. | ||
3305 | * BBB need at least 12 uppercase hexadecimal characters, | ||
3306 | * with a maximum of 126. */ | ||
3307 | for (ch = mod_data.serial; *ch; ++ch) { | ||
3308 | ++len; | ||
3309 | if ((*ch < '0' || *ch > '9') && | ||
3310 | (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */ | ||
3311 | WARNING(fsg, | ||
3312 | "Invalid serial string character: %c; " | ||
3313 | "Failing back to default\n", | ||
3314 | *ch); | ||
3315 | goto fill_serial; | ||
3316 | } | ||
3317 | } | ||
3318 | if (len > 126 || | ||
3319 | (mod_data.transport_type == USB_PR_BULK && len < 12) || | ||
3320 | (mod_data.transport_type != USB_PR_BULK && len > 12)) { | ||
3321 | WARNING(fsg, | ||
3322 | "Invalid serial string length; " | ||
3323 | "Failing back to default\n"); | ||
3324 | goto fill_serial; | ||
3325 | } | ||
3326 | fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial; | ||
3327 | } else { | ||
3328 | WARNING(fsg, | ||
3329 | "Userspace failed to provide serial number; " | ||
3330 | "Failing back to default\n"); | ||
3331 | fill_serial: | ||
3332 | /* Serial number not specified or invalid, make our own. | ||
3333 | * We just encode it from the driver version string, | ||
3334 | * 12 characters to comply with both CB[I] and BBB spec. | ||
3335 | * Warning : Two devices running the same kernel will have | ||
3336 | * the same fallback serial number. */ | ||
3337 | for (i = 0; i < 12; i += 2) { | ||
3338 | unsigned char c = DRIVER_VERSION[i / 2]; | ||
3339 | |||
3340 | if (!c) | ||
3341 | break; | ||
3342 | sprintf(&fsg_string_serial[i], "%02X", c); | ||
3343 | } | ||
3344 | } | ||
3345 | |||
3277 | return 0; | 3346 | return 0; |
3278 | } | 3347 | } |
3279 | 3348 | ||
3280 | 3349 | ||
3281 | static int __init fsg_bind(struct usb_gadget *gadget) | 3350 | static int __ref fsg_bind(struct usb_gadget *gadget) |
3282 | { | 3351 | { |
3283 | struct fsg_dev *fsg = the_fsg; | 3352 | struct fsg_dev *fsg = the_fsg; |
3284 | int rc; | 3353 | int rc; |
@@ -3305,6 +3374,10 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3305 | } | 3374 | } |
3306 | } | 3375 | } |
3307 | 3376 | ||
3377 | /* Only for removable media? */ | ||
3378 | dev_attr_nofua.attr.mode = 0644; | ||
3379 | dev_attr_nofua.store = fsg_store_nofua; | ||
3380 | |||
3308 | /* Find out how many LUNs there should be */ | 3381 | /* Find out how many LUNs there should be */ |
3309 | i = mod_data.nluns; | 3382 | i = mod_data.nluns; |
3310 | if (i == 0) | 3383 | if (i == 0) |
@@ -3330,6 +3403,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3330 | curlun->ro = mod_data.cdrom || mod_data.ro[i]; | 3403 | curlun->ro = mod_data.cdrom || mod_data.ro[i]; |
3331 | curlun->initially_ro = curlun->ro; | 3404 | curlun->initially_ro = curlun->ro; |
3332 | curlun->removable = mod_data.removable; | 3405 | curlun->removable = mod_data.removable; |
3406 | curlun->nofua = mod_data.nofua[i]; | ||
3333 | curlun->dev.release = lun_release; | 3407 | curlun->dev.release = lun_release; |
3334 | curlun->dev.parent = &gadget->dev; | 3408 | curlun->dev.parent = &gadget->dev; |
3335 | curlun->dev.driver = &fsg_driver.driver; | 3409 | curlun->dev.driver = &fsg_driver.driver; |
@@ -3344,6 +3418,8 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3344 | if ((rc = device_create_file(&curlun->dev, | 3418 | if ((rc = device_create_file(&curlun->dev, |
3345 | &dev_attr_ro)) != 0 || | 3419 | &dev_attr_ro)) != 0 || |
3346 | (rc = device_create_file(&curlun->dev, | 3420 | (rc = device_create_file(&curlun->dev, |
3421 | &dev_attr_nofua)) != 0 || | ||
3422 | (rc = device_create_file(&curlun->dev, | ||
3347 | &dev_attr_file)) != 0) { | 3423 | &dev_attr_file)) != 0) { |
3348 | device_unregister(&curlun->dev); | 3424 | device_unregister(&curlun->dev); |
3349 | goto out; | 3425 | goto out; |
@@ -3447,16 +3523,6 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3447 | init_utsname()->sysname, init_utsname()->release, | 3523 | init_utsname()->sysname, init_utsname()->release, |
3448 | gadget->name); | 3524 | gadget->name); |
3449 | 3525 | ||
3450 | /* On a real device, serial[] would be loaded from permanent | ||
3451 | * storage. We just encode it from the driver version string. */ | ||
3452 | for (i = 0; i < sizeof fsg_string_serial - 2; i += 2) { | ||
3453 | unsigned char c = DRIVER_VERSION[i / 2]; | ||
3454 | |||
3455 | if (!c) | ||
3456 | break; | ||
3457 | sprintf(&fsg_string_serial[i], "%02X", c); | ||
3458 | } | ||
3459 | |||
3460 | fsg->thread_task = kthread_create(fsg_main_thread, fsg, | 3526 | fsg->thread_task = kthread_create(fsg_main_thread, fsg, |
3461 | "file-storage-gadget"); | 3527 | "file-storage-gadget"); |
3462 | if (IS_ERR(fsg->thread_task)) { | 3528 | if (IS_ERR(fsg->thread_task)) { |
@@ -3478,8 +3544,8 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3478 | if (IS_ERR(p)) | 3544 | if (IS_ERR(p)) |
3479 | p = NULL; | 3545 | p = NULL; |
3480 | } | 3546 | } |
3481 | LINFO(curlun, "ro=%d, file: %s\n", | 3547 | LINFO(curlun, "ro=%d, nofua=%d, file: %s\n", |
3482 | curlun->ro, (p ? p : "(error)")); | 3548 | curlun->ro, curlun->nofua, (p ? p : "(error)")); |
3483 | } | 3549 | } |
3484 | } | 3550 | } |
3485 | kfree(pathbuf); | 3551 | kfree(pathbuf); |
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index d1af253a9105..a9474f8d5325 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c | |||
@@ -32,12 +32,13 @@ | |||
32 | # include "u_ether.c" | 32 | # include "u_ether.c" |
33 | 33 | ||
34 | static u8 gfs_hostaddr[ETH_ALEN]; | 34 | static u8 gfs_hostaddr[ETH_ALEN]; |
35 | #else | 35 | # ifdef CONFIG_USB_FUNCTIONFS_ETH |
36 | # if !defined CONFIG_USB_FUNCTIONFS_GENERIC | 36 | static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); |
37 | # define CONFIG_USB_FUNCTIONFS_GENERIC | ||
38 | # endif | 37 | # endif |
38 | #else | ||
39 | # define gether_cleanup() do { } while (0) | 39 | # define gether_cleanup() do { } while (0) |
40 | # define gether_setup(gadget, hostaddr) ((int)0) | 40 | # define gether_setup(gadget, hostaddr) ((int)0) |
41 | # define gfs_hostaddr NULL | ||
41 | #endif | 42 | #endif |
42 | 43 | ||
43 | #include "f_fs.c" | 44 | #include "f_fs.c" |
@@ -107,15 +108,7 @@ static const struct usb_descriptor_header *gfs_otg_desc[] = { | |||
107 | enum { | 108 | enum { |
108 | GFS_STRING_MANUFACTURER_IDX, | 109 | GFS_STRING_MANUFACTURER_IDX, |
109 | GFS_STRING_PRODUCT_IDX, | 110 | GFS_STRING_PRODUCT_IDX, |
110 | #ifdef CONFIG_USB_FUNCTIONFS_RNDIS | 111 | GFS_STRING_FIRST_CONFIG_IDX, |
111 | GFS_STRING_RNDIS_CONFIG_IDX, | ||
112 | #endif | ||
113 | #ifdef CONFIG_USB_FUNCTIONFS_ETH | ||
114 | GFS_STRING_ECM_CONFIG_IDX, | ||
115 | #endif | ||
116 | #ifdef CONFIG_USB_FUNCTIONFS_GENERIC | ||
117 | GFS_STRING_GENERIC_CONFIG_IDX, | ||
118 | #endif | ||
119 | }; | 112 | }; |
120 | 113 | ||
121 | static char gfs_manufacturer[50]; | 114 | static char gfs_manufacturer[50]; |
@@ -126,13 +119,13 @@ static struct usb_string gfs_strings[] = { | |||
126 | [GFS_STRING_MANUFACTURER_IDX].s = gfs_manufacturer, | 119 | [GFS_STRING_MANUFACTURER_IDX].s = gfs_manufacturer, |
127 | [GFS_STRING_PRODUCT_IDX].s = gfs_driver_desc, | 120 | [GFS_STRING_PRODUCT_IDX].s = gfs_driver_desc, |
128 | #ifdef CONFIG_USB_FUNCTIONFS_RNDIS | 121 | #ifdef CONFIG_USB_FUNCTIONFS_RNDIS |
129 | [GFS_STRING_RNDIS_CONFIG_IDX].s = "FunctionFS + RNDIS", | 122 | { .s = "FunctionFS + RNDIS" }, |
130 | #endif | 123 | #endif |
131 | #ifdef CONFIG_USB_FUNCTIONFS_ETH | 124 | #ifdef CONFIG_USB_FUNCTIONFS_ETH |
132 | [GFS_STRING_ECM_CONFIG_IDX].s = "FunctionFS + ECM", | 125 | { .s = "FunctionFS + ECM" }, |
133 | #endif | 126 | #endif |
134 | #ifdef CONFIG_USB_FUNCTIONFS_GENERIC | 127 | #ifdef CONFIG_USB_FUNCTIONFS_GENERIC |
135 | [GFS_STRING_GENERIC_CONFIG_IDX].s = "FunctionFS", | 128 | { .s = "FunctionFS" }, |
136 | #endif | 129 | #endif |
137 | { } /* end of list */ | 130 | { } /* end of list */ |
138 | }; | 131 | }; |
@@ -146,59 +139,33 @@ static struct usb_gadget_strings *gfs_dev_strings[] = { | |||
146 | }; | 139 | }; |
147 | 140 | ||
148 | 141 | ||
142 | |||
143 | struct gfs_configuration { | ||
144 | struct usb_configuration c; | ||
145 | int (*eth)(struct usb_configuration *c, u8 *ethaddr); | ||
146 | } gfs_configurations[] = { | ||
149 | #ifdef CONFIG_USB_FUNCTIONFS_RNDIS | 147 | #ifdef CONFIG_USB_FUNCTIONFS_RNDIS |
150 | static int gfs_do_rndis_config(struct usb_configuration *c); | 148 | { |
151 | 149 | .eth = rndis_bind_config, | |
152 | static struct usb_configuration gfs_rndis_config_driver = { | 150 | }, |
153 | .label = "FunctionFS + RNDIS", | ||
154 | .bind = gfs_do_rndis_config, | ||
155 | .bConfigurationValue = 1, | ||
156 | /* .iConfiguration = DYNAMIC */ | ||
157 | .bmAttributes = USB_CONFIG_ATT_SELFPOWER, | ||
158 | }; | ||
159 | # define gfs_add_rndis_config(cdev) \ | ||
160 | usb_add_config(cdev, &gfs_rndis_config_driver) | ||
161 | #else | ||
162 | # define gfs_add_rndis_config(cdev) 0 | ||
163 | #endif | 151 | #endif |
164 | 152 | ||
165 | |||
166 | #ifdef CONFIG_USB_FUNCTIONFS_ETH | 153 | #ifdef CONFIG_USB_FUNCTIONFS_ETH |
167 | static int gfs_do_ecm_config(struct usb_configuration *c); | 154 | { |
168 | 155 | .eth = eth_bind_config, | |
169 | static struct usb_configuration gfs_ecm_config_driver = { | 156 | }, |
170 | .label = "FunctionFS + ECM", | ||
171 | .bind = gfs_do_ecm_config, | ||
172 | .bConfigurationValue = 1, | ||
173 | /* .iConfiguration = DYNAMIC */ | ||
174 | .bmAttributes = USB_CONFIG_ATT_SELFPOWER, | ||
175 | }; | ||
176 | # define gfs_add_ecm_config(cdev) \ | ||
177 | usb_add_config(cdev, &gfs_ecm_config_driver) | ||
178 | #else | ||
179 | # define gfs_add_ecm_config(cdev) 0 | ||
180 | #endif | 157 | #endif |
181 | 158 | ||
182 | |||
183 | #ifdef CONFIG_USB_FUNCTIONFS_GENERIC | 159 | #ifdef CONFIG_USB_FUNCTIONFS_GENERIC |
184 | static int gfs_do_generic_config(struct usb_configuration *c); | 160 | { |
185 | 161 | }, | |
186 | static struct usb_configuration gfs_generic_config_driver = { | ||
187 | .label = "FunctionFS", | ||
188 | .bind = gfs_do_generic_config, | ||
189 | .bConfigurationValue = 2, | ||
190 | /* .iConfiguration = DYNAMIC */ | ||
191 | .bmAttributes = USB_CONFIG_ATT_SELFPOWER, | ||
192 | }; | ||
193 | # define gfs_add_generic_config(cdev) \ | ||
194 | usb_add_config(cdev, &gfs_generic_config_driver) | ||
195 | #else | ||
196 | # define gfs_add_generic_config(cdev) 0 | ||
197 | #endif | 162 | #endif |
163 | }; | ||
198 | 164 | ||
199 | 165 | ||
200 | static int gfs_bind(struct usb_composite_dev *cdev); | 166 | static int gfs_bind(struct usb_composite_dev *cdev); |
201 | static int gfs_unbind(struct usb_composite_dev *cdev); | 167 | static int gfs_unbind(struct usb_composite_dev *cdev); |
168 | static int gfs_do_config(struct usb_configuration *c); | ||
202 | 169 | ||
203 | static struct usb_composite_driver gfs_driver = { | 170 | static struct usb_composite_driver gfs_driver = { |
204 | .name = gfs_short_name, | 171 | .name = gfs_short_name, |
@@ -267,7 +234,7 @@ static int functionfs_check_dev_callback(const char *dev_name) | |||
267 | 234 | ||
268 | static int gfs_bind(struct usb_composite_dev *cdev) | 235 | static int gfs_bind(struct usb_composite_dev *cdev) |
269 | { | 236 | { |
270 | int ret; | 237 | int ret, i; |
271 | 238 | ||
272 | ENTER(); | 239 | ENTER(); |
273 | 240 | ||
@@ -284,57 +251,32 @@ static int gfs_bind(struct usb_composite_dev *cdev) | |||
284 | snprintf(gfs_manufacturer, sizeof gfs_manufacturer, "%s %s with %s", | 251 | snprintf(gfs_manufacturer, sizeof gfs_manufacturer, "%s %s with %s", |
285 | init_utsname()->sysname, init_utsname()->release, | 252 | init_utsname()->sysname, init_utsname()->release, |
286 | cdev->gadget->name); | 253 | cdev->gadget->name); |
287 | ret = usb_string_id(cdev); | ||
288 | if (unlikely(ret < 0)) | ||
289 | goto error; | ||
290 | gfs_strings[GFS_STRING_MANUFACTURER_IDX].id = ret; | ||
291 | gfs_dev_desc.iManufacturer = ret; | ||
292 | |||
293 | ret = usb_string_id(cdev); | ||
294 | if (unlikely(ret < 0)) | ||
295 | goto error; | ||
296 | gfs_strings[GFS_STRING_PRODUCT_IDX].id = ret; | ||
297 | gfs_dev_desc.iProduct = ret; | ||
298 | |||
299 | #ifdef CONFIG_USB_FUNCTIONFS_RNDIS | ||
300 | ret = usb_string_id(cdev); | ||
301 | if (unlikely(ret < 0)) | ||
302 | goto error; | ||
303 | gfs_strings[GFS_STRING_RNDIS_CONFIG_IDX].id = ret; | ||
304 | gfs_rndis_config_driver.iConfiguration = ret; | ||
305 | #endif | ||
306 | 254 | ||
307 | #ifdef CONFIG_USB_FUNCTIONFS_ETH | 255 | ret = usb_string_ids_tab(cdev, gfs_strings); |
308 | ret = usb_string_id(cdev); | ||
309 | if (unlikely(ret < 0)) | 256 | if (unlikely(ret < 0)) |
310 | goto error; | 257 | goto error; |
311 | gfs_strings[GFS_STRING_ECM_CONFIG_IDX].id = ret; | ||
312 | gfs_ecm_config_driver.iConfiguration = ret; | ||
313 | #endif | ||
314 | 258 | ||
315 | #ifdef CONFIG_USB_FUNCTIONFS_GENERIC | 259 | gfs_dev_desc.iManufacturer = gfs_strings[GFS_STRING_MANUFACTURER_IDX].id; |
316 | ret = usb_string_id(cdev); | 260 | gfs_dev_desc.iProduct = gfs_strings[GFS_STRING_PRODUCT_IDX].id; |
317 | if (unlikely(ret < 0)) | ||
318 | goto error; | ||
319 | gfs_strings[GFS_STRING_GENERIC_CONFIG_IDX].id = ret; | ||
320 | gfs_generic_config_driver.iConfiguration = ret; | ||
321 | #endif | ||
322 | 261 | ||
323 | ret = functionfs_bind(gfs_ffs_data, cdev); | 262 | ret = functionfs_bind(gfs_ffs_data, cdev); |
324 | if (unlikely(ret < 0)) | 263 | if (unlikely(ret < 0)) |
325 | goto error; | 264 | goto error; |
326 | 265 | ||
327 | ret = gfs_add_rndis_config(cdev); | 266 | for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) { |
328 | if (unlikely(ret < 0)) | 267 | struct gfs_configuration *c = gfs_configurations + i; |
329 | goto error_unbind; | ||
330 | 268 | ||
331 | ret = gfs_add_ecm_config(cdev); | 269 | ret = GFS_STRING_FIRST_CONFIG_IDX + i; |
332 | if (unlikely(ret < 0)) | 270 | c->c.label = gfs_strings[ret].s; |
333 | goto error_unbind; | 271 | c->c.iConfiguration = gfs_strings[ret].id; |
272 | c->c.bind = gfs_do_config; | ||
273 | c->c.bConfigurationValue = 1 + i; | ||
274 | c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER; | ||
334 | 275 | ||
335 | ret = gfs_add_generic_config(cdev); | 276 | ret = usb_add_config(cdev, &c->c); |
336 | if (unlikely(ret < 0)) | 277 | if (unlikely(ret < 0)) |
337 | goto error_unbind; | 278 | goto error_unbind; |
279 | } | ||
338 | 280 | ||
339 | return 0; | 281 | return 0; |
340 | 282 | ||
@@ -368,10 +310,10 @@ static int gfs_unbind(struct usb_composite_dev *cdev) | |||
368 | } | 310 | } |
369 | 311 | ||
370 | 312 | ||
371 | static int __gfs_do_config(struct usb_configuration *c, | 313 | static int gfs_do_config(struct usb_configuration *c) |
372 | int (*eth)(struct usb_configuration *c, u8 *ethaddr), | ||
373 | u8 *ethaddr) | ||
374 | { | 314 | { |
315 | struct gfs_configuration *gc = | ||
316 | container_of(c, struct gfs_configuration, c); | ||
375 | int ret; | 317 | int ret; |
376 | 318 | ||
377 | if (WARN_ON(!gfs_ffs_data)) | 319 | if (WARN_ON(!gfs_ffs_data)) |
@@ -382,13 +324,13 @@ static int __gfs_do_config(struct usb_configuration *c, | |||
382 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 324 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
383 | } | 325 | } |
384 | 326 | ||
385 | if (eth) { | 327 | if (gc->eth) { |
386 | ret = eth(c, ethaddr); | 328 | ret = gc->eth(c, gfs_hostaddr); |
387 | if (unlikely(ret < 0)) | 329 | if (unlikely(ret < 0)) |
388 | return ret; | 330 | return ret; |
389 | } | 331 | } |
390 | 332 | ||
391 | ret = functionfs_add(c->cdev, c, gfs_ffs_data); | 333 | ret = functionfs_bind_config(c->cdev, c, gfs_ffs_data); |
392 | if (unlikely(ret < 0)) | 334 | if (unlikely(ret < 0)) |
393 | return ret; | 335 | return ret; |
394 | 336 | ||
@@ -406,32 +348,12 @@ static int __gfs_do_config(struct usb_configuration *c, | |||
406 | return 0; | 348 | return 0; |
407 | } | 349 | } |
408 | 350 | ||
409 | #ifdef CONFIG_USB_FUNCTIONFS_RNDIS | ||
410 | static int gfs_do_rndis_config(struct usb_configuration *c) | ||
411 | { | ||
412 | ENTER(); | ||
413 | |||
414 | return __gfs_do_config(c, rndis_bind_config, gfs_hostaddr); | ||
415 | } | ||
416 | #endif | ||
417 | 351 | ||
418 | #ifdef CONFIG_USB_FUNCTIONFS_ETH | 352 | #ifdef CONFIG_USB_FUNCTIONFS_ETH |
419 | static int gfs_do_ecm_config(struct usb_configuration *c) | 353 | static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) |
420 | { | ||
421 | ENTER(); | ||
422 | |||
423 | return __gfs_do_config(c, | ||
424 | can_support_ecm(c->cdev->gadget) | ||
425 | ? ecm_bind_config : geth_bind_config, | ||
426 | gfs_hostaddr); | ||
427 | } | ||
428 | #endif | ||
429 | |||
430 | #ifdef CONFIG_USB_FUNCTIONFS_GENERIC | ||
431 | static int gfs_do_generic_config(struct usb_configuration *c) | ||
432 | { | 354 | { |
433 | ENTER(); | 355 | return can_support_ecm(c->cdev->gadget) |
434 | 356 | ? ecm_bind_config(c, ethaddr) | |
435 | return __gfs_do_config(c, NULL, NULL); | 357 | : geth_bind_config(c, ethaddr); |
436 | } | 358 | } |
437 | #endif | 359 | #endif |
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index b7bf88019b06..1b413a5cc3f6 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c | |||
@@ -1157,7 +1157,7 @@ fail: | |||
1157 | /* | 1157 | /* |
1158 | * Creates an output endpoint, and initializes output ports. | 1158 | * Creates an output endpoint, and initializes output ports. |
1159 | */ | 1159 | */ |
1160 | static int __init gmidi_bind(struct usb_gadget *gadget) | 1160 | static int __ref gmidi_bind(struct usb_gadget *gadget) |
1161 | { | 1161 | { |
1162 | struct gmidi_device *dev; | 1162 | struct gmidi_device *dev; |
1163 | struct usb_ep *in_ep, *out_ep; | 1163 | struct usb_ep *in_ep, *out_ep; |
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 775722686ed8..735495bf8411 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c | |||
@@ -127,7 +127,7 @@ static struct usb_gadget_strings *dev_strings[] = { | |||
127 | 127 | ||
128 | /****************************** Configurations ******************************/ | 128 | /****************************** Configurations ******************************/ |
129 | 129 | ||
130 | static int __init do_config(struct usb_configuration *c) | 130 | static int __ref do_config(struct usb_configuration *c) |
131 | { | 131 | { |
132 | struct hidg_func_node *e; | 132 | struct hidg_func_node *e; |
133 | int func = 0, status = 0; | 133 | int func = 0, status = 0; |
@@ -156,7 +156,7 @@ static struct usb_configuration config_driver = { | |||
156 | 156 | ||
157 | /****************************** Gadget Bind ******************************/ | 157 | /****************************** Gadget Bind ******************************/ |
158 | 158 | ||
159 | static int __init hid_bind(struct usb_composite_dev *cdev) | 159 | static int __ref hid_bind(struct usb_composite_dev *cdev) |
160 | { | 160 | { |
161 | struct usb_gadget *gadget = cdev->gadget; | 161 | struct usb_gadget *gadget = cdev->gadget; |
162 | struct list_head *tmp; | 162 | struct list_head *tmp; |
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index de8a83803505..fc35406fc80c 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -1299,11 +1299,9 @@ static long dev_ioctl (struct file *fd, unsigned code, unsigned long value) | |||
1299 | struct usb_gadget *gadget = dev->gadget; | 1299 | struct usb_gadget *gadget = dev->gadget; |
1300 | long ret = -ENOTTY; | 1300 | long ret = -ENOTTY; |
1301 | 1301 | ||
1302 | if (gadget->ops->ioctl) { | 1302 | if (gadget->ops->ioctl) |
1303 | lock_kernel(); | ||
1304 | ret = gadget->ops->ioctl (gadget, code, value); | 1303 | ret = gadget->ops->ioctl (gadget, code, value); |
1305 | unlock_kernel(); | 1304 | |
1306 | } | ||
1307 | return ret; | 1305 | return ret; |
1308 | } | 1306 | } |
1309 | 1307 | ||
@@ -1867,13 +1865,9 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) | |||
1867 | buf += 4; | 1865 | buf += 4; |
1868 | length -= 4; | 1866 | length -= 4; |
1869 | 1867 | ||
1870 | kbuf = kmalloc (length, GFP_KERNEL); | 1868 | kbuf = memdup_user(buf, length); |
1871 | if (!kbuf) | 1869 | if (IS_ERR(kbuf)) |
1872 | return -ENOMEM; | 1870 | return PTR_ERR(kbuf); |
1873 | if (copy_from_user (kbuf, buf, length)) { | ||
1874 | kfree (kbuf); | ||
1875 | return -EFAULT; | ||
1876 | } | ||
1877 | 1871 | ||
1878 | spin_lock_irq (&dev->lock); | 1872 | spin_lock_irq (&dev->lock); |
1879 | value = -EINVAL; | 1873 | value = -EINVAL; |
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index a3913519fd58..c2d2a201f84b 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c | |||
@@ -842,9 +842,9 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req, | |||
842 | VDBG(dev, "req->mapped = 0\n"); | 842 | VDBG(dev, "req->mapped = 0\n"); |
843 | } | 843 | } |
844 | 844 | ||
845 | DBG(dev, "%s queue req %p, len %u, buf %p, dma 0x%08x\n", | 845 | DBG(dev, "%s queue req %p, len %u, buf %p, dma 0x%08llx\n", |
846 | _ep->name, | 846 | _ep->name, |
847 | _req, _req->length, _req->buf, _req->dma); | 847 | _req, _req->length, _req->buf, (unsigned long long)_req->dma); |
848 | 848 | ||
849 | _req->status = -EINPROGRESS; | 849 | _req->status = -EINPROGRESS; |
850 | _req->actual = 0; | 850 | _req->actual = 0; |
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 705cc1f76327..585f2559484d 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c | |||
@@ -141,9 +141,14 @@ static int msg_thread_exits(struct fsg_common *common) | |||
141 | return 0; | 141 | return 0; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int __init msg_do_config(struct usb_configuration *c) | 144 | static int __ref msg_do_config(struct usb_configuration *c) |
145 | { | 145 | { |
146 | struct fsg_common *common; | 146 | static const struct fsg_operations ops = { |
147 | .thread_exits = msg_thread_exits, | ||
148 | }; | ||
149 | static struct fsg_common common; | ||
150 | |||
151 | struct fsg_common *retp; | ||
147 | struct fsg_config config; | 152 | struct fsg_config config; |
148 | int ret; | 153 | int ret; |
149 | 154 | ||
@@ -153,13 +158,14 @@ static int __init msg_do_config(struct usb_configuration *c) | |||
153 | } | 158 | } |
154 | 159 | ||
155 | fsg_config_from_params(&config, &mod_data); | 160 | fsg_config_from_params(&config, &mod_data); |
156 | config.thread_exits = msg_thread_exits; | 161 | config.ops = &ops; |
157 | common = fsg_common_init(0, c->cdev, &config); | 162 | |
158 | if (IS_ERR(common)) | 163 | retp = fsg_common_init(&common, c->cdev, &config); |
159 | return PTR_ERR(common); | 164 | if (IS_ERR(retp)) |
165 | return PTR_ERR(retp); | ||
160 | 166 | ||
161 | ret = fsg_add(c->cdev, c, common); | 167 | ret = fsg_bind_config(c->cdev, c, &common); |
162 | fsg_common_put(common); | 168 | fsg_common_put(&common); |
163 | return ret; | 169 | return ret; |
164 | } | 170 | } |
165 | 171 | ||
@@ -176,7 +182,7 @@ static struct usb_configuration msg_config_driver = { | |||
176 | /****************************** Gadget Bind ******************************/ | 182 | /****************************** Gadget Bind ******************************/ |
177 | 183 | ||
178 | 184 | ||
179 | static int __init msg_bind(struct usb_composite_dev *cdev) | 185 | static int __ref msg_bind(struct usb_composite_dev *cdev) |
180 | { | 186 | { |
181 | struct usb_gadget *gadget = cdev->gadget; | 187 | struct usb_gadget *gadget = cdev->gadget; |
182 | int status; | 188 | int status; |
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index a930d7fd7e7a..795d76232167 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/utsname.h> | 26 | #include <linux/utsname.h> |
27 | #include <linux/module.h> | ||
27 | 28 | ||
28 | 29 | ||
29 | #if defined USB_ETH_RNDIS | 30 | #if defined USB_ETH_RNDIS |
@@ -35,14 +36,13 @@ | |||
35 | 36 | ||
36 | 37 | ||
37 | #define DRIVER_DESC "Multifunction Composite Gadget" | 38 | #define DRIVER_DESC "Multifunction Composite Gadget" |
38 | #define DRIVER_VERSION "2009/07/21" | ||
39 | 39 | ||
40 | /*-------------------------------------------------------------------------*/ | 40 | MODULE_DESCRIPTION(DRIVER_DESC); |
41 | MODULE_AUTHOR("Michal Nazarewicz"); | ||
42 | MODULE_LICENSE("GPL"); | ||
41 | 43 | ||
42 | #define MULTI_VENDOR_NUM 0x0525 /* XXX NetChip */ | ||
43 | #define MULTI_PRODUCT_NUM 0xa4ab /* XXX */ | ||
44 | 44 | ||
45 | /*-------------------------------------------------------------------------*/ | 45 | /***************************** All the files... *****************************/ |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * kbuild is not very cooperative with respect to linking separately | 48 | * kbuild is not very cooperative with respect to linking separately |
@@ -57,6 +57,8 @@ | |||
57 | #include "config.c" | 57 | #include "config.c" |
58 | #include "epautoconf.c" | 58 | #include "epautoconf.c" |
59 | 59 | ||
60 | #include "f_mass_storage.c" | ||
61 | |||
60 | #include "u_serial.c" | 62 | #include "u_serial.c" |
61 | #include "f_acm.c" | 63 | #include "f_acm.c" |
62 | 64 | ||
@@ -68,13 +70,24 @@ | |||
68 | #endif | 70 | #endif |
69 | #include "u_ether.c" | 71 | #include "u_ether.c" |
70 | 72 | ||
71 | #undef DBG /* u_ether.c has broken idea about macros */ | ||
72 | #undef VDBG /* so clean up after it */ | ||
73 | #undef ERROR | ||
74 | #undef INFO | ||
75 | #include "f_mass_storage.c" | ||
76 | 73 | ||
77 | /*-------------------------------------------------------------------------*/ | 74 | |
75 | /***************************** Device Descriptor ****************************/ | ||
76 | |||
77 | #define MULTI_VENDOR_NUM 0x0525 /* XXX NetChip */ | ||
78 | #define MULTI_PRODUCT_NUM 0xa4ab /* XXX */ | ||
79 | |||
80 | |||
81 | enum { | ||
82 | __MULTI_NO_CONFIG, | ||
83 | #ifdef CONFIG_USB_G_MULTI_RNDIS | ||
84 | MULTI_RNDIS_CONFIG_NUM, | ||
85 | #endif | ||
86 | #ifdef CONFIG_USB_G_MULTI_CDC | ||
87 | MULTI_CDC_CONFIG_NUM, | ||
88 | #endif | ||
89 | }; | ||
90 | |||
78 | 91 | ||
79 | static struct usb_device_descriptor device_desc = { | 92 | static struct usb_device_descriptor device_desc = { |
80 | .bLength = sizeof device_desc, | 93 | .bLength = sizeof device_desc, |
@@ -82,80 +95,82 @@ static struct usb_device_descriptor device_desc = { | |||
82 | 95 | ||
83 | .bcdUSB = cpu_to_le16(0x0200), | 96 | .bcdUSB = cpu_to_le16(0x0200), |
84 | 97 | ||
85 | /* .bDeviceClass = USB_CLASS_COMM, */ | 98 | .bDeviceClass = USB_CLASS_MISC /* 0xEF */, |
86 | /* .bDeviceSubClass = 0, */ | ||
87 | /* .bDeviceProtocol = 0, */ | ||
88 | .bDeviceClass = 0xEF, | ||
89 | .bDeviceSubClass = 2, | 99 | .bDeviceSubClass = 2, |
90 | .bDeviceProtocol = 1, | 100 | .bDeviceProtocol = 1, |
91 | /* .bMaxPacketSize0 = f(hardware) */ | ||
92 | 101 | ||
93 | /* Vendor and product id can be overridden by module parameters. */ | 102 | /* Vendor and product id can be overridden by module parameters. */ |
94 | .idVendor = cpu_to_le16(MULTI_VENDOR_NUM), | 103 | .idVendor = cpu_to_le16(MULTI_VENDOR_NUM), |
95 | .idProduct = cpu_to_le16(MULTI_PRODUCT_NUM), | 104 | .idProduct = cpu_to_le16(MULTI_PRODUCT_NUM), |
96 | /* .bcdDevice = f(hardware) */ | ||
97 | /* .iManufacturer = DYNAMIC */ | ||
98 | /* .iProduct = DYNAMIC */ | ||
99 | /* NO SERIAL NUMBER */ | ||
100 | .bNumConfigurations = 1, | ||
101 | }; | 105 | }; |
102 | 106 | ||
103 | static struct usb_otg_descriptor otg_descriptor = { | ||
104 | .bLength = sizeof otg_descriptor, | ||
105 | .bDescriptorType = USB_DT_OTG, | ||
106 | |||
107 | /* REVISIT SRP-only hardware is possible, although | ||
108 | * it would not be called "OTG" ... | ||
109 | */ | ||
110 | .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, | ||
111 | }; | ||
112 | 107 | ||
113 | static const struct usb_descriptor_header *otg_desc[] = { | 108 | static const struct usb_descriptor_header *otg_desc[] = { |
114 | (struct usb_descriptor_header *) &otg_descriptor, | 109 | (struct usb_descriptor_header *) &(struct usb_otg_descriptor){ |
110 | .bLength = sizeof(struct usb_otg_descriptor), | ||
111 | .bDescriptorType = USB_DT_OTG, | ||
112 | |||
113 | /* | ||
114 | * REVISIT SRP-only hardware is possible, although | ||
115 | * it would not be called "OTG" ... | ||
116 | */ | ||
117 | .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, | ||
118 | }, | ||
115 | NULL, | 119 | NULL, |
116 | }; | 120 | }; |
117 | 121 | ||
118 | 122 | ||
119 | /* string IDs are assigned dynamically */ | 123 | enum { |
120 | 124 | MULTI_STRING_MANUFACTURER_IDX, | |
121 | #define STRING_MANUFACTURER_IDX 0 | 125 | MULTI_STRING_PRODUCT_IDX, |
122 | #define STRING_PRODUCT_IDX 1 | 126 | #ifdef CONFIG_USB_G_MULTI_RNDIS |
127 | MULTI_STRING_RNDIS_CONFIG_IDX, | ||
128 | #endif | ||
129 | #ifdef CONFIG_USB_G_MULTI_CDC | ||
130 | MULTI_STRING_CDC_CONFIG_IDX, | ||
131 | #endif | ||
132 | }; | ||
123 | 133 | ||
124 | static char manufacturer[50]; | 134 | static char manufacturer[50]; |
125 | 135 | ||
126 | static struct usb_string strings_dev[] = { | 136 | static struct usb_string strings_dev[] = { |
127 | [STRING_MANUFACTURER_IDX].s = manufacturer, | 137 | [MULTI_STRING_MANUFACTURER_IDX].s = manufacturer, |
128 | [STRING_PRODUCT_IDX].s = DRIVER_DESC, | 138 | [MULTI_STRING_PRODUCT_IDX].s = DRIVER_DESC, |
139 | #ifdef CONFIG_USB_G_MULTI_RNDIS | ||
140 | [MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS", | ||
141 | #endif | ||
142 | #ifdef CONFIG_USB_G_MULTI_CDC | ||
143 | [MULTI_STRING_CDC_CONFIG_IDX].s = "Multifunction with CDC ECM", | ||
144 | #endif | ||
129 | { } /* end of list */ | 145 | { } /* end of list */ |
130 | }; | 146 | }; |
131 | 147 | ||
132 | static struct usb_gadget_strings stringtab_dev = { | ||
133 | .language = 0x0409, /* en-us */ | ||
134 | .strings = strings_dev, | ||
135 | }; | ||
136 | |||
137 | static struct usb_gadget_strings *dev_strings[] = { | 148 | static struct usb_gadget_strings *dev_strings[] = { |
138 | &stringtab_dev, | 149 | &(struct usb_gadget_strings){ |
150 | .language = 0x0409, /* en-us */ | ||
151 | .strings = strings_dev, | ||
152 | }, | ||
139 | NULL, | 153 | NULL, |
140 | }; | 154 | }; |
141 | 155 | ||
142 | static u8 hostaddr[ETH_ALEN]; | ||
143 | 156 | ||
144 | 157 | ||
145 | 158 | ||
146 | /****************************** Configurations ******************************/ | 159 | /****************************** Configurations ******************************/ |
147 | 160 | ||
148 | static struct fsg_module_parameters mod_data = { | 161 | static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; |
149 | .stall = 1 | 162 | FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); |
150 | }; | 163 | |
151 | FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); | 164 | static struct fsg_common fsg_common; |
165 | |||
166 | static u8 hostaddr[ETH_ALEN]; | ||
152 | 167 | ||
153 | static struct fsg_common *fsg_common; | ||
154 | 168 | ||
169 | /********** RNDIS **********/ | ||
155 | 170 | ||
156 | #ifdef USB_ETH_RNDIS | 171 | #ifdef USB_ETH_RNDIS |
157 | 172 | ||
158 | static int __init rndis_do_config(struct usb_configuration *c) | 173 | static __ref int rndis_do_config(struct usb_configuration *c) |
159 | { | 174 | { |
160 | int ret; | 175 | int ret; |
161 | 176 | ||
@@ -172,26 +187,42 @@ static int __init rndis_do_config(struct usb_configuration *c) | |||
172 | if (ret < 0) | 187 | if (ret < 0) |
173 | return ret; | 188 | return ret; |
174 | 189 | ||
175 | ret = fsg_add(c->cdev, c, fsg_common); | 190 | ret = fsg_bind_config(c->cdev, c, &fsg_common); |
176 | if (ret < 0) | 191 | if (ret < 0) |
177 | return ret; | 192 | return ret; |
178 | 193 | ||
179 | return 0; | 194 | return 0; |
180 | } | 195 | } |
181 | 196 | ||
182 | static struct usb_configuration rndis_config_driver = { | 197 | static int rndis_config_register(struct usb_composite_dev *cdev) |
183 | .label = "Multifunction Composite (RNDIS + MS + ACM)", | 198 | { |
184 | .bind = rndis_do_config, | 199 | static struct usb_configuration config = { |
185 | .bConfigurationValue = 2, | 200 | .bind = rndis_do_config, |
186 | /* .iConfiguration = DYNAMIC */ | 201 | .bConfigurationValue = MULTI_RNDIS_CONFIG_NUM, |
187 | .bmAttributes = USB_CONFIG_ATT_SELFPOWER, | 202 | .bmAttributes = USB_CONFIG_ATT_SELFPOWER, |
188 | }; | 203 | }; |
204 | |||
205 | config.label = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].s; | ||
206 | config.iConfiguration = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].id; | ||
207 | |||
208 | return usb_add_config(cdev, &config); | ||
209 | } | ||
210 | |||
211 | #else | ||
212 | |||
213 | static int rndis_config_register(struct usb_composite_dev *cdev) | ||
214 | { | ||
215 | return 0; | ||
216 | } | ||
189 | 217 | ||
190 | #endif | 218 | #endif |
191 | 219 | ||
220 | |||
221 | /********** CDC ECM **********/ | ||
222 | |||
192 | #ifdef CONFIG_USB_G_MULTI_CDC | 223 | #ifdef CONFIG_USB_G_MULTI_CDC |
193 | 224 | ||
194 | static int __init cdc_do_config(struct usb_configuration *c) | 225 | static __ref int cdc_do_config(struct usb_configuration *c) |
195 | { | 226 | { |
196 | int ret; | 227 | int ret; |
197 | 228 | ||
@@ -208,20 +239,33 @@ static int __init cdc_do_config(struct usb_configuration *c) | |||
208 | if (ret < 0) | 239 | if (ret < 0) |
209 | return ret; | 240 | return ret; |
210 | 241 | ||
211 | ret = fsg_add(c->cdev, c, fsg_common); | 242 | ret = fsg_bind_config(c->cdev, c, &fsg_common); |
212 | if (ret < 0) | 243 | if (ret < 0) |
213 | return ret; | 244 | return ret; |
214 | 245 | ||
215 | return 0; | 246 | return 0; |
216 | } | 247 | } |
217 | 248 | ||
218 | static struct usb_configuration cdc_config_driver = { | 249 | static int cdc_config_register(struct usb_composite_dev *cdev) |
219 | .label = "Multifunction Composite (CDC + MS + ACM)", | 250 | { |
220 | .bind = cdc_do_config, | 251 | static struct usb_configuration config = { |
221 | .bConfigurationValue = 1, | 252 | .bind = cdc_do_config, |
222 | /* .iConfiguration = DYNAMIC */ | 253 | .bConfigurationValue = MULTI_CDC_CONFIG_NUM, |
223 | .bmAttributes = USB_CONFIG_ATT_SELFPOWER, | 254 | .bmAttributes = USB_CONFIG_ATT_SELFPOWER, |
224 | }; | 255 | }; |
256 | |||
257 | config.label = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].s; | ||
258 | config.iConfiguration = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].id; | ||
259 | |||
260 | return usb_add_config(cdev, &config); | ||
261 | } | ||
262 | |||
263 | #else | ||
264 | |||
265 | static int cdc_config_register(struct usb_composite_dev *cdev) | ||
266 | { | ||
267 | return 0; | ||
268 | } | ||
225 | 269 | ||
226 | #endif | 270 | #endif |
227 | 271 | ||
@@ -230,7 +274,7 @@ static struct usb_configuration cdc_config_driver = { | |||
230 | /****************************** Gadget Bind ******************************/ | 274 | /****************************** Gadget Bind ******************************/ |
231 | 275 | ||
232 | 276 | ||
233 | static int __init multi_bind(struct usb_composite_dev *cdev) | 277 | static int __ref multi_bind(struct usb_composite_dev *cdev) |
234 | { | 278 | { |
235 | struct usb_gadget *gadget = cdev->gadget; | 279 | struct usb_gadget *gadget = cdev->gadget; |
236 | int status, gcnum; | 280 | int status, gcnum; |
@@ -252,67 +296,56 @@ static int __init multi_bind(struct usb_composite_dev *cdev) | |||
252 | goto fail0; | 296 | goto fail0; |
253 | 297 | ||
254 | /* set up mass storage function */ | 298 | /* set up mass storage function */ |
255 | fsg_common = fsg_common_from_params(0, cdev, &mod_data); | 299 | { |
256 | if (IS_ERR(fsg_common)) { | 300 | void *retp; |
257 | status = PTR_ERR(fsg_common); | 301 | retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data); |
258 | goto fail1; | 302 | if (IS_ERR(retp)) { |
303 | status = PTR_ERR(retp); | ||
304 | goto fail1; | ||
305 | } | ||
259 | } | 306 | } |
260 | 307 | ||
261 | 308 | /* set bcdDevice */ | |
262 | gcnum = usb_gadget_controller_number(gadget); | 309 | gcnum = usb_gadget_controller_number(gadget); |
263 | if (gcnum >= 0) | 310 | if (gcnum >= 0) { |
264 | device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); | 311 | device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); |
265 | else { | 312 | } else { |
266 | /* We assume that can_support_ecm() tells the truth; | 313 | WARNING(cdev, "controller '%s' not recognized\n", gadget->name); |
267 | * but if the controller isn't recognized at all then | ||
268 | * that assumption is a bit more likely to be wrong. | ||
269 | */ | ||
270 | WARNING(cdev, "controller '%s' not recognized\n", | ||
271 | gadget->name); | ||
272 | device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099); | 314 | device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099); |
273 | } | 315 | } |
274 | 316 | ||
275 | 317 | /* allocate string descriptor numbers */ | |
276 | /* Allocate string descriptor numbers ... note that string | ||
277 | * contents can be overridden by the composite_dev glue. | ||
278 | */ | ||
279 | |||
280 | /* device descriptor strings: manufacturer, product */ | ||
281 | snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", | 318 | snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", |
282 | init_utsname()->sysname, init_utsname()->release, | 319 | init_utsname()->sysname, init_utsname()->release, |
283 | gadget->name); | 320 | gadget->name); |
284 | status = usb_string_id(cdev); | ||
285 | if (status < 0) | ||
286 | goto fail2; | ||
287 | strings_dev[STRING_MANUFACTURER_IDX].id = status; | ||
288 | device_desc.iManufacturer = status; | ||
289 | 321 | ||
290 | status = usb_string_id(cdev); | 322 | status = usb_string_ids_tab(cdev, strings_dev); |
291 | if (status < 0) | 323 | if (unlikely(status < 0)) |
292 | goto fail2; | 324 | goto fail2; |
293 | strings_dev[STRING_PRODUCT_IDX].id = status; | ||
294 | device_desc.iProduct = status; | ||
295 | 325 | ||
296 | #ifdef USB_ETH_RNDIS | 326 | device_desc.iManufacturer = |
297 | /* register our first configuration */ | 327 | strings_dev[MULTI_STRING_MANUFACTURER_IDX].id; |
298 | status = usb_add_config(cdev, &rndis_config_driver); | 328 | device_desc.iProduct = |
299 | if (status < 0) | 329 | strings_dev[MULTI_STRING_PRODUCT_IDX].id; |
330 | |||
331 | /* register configurations */ | ||
332 | status = rndis_config_register(cdev); | ||
333 | if (unlikely(status < 0)) | ||
300 | goto fail2; | 334 | goto fail2; |
301 | #endif | ||
302 | 335 | ||
303 | #ifdef CONFIG_USB_G_MULTI_CDC | 336 | status = cdc_config_register(cdev); |
304 | /* register our second configuration */ | 337 | if (unlikely(status < 0)) |
305 | status = usb_add_config(cdev, &cdc_config_driver); | ||
306 | if (status < 0) | ||
307 | goto fail2; | 338 | goto fail2; |
308 | #endif | ||
309 | 339 | ||
310 | dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); | 340 | /* we're done */ |
311 | fsg_common_put(fsg_common); | 341 | dev_info(&gadget->dev, DRIVER_DESC "\n"); |
342 | fsg_common_put(&fsg_common); | ||
312 | return 0; | 343 | return 0; |
313 | 344 | ||
345 | |||
346 | /* error recovery */ | ||
314 | fail2: | 347 | fail2: |
315 | fsg_common_put(fsg_common); | 348 | fsg_common_put(&fsg_common); |
316 | fail1: | 349 | fail1: |
317 | gserial_cleanup(); | 350 | gserial_cleanup(); |
318 | fail0: | 351 | fail0: |
@@ -339,18 +372,15 @@ static struct usb_composite_driver multi_driver = { | |||
339 | .unbind = __exit_p(multi_unbind), | 372 | .unbind = __exit_p(multi_unbind), |
340 | }; | 373 | }; |
341 | 374 | ||
342 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
343 | MODULE_AUTHOR("Michal Nazarewicz"); | ||
344 | MODULE_LICENSE("GPL"); | ||
345 | 375 | ||
346 | static int __init g_multi_init(void) | 376 | static int __init multi_init(void) |
347 | { | 377 | { |
348 | return usb_composite_register(&multi_driver); | 378 | return usb_composite_register(&multi_driver); |
349 | } | 379 | } |
350 | module_init(g_multi_init); | 380 | module_init(multi_init); |
351 | 381 | ||
352 | static void __exit g_multi_cleanup(void) | 382 | static void __exit multi_exit(void) |
353 | { | 383 | { |
354 | usb_composite_unregister(&multi_driver); | 384 | usb_composite_unregister(&multi_driver); |
355 | } | 385 | } |
356 | module_exit(g_multi_cleanup); | 386 | module_exit(multi_exit); |
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 4c3ac5c42237..cf241c371a71 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/ioport.h> | 25 | #include <linux/ioport.h> |
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/smp_lock.h> | 28 | #include <linux/mutex.h> |
29 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/timer.h> | 31 | #include <linux/timer.h> |
@@ -70,6 +70,7 @@ | |||
70 | #define DRIVER_DESC "Printer Gadget" | 70 | #define DRIVER_DESC "Printer Gadget" |
71 | #define DRIVER_VERSION "2007 OCT 06" | 71 | #define DRIVER_VERSION "2007 OCT 06" |
72 | 72 | ||
73 | static DEFINE_MUTEX(printer_mutex); | ||
73 | static const char shortname [] = "printer"; | 74 | static const char shortname [] = "printer"; |
74 | static const char driver_desc [] = DRIVER_DESC; | 75 | static const char driver_desc [] = DRIVER_DESC; |
75 | 76 | ||
@@ -476,7 +477,7 @@ printer_open(struct inode *inode, struct file *fd) | |||
476 | unsigned long flags; | 477 | unsigned long flags; |
477 | int ret = -EBUSY; | 478 | int ret = -EBUSY; |
478 | 479 | ||
479 | lock_kernel(); | 480 | mutex_lock(&printer_mutex); |
480 | dev = container_of(inode->i_cdev, struct printer_dev, printer_cdev); | 481 | dev = container_of(inode->i_cdev, struct printer_dev, printer_cdev); |
481 | 482 | ||
482 | spin_lock_irqsave(&dev->lock, flags); | 483 | spin_lock_irqsave(&dev->lock, flags); |
@@ -492,7 +493,7 @@ printer_open(struct inode *inode, struct file *fd) | |||
492 | spin_unlock_irqrestore(&dev->lock, flags); | 493 | spin_unlock_irqrestore(&dev->lock, flags); |
493 | 494 | ||
494 | DBG(dev, "printer_open returned %x\n", ret); | 495 | DBG(dev, "printer_open returned %x\n", ret); |
495 | unlock_kernel(); | 496 | mutex_unlock(&printer_mutex); |
496 | return ret; | 497 | return ret; |
497 | } | 498 | } |
498 | 499 | ||
@@ -1346,7 +1347,7 @@ printer_unbind(struct usb_gadget *gadget) | |||
1346 | set_gadget_data(gadget, NULL); | 1347 | set_gadget_data(gadget, NULL); |
1347 | } | 1348 | } |
1348 | 1349 | ||
1349 | static int __init | 1350 | static int __ref |
1350 | printer_bind(struct usb_gadget *gadget) | 1351 | printer_bind(struct usb_gadget *gadget) |
1351 | { | 1352 | { |
1352 | struct printer_dev *dev; | 1353 | struct printer_dev *dev; |
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 26193eceb323..521ebed0118d 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c | |||
@@ -12,6 +12,8 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #define DEBUG | ||
16 | |||
15 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 18 | #include <linux/module.h> |
17 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
@@ -23,6 +25,7 @@ | |||
23 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
24 | #include <linux/io.h> | 26 | #include <linux/io.h> |
25 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/clk.h> | ||
26 | 29 | ||
27 | #include <linux/usb/ch9.h> | 30 | #include <linux/usb/ch9.h> |
28 | #include <linux/usb/gadget.h> | 31 | #include <linux/usb/gadget.h> |
@@ -33,6 +36,7 @@ | |||
33 | #include <plat/regs-usb-hsotg.h> | 36 | #include <plat/regs-usb-hsotg.h> |
34 | #include <mach/regs-sys.h> | 37 | #include <mach/regs-sys.h> |
35 | #include <plat/udc-hs.h> | 38 | #include <plat/udc-hs.h> |
39 | #include <plat/cpu.h> | ||
36 | 40 | ||
37 | #define DMA_ADDR_INVALID (~((dma_addr_t)0)) | 41 | #define DMA_ADDR_INVALID (~((dma_addr_t)0)) |
38 | 42 | ||
@@ -91,7 +95,9 @@ struct s3c_hsotg_req; | |||
91 | * For periodic IN endpoints, we have fifo_size and fifo_load to try | 95 | * For periodic IN endpoints, we have fifo_size and fifo_load to try |
92 | * and keep track of the amount of data in the periodic FIFO for each | 96 | * and keep track of the amount of data in the periodic FIFO for each |
93 | * of these as we don't have a status register that tells us how much | 97 | * of these as we don't have a status register that tells us how much |
94 | * is in each of them. | 98 | * is in each of them. (note, this may actually be useless information |
99 | * as in shared-fifo mode periodic in acts like a single-frame packet | ||
100 | * buffer than a fifo) | ||
95 | */ | 101 | */ |
96 | struct s3c_hsotg_ep { | 102 | struct s3c_hsotg_ep { |
97 | struct usb_ep ep; | 103 | struct usb_ep ep; |
@@ -128,6 +134,7 @@ struct s3c_hsotg_ep { | |||
128 | * @regs: The memory area mapped for accessing registers. | 134 | * @regs: The memory area mapped for accessing registers. |
129 | * @regs_res: The resource that was allocated when claiming register space. | 135 | * @regs_res: The resource that was allocated when claiming register space. |
130 | * @irq: The IRQ number we are using | 136 | * @irq: The IRQ number we are using |
137 | * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos. | ||
131 | * @debug_root: root directrory for debugfs. | 138 | * @debug_root: root directrory for debugfs. |
132 | * @debug_file: main status file for debugfs. | 139 | * @debug_file: main status file for debugfs. |
133 | * @debug_fifo: FIFO status file for debugfs. | 140 | * @debug_fifo: FIFO status file for debugfs. |
@@ -145,6 +152,9 @@ struct s3c_hsotg { | |||
145 | void __iomem *regs; | 152 | void __iomem *regs; |
146 | struct resource *regs_res; | 153 | struct resource *regs_res; |
147 | int irq; | 154 | int irq; |
155 | struct clk *clk; | ||
156 | |||
157 | unsigned int dedicated_fifos:1; | ||
148 | 158 | ||
149 | struct dentry *debug_root; | 159 | struct dentry *debug_root; |
150 | struct dentry *debug_file; | 160 | struct dentry *debug_file; |
@@ -310,11 +320,11 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg) | |||
310 | hsotg->regs + S3C_GNPTXFSIZ); | 320 | hsotg->regs + S3C_GNPTXFSIZ); |
311 | */ | 321 | */ |
312 | 322 | ||
313 | /* set FIFO sizes to 2048/0x1C0 */ | 323 | /* set FIFO sizes to 2048/1024 */ |
314 | 324 | ||
315 | writel(2048, hsotg->regs + S3C_GRXFSIZ); | 325 | writel(2048, hsotg->regs + S3C_GRXFSIZ); |
316 | writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) | | 326 | writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) | |
317 | S3C_GNPTXFSIZ_NPTxFDep(0x1C0), | 327 | S3C_GNPTXFSIZ_NPTxFDep(1024), |
318 | hsotg->regs + S3C_GNPTXFSIZ); | 328 | hsotg->regs + S3C_GNPTXFSIZ); |
319 | 329 | ||
320 | /* arange all the rest of the TX FIFOs, as some versions of this | 330 | /* arange all the rest of the TX FIFOs, as some versions of this |
@@ -464,7 +474,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, | |||
464 | if (to_write == 0) | 474 | if (to_write == 0) |
465 | return 0; | 475 | return 0; |
466 | 476 | ||
467 | if (periodic) { | 477 | if (periodic && !hsotg->dedicated_fifos) { |
468 | u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index)); | 478 | u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index)); |
469 | int size_left; | 479 | int size_left; |
470 | int size_done; | 480 | int size_done; |
@@ -474,6 +484,14 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, | |||
474 | 484 | ||
475 | size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); | 485 | size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); |
476 | 486 | ||
487 | /* if shared fifo, we cannot write anything until the | ||
488 | * previous data has been completely sent. | ||
489 | */ | ||
490 | if (hs_ep->fifo_load != 0) { | ||
491 | s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp); | ||
492 | return -ENOSPC; | ||
493 | } | ||
494 | |||
477 | dev_dbg(hsotg->dev, "%s: left=%d, load=%d, fifo=%d, size %d\n", | 495 | dev_dbg(hsotg->dev, "%s: left=%d, load=%d, fifo=%d, size %d\n", |
478 | __func__, size_left, | 496 | __func__, size_left, |
479 | hs_ep->size_loaded, hs_ep->fifo_load, hs_ep->fifo_size); | 497 | hs_ep->size_loaded, hs_ep->fifo_load, hs_ep->fifo_size); |
@@ -494,6 +512,11 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, | |||
494 | s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp); | 512 | s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp); |
495 | return -ENOSPC; | 513 | return -ENOSPC; |
496 | } | 514 | } |
515 | } else if (hsotg->dedicated_fifos && hs_ep->index != 0) { | ||
516 | can_write = readl(hsotg->regs + S3C_DTXFSTS(hs_ep->index)); | ||
517 | |||
518 | can_write &= 0xffff; | ||
519 | can_write *= 4; | ||
497 | } else { | 520 | } else { |
498 | if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) { | 521 | if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) { |
499 | dev_dbg(hsotg->dev, | 522 | dev_dbg(hsotg->dev, |
@@ -505,6 +528,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, | |||
505 | } | 528 | } |
506 | 529 | ||
507 | can_write = S3C_GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts); | 530 | can_write = S3C_GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts); |
531 | can_write *= 4; /* fifo size is in 32bit quantities. */ | ||
508 | } | 532 | } |
509 | 533 | ||
510 | dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n", | 534 | dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n", |
@@ -517,6 +541,17 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, | |||
517 | if (can_write > 512) | 541 | if (can_write > 512) |
518 | can_write = 512; | 542 | can_write = 512; |
519 | 543 | ||
544 | /* limit the write to one max-packet size worth of data, but allow | ||
545 | * the transfer to return that it did not run out of fifo space | ||
546 | * doing it. */ | ||
547 | if (to_write > hs_ep->ep.maxpacket) { | ||
548 | to_write = hs_ep->ep.maxpacket; | ||
549 | |||
550 | s3c_hsotg_en_gsint(hsotg, | ||
551 | periodic ? S3C_GINTSTS_PTxFEmp : | ||
552 | S3C_GINTSTS_NPTxFEmp); | ||
553 | } | ||
554 | |||
520 | /* see if we can write data */ | 555 | /* see if we can write data */ |
521 | 556 | ||
522 | if (to_write > can_write) { | 557 | if (to_write > can_write) { |
@@ -579,12 +614,10 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep) | |||
579 | maxsize = S3C_DxEPTSIZ_XferSize_LIMIT + 1; | 614 | maxsize = S3C_DxEPTSIZ_XferSize_LIMIT + 1; |
580 | maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1; | 615 | maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1; |
581 | } else { | 616 | } else { |
617 | maxsize = 64+64; | ||
582 | if (hs_ep->dir_in) { | 618 | if (hs_ep->dir_in) { |
583 | /* maxsize = S3C_DIEPTSIZ0_XferSize_LIMIT + 1; */ | ||
584 | maxsize = 64+64+1; | ||
585 | maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1; | 619 | maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1; |
586 | } else { | 620 | } else { |
587 | maxsize = 0x3f; | ||
588 | maxpkt = 2; | 621 | maxpkt = 2; |
589 | } | 622 | } |
590 | } | 623 | } |
@@ -1353,6 +1386,9 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) | |||
1353 | read_ptr = hs_req->req.actual; | 1386 | read_ptr = hs_req->req.actual; |
1354 | max_req = hs_req->req.length - read_ptr; | 1387 | max_req = hs_req->req.length - read_ptr; |
1355 | 1388 | ||
1389 | dev_dbg(hsotg->dev, "%s: read %d/%d, done %d/%d\n", | ||
1390 | __func__, to_read, max_req, read_ptr, hs_req->req.length); | ||
1391 | |||
1356 | if (to_read > max_req) { | 1392 | if (to_read > max_req) { |
1357 | /* more data appeared than we where willing | 1393 | /* more data appeared than we where willing |
1358 | * to deal with in this request. | 1394 | * to deal with in this request. |
@@ -1362,9 +1398,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) | |||
1362 | WARN_ON_ONCE(1); | 1398 | WARN_ON_ONCE(1); |
1363 | } | 1399 | } |
1364 | 1400 | ||
1365 | dev_dbg(hsotg->dev, "%s: read %d/%d, done %d/%d\n", | ||
1366 | __func__, to_read, max_req, read_ptr, hs_req->req.length); | ||
1367 | |||
1368 | hs_ep->total_data += to_read; | 1401 | hs_ep->total_data += to_read; |
1369 | hs_req->req.actual += to_read; | 1402 | hs_req->req.actual += to_read; |
1370 | to_read = DIV_ROUND_UP(to_read, 4); | 1403 | to_read = DIV_ROUND_UP(to_read, 4); |
@@ -1433,9 +1466,11 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg, | |||
1433 | static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, | 1466 | static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, |
1434 | int epnum, bool was_setup) | 1467 | int epnum, bool was_setup) |
1435 | { | 1468 | { |
1469 | u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum)); | ||
1436 | struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum]; | 1470 | struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum]; |
1437 | struct s3c_hsotg_req *hs_req = hs_ep->req; | 1471 | struct s3c_hsotg_req *hs_req = hs_ep->req; |
1438 | struct usb_request *req = &hs_req->req; | 1472 | struct usb_request *req = &hs_req->req; |
1473 | unsigned size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); | ||
1439 | int result = 0; | 1474 | int result = 0; |
1440 | 1475 | ||
1441 | if (!hs_req) { | 1476 | if (!hs_req) { |
@@ -1444,9 +1479,7 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, | |||
1444 | } | 1479 | } |
1445 | 1480 | ||
1446 | if (using_dma(hsotg)) { | 1481 | if (using_dma(hsotg)) { |
1447 | u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum)); | ||
1448 | unsigned size_done; | 1482 | unsigned size_done; |
1449 | unsigned size_left; | ||
1450 | 1483 | ||
1451 | /* Calculate the size of the transfer by checking how much | 1484 | /* Calculate the size of the transfer by checking how much |
1452 | * is left in the endpoint size register and then working it | 1485 | * is left in the endpoint size register and then working it |
@@ -1456,14 +1489,18 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, | |||
1456 | * so may overshoot/undershoot the transfer. | 1489 | * so may overshoot/undershoot the transfer. |
1457 | */ | 1490 | */ |
1458 | 1491 | ||
1459 | size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); | ||
1460 | |||
1461 | size_done = hs_ep->size_loaded - size_left; | 1492 | size_done = hs_ep->size_loaded - size_left; |
1462 | size_done += hs_ep->last_load; | 1493 | size_done += hs_ep->last_load; |
1463 | 1494 | ||
1464 | req->actual = size_done; | 1495 | req->actual = size_done; |
1465 | } | 1496 | } |
1466 | 1497 | ||
1498 | /* if there is more request to do, schedule new transfer */ | ||
1499 | if (req->actual < req->length && size_left == 0) { | ||
1500 | s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); | ||
1501 | return; | ||
1502 | } | ||
1503 | |||
1467 | if (req->actual < req->length && req->short_not_ok) { | 1504 | if (req->actual < req->length && req->short_not_ok) { |
1468 | dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n", | 1505 | dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n", |
1469 | __func__, req->actual, req->length); | 1506 | __func__, req->actual, req->length); |
@@ -1758,7 +1795,7 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, | |||
1758 | if (dir_in) { | 1795 | if (dir_in) { |
1759 | s3c_hsotg_complete_in(hsotg, hs_ep); | 1796 | s3c_hsotg_complete_in(hsotg, hs_ep); |
1760 | 1797 | ||
1761 | if (idx == 0) | 1798 | if (idx == 0 && !hs_ep->req) |
1762 | s3c_hsotg_enqueue_setup(hsotg); | 1799 | s3c_hsotg_enqueue_setup(hsotg); |
1763 | } else if (using_dma(hsotg)) { | 1800 | } else if (using_dma(hsotg)) { |
1764 | /* We're using DMA, we need to fire an OutDone here | 1801 | /* We're using DMA, we need to fire an OutDone here |
@@ -1818,6 +1855,15 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, | |||
1818 | __func__, idx); | 1855 | __func__, idx); |
1819 | clear |= S3C_DIEPMSK_INTknEPMisMsk; | 1856 | clear |= S3C_DIEPMSK_INTknEPMisMsk; |
1820 | } | 1857 | } |
1858 | |||
1859 | /* FIFO has space or is empty (see GAHBCFG) */ | ||
1860 | if (hsotg->dedicated_fifos && | ||
1861 | ints & S3C_DIEPMSK_TxFIFOEmpty) { | ||
1862 | dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", | ||
1863 | __func__, idx); | ||
1864 | s3c_hsotg_trytx(hsotg, hs_ep); | ||
1865 | clear |= S3C_DIEPMSK_TxFIFOEmpty; | ||
1866 | } | ||
1821 | } | 1867 | } |
1822 | 1868 | ||
1823 | writel(clear, hsotg->regs + epint_reg); | 1869 | writel(clear, hsotg->regs + epint_reg); |
@@ -2071,17 +2117,12 @@ irq_retry: | |||
2071 | kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true); | 2117 | kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true); |
2072 | 2118 | ||
2073 | /* it seems after a reset we can end up with a situation | 2119 | /* it seems after a reset we can end up with a situation |
2074 | * where the TXFIFO still has data in it... try flushing | 2120 | * where the TXFIFO still has data in it... the docs |
2075 | * it to remove anything that may still be in it. | 2121 | * suggest resetting all the fifos, so use the init_fifo |
2122 | * code to relayout and flush the fifos. | ||
2076 | */ | 2123 | */ |
2077 | 2124 | ||
2078 | if (1) { | 2125 | s3c_hsotg_init_fifo(hsotg); |
2079 | writel(S3C_GRSTCTL_TxFNum(0) | S3C_GRSTCTL_TxFFlsh, | ||
2080 | hsotg->regs + S3C_GRSTCTL); | ||
2081 | |||
2082 | dev_info(hsotg->dev, "GNPTXSTS=%08x\n", | ||
2083 | readl(hsotg->regs + S3C_GNPTXSTS)); | ||
2084 | } | ||
2085 | 2126 | ||
2086 | s3c_hsotg_enqueue_setup(hsotg); | 2127 | s3c_hsotg_enqueue_setup(hsotg); |
2087 | 2128 | ||
@@ -2274,6 +2315,12 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, | |||
2274 | break; | 2315 | break; |
2275 | } | 2316 | } |
2276 | 2317 | ||
2318 | /* if the hardware has dedicated fifos, we must give each IN EP | ||
2319 | * a unique tx-fifo even if it is non-periodic. | ||
2320 | */ | ||
2321 | if (dir_in && hsotg->dedicated_fifos) | ||
2322 | epctrl |= S3C_DxEPCTL_TxFNum(index); | ||
2323 | |||
2277 | /* for non control endpoints, set PID to D0 */ | 2324 | /* for non control endpoints, set PID to D0 */ |
2278 | if (index) | 2325 | if (index) |
2279 | epctrl |= S3C_DxEPCTL_SetD0PID; | 2326 | epctrl |= S3C_DxEPCTL_SetD0PID; |
@@ -2563,7 +2610,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) | |||
2563 | 2610 | ||
2564 | writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | | 2611 | writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | |
2565 | S3C_DIEPMSK_INTknEPMisMsk | | 2612 | S3C_DIEPMSK_INTknEPMisMsk | |
2566 | S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk, | 2613 | S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk | |
2614 | ((hsotg->dedicated_fifos) ? S3C_DIEPMSK_TxFIFOEmpty : 0), | ||
2567 | hsotg->regs + S3C_DIEPMSK); | 2615 | hsotg->regs + S3C_DIEPMSK); |
2568 | 2616 | ||
2569 | /* don't need XferCompl, we get that from RXFIFO in slave mode. In | 2617 | /* don't need XferCompl, we get that from RXFIFO in slave mode. In |
@@ -2732,7 +2780,7 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg, | |||
2732 | */ | 2780 | */ |
2733 | 2781 | ||
2734 | ptxfifo = readl(hsotg->regs + S3C_DPTXFSIZn(epnum)); | 2782 | ptxfifo = readl(hsotg->regs + S3C_DPTXFSIZn(epnum)); |
2735 | hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo); | 2783 | hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4; |
2736 | 2784 | ||
2737 | /* if we're using dma, we need to set the next-endpoint pointer | 2785 | /* if we're using dma, we need to set the next-endpoint pointer |
2738 | * to be something valid. | 2786 | * to be something valid. |
@@ -2753,13 +2801,33 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg, | |||
2753 | */ | 2801 | */ |
2754 | static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg) | 2802 | static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg) |
2755 | { | 2803 | { |
2756 | u32 osc; | 2804 | struct clk *xusbxti; |
2805 | u32 pwr, osc; | ||
2757 | 2806 | ||
2758 | writel(0, S3C_PHYPWR); | 2807 | pwr = readl(S3C_PHYPWR); |
2808 | pwr &= ~0x19; | ||
2809 | writel(pwr, S3C_PHYPWR); | ||
2759 | mdelay(1); | 2810 | mdelay(1); |
2760 | 2811 | ||
2761 | osc = hsotg->plat->is_osc ? S3C_PHYCLK_EXT_OSC : 0; | 2812 | osc = hsotg->plat->is_osc ? S3C_PHYCLK_EXT_OSC : 0; |
2762 | 2813 | ||
2814 | xusbxti = clk_get(hsotg->dev, "xusbxti"); | ||
2815 | if (xusbxti && !IS_ERR(xusbxti)) { | ||
2816 | switch (clk_get_rate(xusbxti)) { | ||
2817 | case 12*MHZ: | ||
2818 | osc |= S3C_PHYCLK_CLKSEL_12M; | ||
2819 | break; | ||
2820 | case 24*MHZ: | ||
2821 | osc |= S3C_PHYCLK_CLKSEL_24M; | ||
2822 | break; | ||
2823 | default: | ||
2824 | case 48*MHZ: | ||
2825 | /* default reference clock */ | ||
2826 | break; | ||
2827 | } | ||
2828 | clk_put(xusbxti); | ||
2829 | } | ||
2830 | |||
2763 | writel(osc | 0x10, S3C_PHYCLK); | 2831 | writel(osc | 0x10, S3C_PHYCLK); |
2764 | 2832 | ||
2765 | /* issue a full set of resets to the otg and core */ | 2833 | /* issue a full set of resets to the otg and core */ |
@@ -2772,6 +2840,8 @@ static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg) | |||
2772 | 2840 | ||
2773 | static void s3c_hsotg_init(struct s3c_hsotg *hsotg) | 2841 | static void s3c_hsotg_init(struct s3c_hsotg *hsotg) |
2774 | { | 2842 | { |
2843 | u32 cfg4; | ||
2844 | |||
2775 | /* unmask subset of endpoint interrupts */ | 2845 | /* unmask subset of endpoint interrupts */ |
2776 | 2846 | ||
2777 | writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | | 2847 | writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | |
@@ -2807,6 +2877,14 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg) | |||
2807 | 2877 | ||
2808 | writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0, | 2878 | writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0, |
2809 | hsotg->regs + S3C_GAHBCFG); | 2879 | hsotg->regs + S3C_GAHBCFG); |
2880 | |||
2881 | /* check hardware configuration */ | ||
2882 | |||
2883 | cfg4 = readl(hsotg->regs + 0x50); | ||
2884 | hsotg->dedicated_fifos = (cfg4 >> 25) & 1; | ||
2885 | |||
2886 | dev_info(hsotg->dev, "%s fifos\n", | ||
2887 | hsotg->dedicated_fifos ? "dedicated" : "shared"); | ||
2810 | } | 2888 | } |
2811 | 2889 | ||
2812 | static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) | 2890 | static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) |
@@ -3181,13 +3259,20 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) | |||
3181 | hsotg->dev = dev; | 3259 | hsotg->dev = dev; |
3182 | hsotg->plat = plat; | 3260 | hsotg->plat = plat; |
3183 | 3261 | ||
3262 | hsotg->clk = clk_get(&pdev->dev, "otg"); | ||
3263 | if (IS_ERR(hsotg->clk)) { | ||
3264 | dev_err(dev, "cannot get otg clock\n"); | ||
3265 | ret = -EINVAL; | ||
3266 | goto err_mem; | ||
3267 | } | ||
3268 | |||
3184 | platform_set_drvdata(pdev, hsotg); | 3269 | platform_set_drvdata(pdev, hsotg); |
3185 | 3270 | ||
3186 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 3271 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
3187 | if (!res) { | 3272 | if (!res) { |
3188 | dev_err(dev, "cannot find register resource 0\n"); | 3273 | dev_err(dev, "cannot find register resource 0\n"); |
3189 | ret = -EINVAL; | 3274 | ret = -EINVAL; |
3190 | goto err_mem; | 3275 | goto err_clk; |
3191 | } | 3276 | } |
3192 | 3277 | ||
3193 | hsotg->regs_res = request_mem_region(res->start, resource_size(res), | 3278 | hsotg->regs_res = request_mem_region(res->start, resource_size(res), |
@@ -3195,7 +3280,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) | |||
3195 | if (!hsotg->regs_res) { | 3280 | if (!hsotg->regs_res) { |
3196 | dev_err(dev, "cannot reserve registers\n"); | 3281 | dev_err(dev, "cannot reserve registers\n"); |
3197 | ret = -ENOENT; | 3282 | ret = -ENOENT; |
3198 | goto err_mem; | 3283 | goto err_clk; |
3199 | } | 3284 | } |
3200 | 3285 | ||
3201 | hsotg->regs = ioremap(res->start, resource_size(res)); | 3286 | hsotg->regs = ioremap(res->start, resource_size(res)); |
@@ -3248,6 +3333,8 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) | |||
3248 | 3333 | ||
3249 | /* reset the system */ | 3334 | /* reset the system */ |
3250 | 3335 | ||
3336 | clk_enable(hsotg->clk); | ||
3337 | |||
3251 | s3c_hsotg_gate(pdev, true); | 3338 | s3c_hsotg_gate(pdev, true); |
3252 | 3339 | ||
3253 | s3c_hsotg_otgreset(hsotg); | 3340 | s3c_hsotg_otgreset(hsotg); |
@@ -3271,7 +3358,8 @@ err_regs: | |||
3271 | err_regs_res: | 3358 | err_regs_res: |
3272 | release_resource(hsotg->regs_res); | 3359 | release_resource(hsotg->regs_res); |
3273 | kfree(hsotg->regs_res); | 3360 | kfree(hsotg->regs_res); |
3274 | 3361 | err_clk: | |
3362 | clk_put(hsotg->clk); | ||
3275 | err_mem: | 3363 | err_mem: |
3276 | kfree(hsotg); | 3364 | kfree(hsotg); |
3277 | return ret; | 3365 | return ret; |
@@ -3293,6 +3381,9 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev) | |||
3293 | 3381 | ||
3294 | s3c_hsotg_gate(pdev, false); | 3382 | s3c_hsotg_gate(pdev, false); |
3295 | 3383 | ||
3384 | clk_disable(hsotg->clk); | ||
3385 | clk_put(hsotg->clk); | ||
3386 | |||
3296 | kfree(hsotg); | 3387 | kfree(hsotg); |
3297 | return 0; | 3388 | return 0; |
3298 | } | 3389 | } |
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index f46a60962dab..b22eedbc7dc5 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -137,7 +137,7 @@ MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); | |||
137 | 137 | ||
138 | /*-------------------------------------------------------------------------*/ | 138 | /*-------------------------------------------------------------------------*/ |
139 | 139 | ||
140 | static int __init serial_bind_config(struct usb_configuration *c) | 140 | static int __ref serial_bind_config(struct usb_configuration *c) |
141 | { | 141 | { |
142 | unsigned i; | 142 | unsigned i; |
143 | int status = 0; | 143 | int status = 0; |
@@ -161,7 +161,7 @@ static struct usb_configuration serial_config_driver = { | |||
161 | .bmAttributes = USB_CONFIG_ATT_SELFPOWER, | 161 | .bmAttributes = USB_CONFIG_ATT_SELFPOWER, |
162 | }; | 162 | }; |
163 | 163 | ||
164 | static int __init gs_bind(struct usb_composite_dev *cdev) | 164 | static int __ref gs_bind(struct usb_composite_dev *cdev) |
165 | { | 165 | { |
166 | int gcnum; | 166 | int gcnum; |
167 | struct usb_gadget *gadget = cdev->gadget; | 167 | struct usb_gadget *gadget = cdev->gadget; |
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 04c462ff0ea6..484acfb1a7c5 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c | |||
@@ -57,10 +57,12 @@ | |||
57 | #include <asm/unaligned.h> | 57 | #include <asm/unaligned.h> |
58 | 58 | ||
59 | 59 | ||
60 | /* Thanks to NetChip Technologies for donating this product ID. | 60 | /* |
61 | * Thanks to NetChip Technologies for donating this product ID. | ||
61 | * | 62 | * |
62 | * DO NOT REUSE THESE IDs with any other driver!! Ever!! | 63 | * DO NOT REUSE THESE IDs with any other driver!! Ever!! |
63 | * Instead: allocate your own, using normal USB-IF procedures. */ | 64 | * Instead: allocate your own, using normal USB-IF procedures. |
65 | */ | ||
64 | #define FSG_VENDOR_ID 0x0525 /* NetChip */ | 66 | #define FSG_VENDOR_ID 0x0525 /* NetChip */ |
65 | #define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ | 67 | #define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ |
66 | 68 | ||
@@ -84,14 +86,27 @@ | |||
84 | #define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args) | 86 | #define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args) |
85 | #define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args) | 87 | #define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args) |
86 | 88 | ||
87 | /* Keep those macros in sync with thos in | 89 | /* |
88 | * include/linux/ubs/composite.h or else GCC will complain. If they | 90 | * Keep those macros in sync with those in |
91 | * include/linux/usb/composite.h or else GCC will complain. If they | ||
89 | * are identical (the same names of arguments, white spaces in the | 92 | * are identical (the same names of arguments, white spaces in the |
90 | * same places) GCC will allow redefinition otherwise (even if some | 93 | * same places) GCC will allow redefinition otherwise (even if some |
91 | * white space is removed or added) warning will be issued. No | 94 | * white space is removed or added) warning will be issued. |
92 | * checking if those symbols is defined is performed because warning | 95 | * |
93 | * is desired when those macros were defined by someone else to mean | 96 | * Those macros are needed here because File Storage Gadget does not |
94 | * something else. */ | 97 | * include the composite.h header. For composite gadgets those macros |
98 | * are redundant since composite.h is included any way. | ||
99 | * | ||
100 | * One could check whether those macros are already defined (which | ||
101 | * would indicate composite.h had been included) or not (which would | ||
102 | * indicate we were in FSG) but this is not done because a warning is | ||
103 | * desired if definitions here differ from the ones in composite.h. | ||
104 | * | ||
105 | * We want the definitions to match and be the same in File Storage | ||
106 | * Gadget as well as Mass Storage Function (and so composite gadgets | ||
107 | * using MSF). If someone changes them in composite.h it will produce | ||
108 | * a warning in this file when building MSF. | ||
109 | */ | ||
95 | #define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args) | 110 | #define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args) |
96 | #define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args) | 111 | #define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args) |
97 | #define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args) | 112 | #define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args) |
@@ -269,6 +284,7 @@ struct fsg_lun { | |||
269 | unsigned int prevent_medium_removal:1; | 284 | unsigned int prevent_medium_removal:1; |
270 | unsigned int registered:1; | 285 | unsigned int registered:1; |
271 | unsigned int info_valid:1; | 286 | unsigned int info_valid:1; |
287 | unsigned int nofua:1; | ||
272 | 288 | ||
273 | u32 sense_data; | 289 | u32 sense_data; |
274 | u32 sense_data_info; | 290 | u32 sense_data_info; |
@@ -313,9 +329,11 @@ struct fsg_buffhd { | |||
313 | enum fsg_buffer_state state; | 329 | enum fsg_buffer_state state; |
314 | struct fsg_buffhd *next; | 330 | struct fsg_buffhd *next; |
315 | 331 | ||
316 | /* The NetChip 2280 is faster, and handles some protocol faults | 332 | /* |
333 | * The NetChip 2280 is faster, and handles some protocol faults | ||
317 | * better, if we don't submit any short bulk-out read requests. | 334 | * better, if we don't submit any short bulk-out read requests. |
318 | * So we will record the intended request length here. */ | 335 | * So we will record the intended request length here. |
336 | */ | ||
319 | unsigned int bulk_out_intended_length; | 337 | unsigned int bulk_out_intended_length; |
320 | 338 | ||
321 | struct usb_request *inreq; | 339 | struct usb_request *inreq; |
@@ -395,8 +413,10 @@ fsg_intf_desc = { | |||
395 | .iInterface = FSG_STRING_INTERFACE, | 413 | .iInterface = FSG_STRING_INTERFACE, |
396 | }; | 414 | }; |
397 | 415 | ||
398 | /* Three full-speed endpoint descriptors: bulk-in, bulk-out, | 416 | /* |
399 | * and interrupt-in. */ | 417 | * Three full-speed endpoint descriptors: bulk-in, bulk-out, and |
418 | * interrupt-in. | ||
419 | */ | ||
400 | 420 | ||
401 | static struct usb_endpoint_descriptor | 421 | static struct usb_endpoint_descriptor |
402 | fsg_fs_bulk_in_desc = { | 422 | fsg_fs_bulk_in_desc = { |
@@ -459,7 +479,7 @@ static struct usb_descriptor_header *fsg_fs_function[] = { | |||
459 | * | 479 | * |
460 | * That means alternate endpoint descriptors (bigger packets) | 480 | * That means alternate endpoint descriptors (bigger packets) |
461 | * and a "device qualifier" ... plus more construction options | 481 | * and a "device qualifier" ... plus more construction options |
462 | * for the config descriptor. | 482 | * for the configuration descriptor. |
463 | */ | 483 | */ |
464 | static struct usb_endpoint_descriptor | 484 | static struct usb_endpoint_descriptor |
465 | fsg_hs_bulk_in_desc = { | 485 | fsg_hs_bulk_in_desc = { |
@@ -547,8 +567,10 @@ static struct usb_gadget_strings fsg_stringtab = { | |||
547 | 567 | ||
548 | /*-------------------------------------------------------------------------*/ | 568 | /*-------------------------------------------------------------------------*/ |
549 | 569 | ||
550 | /* If the next two routines are called while the gadget is registered, | 570 | /* |
551 | * the caller must own fsg->filesem for writing. */ | 571 | * If the next two routines are called while the gadget is registered, |
572 | * the caller must own fsg->filesem for writing. | ||
573 | */ | ||
552 | 574 | ||
553 | static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) | 575 | static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) |
554 | { | 576 | { |
@@ -587,8 +609,10 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) | |||
587 | goto out; | 609 | goto out; |
588 | } | 610 | } |
589 | 611 | ||
590 | /* If we can't read the file, it's no good. | 612 | /* |
591 | * If we can't write the file, use it read-only. */ | 613 | * If we can't read the file, it's no good. |
614 | * If we can't write the file, use it read-only. | ||
615 | */ | ||
592 | if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) { | 616 | if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) { |
593 | LINFO(curlun, "file not readable: %s\n", filename); | 617 | LINFO(curlun, "file not readable: %s\n", filename); |
594 | goto out; | 618 | goto out; |
@@ -646,8 +670,10 @@ static void fsg_lun_close(struct fsg_lun *curlun) | |||
646 | 670 | ||
647 | /*-------------------------------------------------------------------------*/ | 671 | /*-------------------------------------------------------------------------*/ |
648 | 672 | ||
649 | /* Sync the file data, don't bother with the metadata. | 673 | /* |
650 | * This code was copied from fs/buffer.c:sys_fdatasync(). */ | 674 | * Sync the file data, don't bother with the metadata. |
675 | * This code was copied from fs/buffer.c:sys_fdatasync(). | ||
676 | */ | ||
651 | static int fsg_lun_fsync_sub(struct fsg_lun *curlun) | 677 | static int fsg_lun_fsync_sub(struct fsg_lun *curlun) |
652 | { | 678 | { |
653 | struct file *filp = curlun->filp; | 679 | struct file *filp = curlun->filp; |
@@ -689,6 +715,14 @@ static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr, | |||
689 | : curlun->initially_ro); | 715 | : curlun->initially_ro); |
690 | } | 716 | } |
691 | 717 | ||
718 | static ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr, | ||
719 | char *buf) | ||
720 | { | ||
721 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); | ||
722 | |||
723 | return sprintf(buf, "%u\n", curlun->nofua); | ||
724 | } | ||
725 | |||
692 | static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr, | 726 | static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr, |
693 | char *buf) | 727 | char *buf) |
694 | { | 728 | { |
@@ -723,26 +757,47 @@ static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr, | |||
723 | ssize_t rc = count; | 757 | ssize_t rc = count; |
724 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); | 758 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); |
725 | struct rw_semaphore *filesem = dev_get_drvdata(dev); | 759 | struct rw_semaphore *filesem = dev_get_drvdata(dev); |
726 | int i; | 760 | unsigned long ro; |
727 | 761 | ||
728 | if (sscanf(buf, "%d", &i) != 1) | 762 | if (strict_strtoul(buf, 2, &ro)) |
729 | return -EINVAL; | 763 | return -EINVAL; |
730 | 764 | ||
731 | /* Allow the write-enable status to change only while the backing file | 765 | /* |
732 | * is closed. */ | 766 | * Allow the write-enable status to change only while the |
767 | * backing file is closed. | ||
768 | */ | ||
733 | down_read(filesem); | 769 | down_read(filesem); |
734 | if (fsg_lun_is_open(curlun)) { | 770 | if (fsg_lun_is_open(curlun)) { |
735 | LDBG(curlun, "read-only status change prevented\n"); | 771 | LDBG(curlun, "read-only status change prevented\n"); |
736 | rc = -EBUSY; | 772 | rc = -EBUSY; |
737 | } else { | 773 | } else { |
738 | curlun->ro = !!i; | 774 | curlun->ro = ro; |
739 | curlun->initially_ro = !!i; | 775 | curlun->initially_ro = ro; |
740 | LDBG(curlun, "read-only status set to %d\n", curlun->ro); | 776 | LDBG(curlun, "read-only status set to %d\n", curlun->ro); |
741 | } | 777 | } |
742 | up_read(filesem); | 778 | up_read(filesem); |
743 | return rc; | 779 | return rc; |
744 | } | 780 | } |
745 | 781 | ||
782 | static ssize_t fsg_store_nofua(struct device *dev, | ||
783 | struct device_attribute *attr, | ||
784 | const char *buf, size_t count) | ||
785 | { | ||
786 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); | ||
787 | unsigned long nofua; | ||
788 | |||
789 | if (strict_strtoul(buf, 2, &nofua)) | ||
790 | return -EINVAL; | ||
791 | |||
792 | /* Sync data when switching from async mode to sync */ | ||
793 | if (!nofua && curlun->nofua) | ||
794 | fsg_lun_fsync_sub(curlun); | ||
795 | |||
796 | curlun->nofua = nofua; | ||
797 | |||
798 | return count; | ||
799 | } | ||
800 | |||
746 | static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr, | 801 | static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr, |
747 | const char *buf, size_t count) | 802 | const char *buf, size_t count) |
748 | { | 803 | { |
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 1da755a1c855..6bb876d65252 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c | |||
@@ -704,17 +704,6 @@ static char *host_addr; | |||
704 | module_param(host_addr, charp, S_IRUGO); | 704 | module_param(host_addr, charp, S_IRUGO); |
705 | MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); | 705 | MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); |
706 | 706 | ||
707 | |||
708 | static u8 __init nibble(unsigned char c) | ||
709 | { | ||
710 | if (isdigit(c)) | ||
711 | return c - '0'; | ||
712 | c = toupper(c); | ||
713 | if (isxdigit(c)) | ||
714 | return 10 + c - 'A'; | ||
715 | return 0; | ||
716 | } | ||
717 | |||
718 | static int get_ether_addr(const char *str, u8 *dev_addr) | 707 | static int get_ether_addr(const char *str, u8 *dev_addr) |
719 | { | 708 | { |
720 | if (str) { | 709 | if (str) { |
@@ -725,8 +714,8 @@ static int get_ether_addr(const char *str, u8 *dev_addr) | |||
725 | 714 | ||
726 | if ((*str == '.') || (*str == ':')) | 715 | if ((*str == '.') || (*str == ':')) |
727 | str++; | 716 | str++; |
728 | num = nibble(*str++) << 4; | 717 | num = hex_to_bin(*str++) << 4; |
729 | num |= (nibble(*str++)); | 718 | num |= hex_to_bin(*str++); |
730 | dev_addr [i] = num; | 719 | dev_addr [i] = num; |
731 | } | 720 | } |
732 | if (is_valid_ether_addr(dev_addr)) | 721 | if (is_valid_ether_addr(dev_addr)) |
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 3e8dcb5455e3..01e5354a4c20 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c | |||
@@ -18,6 +18,7 @@ | |||
18 | /* #define VERBOSE_DEBUG */ | 18 | /* #define VERBOSE_DEBUG */ |
19 | 19 | ||
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/sched.h> | ||
21 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
22 | #include <linux/device.h> | 23 | #include <linux/device.h> |
23 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index 288d21155abe..de1deb7a3c63 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c | |||
@@ -308,7 +308,7 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = { | |||
308 | * USB configuration | 308 | * USB configuration |
309 | */ | 309 | */ |
310 | 310 | ||
311 | static int __init | 311 | static int __ref |
312 | webcam_config_bind(struct usb_configuration *c) | 312 | webcam_config_bind(struct usb_configuration *c) |
313 | { | 313 | { |
314 | return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls, | 314 | return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls, |
@@ -330,7 +330,7 @@ webcam_unbind(struct usb_composite_dev *cdev) | |||
330 | return 0; | 330 | return 0; |
331 | } | 331 | } |
332 | 332 | ||
333 | static int __init | 333 | static int __ref |
334 | webcam_bind(struct usb_composite_dev *cdev) | 334 | webcam_bind(struct usb_composite_dev *cdev) |
335 | { | 335 | { |
336 | int ret; | 336 | int ret; |
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 807280d069f9..cf353920bb1c 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c | |||
@@ -264,7 +264,7 @@ static void zero_resume(struct usb_composite_dev *cdev) | |||
264 | 264 | ||
265 | /*-------------------------------------------------------------------------*/ | 265 | /*-------------------------------------------------------------------------*/ |
266 | 266 | ||
267 | static int __init zero_bind(struct usb_composite_dev *cdev) | 267 | static int __ref zero_bind(struct usb_composite_dev *cdev) |
268 | { | 268 | { |
269 | int gcnum; | 269 | int gcnum; |
270 | struct usb_gadget *gadget = cdev->gadget; | 270 | struct usb_gadget *gadget = cdev->gadget; |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f865be2276d4..2d926cec0725 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -72,8 +72,9 @@ config USB_EHCI_ROOT_HUB_TT | |||
72 | from ARC, and has since changed hands a few times. | 72 | from ARC, and has since changed hands a few times. |
73 | 73 | ||
74 | config USB_EHCI_TT_NEWSCHED | 74 | config USB_EHCI_TT_NEWSCHED |
75 | bool "Improved Transaction Translator scheduling (EXPERIMENTAL)" | 75 | bool "Improved Transaction Translator scheduling" |
76 | depends on USB_EHCI_HCD && EXPERIMENTAL | 76 | depends on USB_EHCI_HCD |
77 | default y | ||
77 | ---help--- | 78 | ---help--- |
78 | This changes the periodic scheduling code to fill more of the low | 79 | This changes the periodic scheduling code to fill more of the low |
79 | and full speed bandwidth available from the Transaction Translator | 80 | and full speed bandwidth available from the Transaction Translator |
@@ -84,9 +85,11 @@ config USB_EHCI_TT_NEWSCHED | |||
84 | If you have multiple periodic low/fullspeed devices connected to a | 85 | If you have multiple periodic low/fullspeed devices connected to a |
85 | highspeed USB hub which is connected to a highspeed USB Host | 86 | highspeed USB hub which is connected to a highspeed USB Host |
86 | Controller, and some of those devices will not work correctly | 87 | Controller, and some of those devices will not work correctly |
87 | (possibly due to "ENOSPC" or "-28" errors), say Y. | 88 | (possibly due to "ENOSPC" or "-28" errors), say Y. Conversely, if |
89 | you have only one such device and it doesn't work, you could try | ||
90 | saying N. | ||
88 | 91 | ||
89 | If unsure, say N. | 92 | If unsure, say Y. |
90 | 93 | ||
91 | config USB_EHCI_BIG_ENDIAN_MMIO | 94 | config USB_EHCI_BIG_ENDIAN_MMIO |
92 | bool | 95 | bool |
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index faa61748db70..2baf8a849086 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c | |||
@@ -228,7 +228,7 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) | |||
228 | * the root hub is either suspended or stopped. | 228 | * the root hub is either suspended or stopped. |
229 | */ | 229 | */ |
230 | spin_lock_irqsave(&ehci->lock, flags); | 230 | spin_lock_irqsave(&ehci->lock, flags); |
231 | ehci_prepare_ports_for_controller_suspend(ehci); | 231 | ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); |
232 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); | 232 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
233 | (void)ehci_readl(ehci, &ehci->regs->intr_enable); | 233 | (void)ehci_readl(ehci, &ehci->regs->intr_enable); |
234 | 234 | ||
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 874d2000bf92..76b7fd2d838a 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
@@ -98,13 +98,18 @@ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) | |||
98 | HCC_64BIT_ADDR(params) ? " 64 bit addr" : ""); | 98 | HCC_64BIT_ADDR(params) ? " 64 bit addr" : ""); |
99 | } else { | 99 | } else { |
100 | ehci_dbg (ehci, | 100 | ehci_dbg (ehci, |
101 | "%s hcc_params %04x thresh %d uframes %s%s%s\n", | 101 | "%s hcc_params %04x thresh %d uframes %s%s%s%s%s%s%s\n", |
102 | label, | 102 | label, |
103 | params, | 103 | params, |
104 | HCC_ISOC_THRES(params), | 104 | HCC_ISOC_THRES(params), |
105 | HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", | 105 | HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", |
106 | HCC_CANPARK(params) ? " park" : "", | 106 | HCC_CANPARK(params) ? " park" : "", |
107 | HCC_64BIT_ADDR(params) ? " 64 bit addr" : ""); | 107 | HCC_64BIT_ADDR(params) ? " 64 bit addr" : "", |
108 | HCC_LPM(params) ? " LPM" : "", | ||
109 | HCC_PER_PORT_CHANGE_EVENT(params) ? " ppce" : "", | ||
110 | HCC_HW_PREFETCH(params) ? " hw prefetch" : "", | ||
111 | HCC_32FRAME_PERIODIC_LIST(params) ? | ||
112 | " 32 peridic list" : ""); | ||
108 | } | 113 | } |
109 | } | 114 | } |
110 | #else | 115 | #else |
@@ -191,8 +196,9 @@ static int __maybe_unused | |||
191 | dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) | 196 | dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) |
192 | { | 197 | { |
193 | return scnprintf (buf, len, | 198 | return scnprintf (buf, len, |
194 | "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s", | 199 | "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s%s", |
195 | label, label [0] ? " " : "", status, | 200 | label, label [0] ? " " : "", status, |
201 | (status & STS_PPCE_MASK) ? " PPCE" : "", | ||
196 | (status & STS_ASS) ? " Async" : "", | 202 | (status & STS_ASS) ? " Async" : "", |
197 | (status & STS_PSS) ? " Periodic" : "", | 203 | (status & STS_PSS) ? " Periodic" : "", |
198 | (status & STS_RECL) ? " Recl" : "", | 204 | (status & STS_RECL) ? " Recl" : "", |
@@ -210,8 +216,9 @@ static int __maybe_unused | |||
210 | dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) | 216 | dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) |
211 | { | 217 | { |
212 | return scnprintf (buf, len, | 218 | return scnprintf (buf, len, |
213 | "%s%sintrenable %02x%s%s%s%s%s%s", | 219 | "%s%sintrenable %02x%s%s%s%s%s%s%s", |
214 | label, label [0] ? " " : "", enable, | 220 | label, label [0] ? " " : "", enable, |
221 | (enable & STS_PPCE_MASK) ? " PPCE" : "", | ||
215 | (enable & STS_IAA) ? " IAA" : "", | 222 | (enable & STS_IAA) ? " IAA" : "", |
216 | (enable & STS_FATAL) ? " FATAL" : "", | 223 | (enable & STS_FATAL) ? " FATAL" : "", |
217 | (enable & STS_FLR) ? " FLR" : "", | 224 | (enable & STS_FLR) ? " FLR" : "", |
@@ -228,9 +235,15 @@ static int | |||
228 | dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) | 235 | dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) |
229 | { | 236 | { |
230 | return scnprintf (buf, len, | 237 | return scnprintf (buf, len, |
231 | "%s%scommand %06x %s=%d ithresh=%d%s%s%s%s period=%s%s %s", | 238 | "%s%scommand %07x %s%s%s%s%s%s=%d ithresh=%d%s%s%s%s " |
239 | "period=%s%s %s", | ||
232 | label, label [0] ? " " : "", command, | 240 | label, label [0] ? " " : "", command, |
233 | (command & CMD_PARK) ? "park" : "(park)", | 241 | (command & CMD_HIRD) ? " HIRD" : "", |
242 | (command & CMD_PPCEE) ? " PPCEE" : "", | ||
243 | (command & CMD_FSP) ? " FSP" : "", | ||
244 | (command & CMD_ASPE) ? " ASPE" : "", | ||
245 | (command & CMD_PSPE) ? " PSPE" : "", | ||
246 | (command & CMD_PARK) ? " park" : "(park)", | ||
234 | CMD_PARK_CNT (command), | 247 | CMD_PARK_CNT (command), |
235 | (command >> 16) & 0x3f, | 248 | (command >> 16) & 0x3f, |
236 | (command & CMD_LRESET) ? " LReset" : "", | 249 | (command & CMD_LRESET) ? " LReset" : "", |
@@ -257,11 +270,22 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) | |||
257 | } | 270 | } |
258 | 271 | ||
259 | return scnprintf (buf, len, | 272 | return scnprintf (buf, len, |
260 | "%s%sport %d status %06x%s%s sig=%s%s%s%s%s%s%s%s%s%s", | 273 | "%s%sport:%d status %06x %d %s%s%s%s%s%s " |
274 | "sig=%s%s%s%s%s%s%s%s%s%s%s", | ||
261 | label, label [0] ? " " : "", port, status, | 275 | label, label [0] ? " " : "", port, status, |
276 | status>>25,/*device address */ | ||
277 | (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ACK ? | ||
278 | " ACK" : "", | ||
279 | (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_NYET ? | ||
280 | " NYET" : "", | ||
281 | (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_STALL ? | ||
282 | " STALL" : "", | ||
283 | (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ERR ? | ||
284 | " ERR" : "", | ||
262 | (status & PORT_POWER) ? " POWER" : "", | 285 | (status & PORT_POWER) ? " POWER" : "", |
263 | (status & PORT_OWNER) ? " OWNER" : "", | 286 | (status & PORT_OWNER) ? " OWNER" : "", |
264 | sig, | 287 | sig, |
288 | (status & PORT_LPM) ? " LPM" : "", | ||
265 | (status & PORT_RESET) ? " RESET" : "", | 289 | (status & PORT_RESET) ? " RESET" : "", |
266 | (status & PORT_SUSPEND) ? " SUSPEND" : "", | 290 | (status & PORT_SUSPEND) ? " SUSPEND" : "", |
267 | (status & PORT_RESUME) ? " RESUME" : "", | 291 | (status & PORT_RESUME) ? " RESUME" : "", |
@@ -330,6 +354,13 @@ static int debug_async_open(struct inode *, struct file *); | |||
330 | static int debug_periodic_open(struct inode *, struct file *); | 354 | static int debug_periodic_open(struct inode *, struct file *); |
331 | static int debug_registers_open(struct inode *, struct file *); | 355 | static int debug_registers_open(struct inode *, struct file *); |
332 | static int debug_async_open(struct inode *, struct file *); | 356 | static int debug_async_open(struct inode *, struct file *); |
357 | static int debug_lpm_open(struct inode *, struct file *); | ||
358 | static ssize_t debug_lpm_read(struct file *file, char __user *user_buf, | ||
359 | size_t count, loff_t *ppos); | ||
360 | static ssize_t debug_lpm_write(struct file *file, const char __user *buffer, | ||
361 | size_t count, loff_t *ppos); | ||
362 | static int debug_lpm_close(struct inode *inode, struct file *file); | ||
363 | |||
333 | static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); | 364 | static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); |
334 | static int debug_close(struct inode *, struct file *); | 365 | static int debug_close(struct inode *, struct file *); |
335 | 366 | ||
@@ -351,6 +382,13 @@ static const struct file_operations debug_registers_fops = { | |||
351 | .read = debug_output, | 382 | .read = debug_output, |
352 | .release = debug_close, | 383 | .release = debug_close, |
353 | }; | 384 | }; |
385 | static const struct file_operations debug_lpm_fops = { | ||
386 | .owner = THIS_MODULE, | ||
387 | .open = debug_lpm_open, | ||
388 | .read = debug_lpm_read, | ||
389 | .write = debug_lpm_write, | ||
390 | .release = debug_lpm_close, | ||
391 | }; | ||
354 | 392 | ||
355 | static struct dentry *ehci_debug_root; | 393 | static struct dentry *ehci_debug_root; |
356 | 394 | ||
@@ -674,7 +712,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) | |||
674 | 712 | ||
675 | spin_lock_irqsave (&ehci->lock, flags); | 713 | spin_lock_irqsave (&ehci->lock, flags); |
676 | 714 | ||
677 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | 715 | if (!HCD_HW_ACCESSIBLE(hcd)) { |
678 | size = scnprintf (next, size, | 716 | size = scnprintf (next, size, |
679 | "bus %s, device %s\n" | 717 | "bus %s, device %s\n" |
680 | "%s\n" | 718 | "%s\n" |
@@ -917,51 +955,127 @@ static int debug_registers_open(struct inode *inode, struct file *file) | |||
917 | return file->private_data ? 0 : -ENOMEM; | 955 | return file->private_data ? 0 : -ENOMEM; |
918 | } | 956 | } |
919 | 957 | ||
958 | static int debug_lpm_open(struct inode *inode, struct file *file) | ||
959 | { | ||
960 | file->private_data = inode->i_private; | ||
961 | return 0; | ||
962 | } | ||
963 | |||
964 | static int debug_lpm_close(struct inode *inode, struct file *file) | ||
965 | { | ||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | static ssize_t debug_lpm_read(struct file *file, char __user *user_buf, | ||
970 | size_t count, loff_t *ppos) | ||
971 | { | ||
972 | /* TODO: show lpm stats */ | ||
973 | return 0; | ||
974 | } | ||
975 | |||
976 | static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf, | ||
977 | size_t count, loff_t *ppos) | ||
978 | { | ||
979 | struct usb_hcd *hcd; | ||
980 | struct ehci_hcd *ehci; | ||
981 | char buf[50]; | ||
982 | size_t len; | ||
983 | u32 temp; | ||
984 | unsigned long port; | ||
985 | u32 __iomem *portsc ; | ||
986 | u32 params; | ||
987 | |||
988 | hcd = bus_to_hcd(file->private_data); | ||
989 | ehci = hcd_to_ehci(hcd); | ||
990 | |||
991 | len = min(count, sizeof(buf) - 1); | ||
992 | if (copy_from_user(buf, user_buf, len)) | ||
993 | return -EFAULT; | ||
994 | buf[len] = '\0'; | ||
995 | if (len > 0 && buf[len - 1] == '\n') | ||
996 | buf[len - 1] = '\0'; | ||
997 | |||
998 | if (strncmp(buf, "enable", 5) == 0) { | ||
999 | if (strict_strtoul(buf + 7, 10, &port)) | ||
1000 | return -EINVAL; | ||
1001 | params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
1002 | if (port > HCS_N_PORTS(params)) { | ||
1003 | ehci_dbg(ehci, "ERR: LPM on bad port %lu\n", port); | ||
1004 | return -ENODEV; | ||
1005 | } | ||
1006 | portsc = &ehci->regs->port_status[port-1]; | ||
1007 | temp = ehci_readl(ehci, portsc); | ||
1008 | if (!(temp & PORT_DEV_ADDR)) { | ||
1009 | ehci_dbg(ehci, "LPM: no device attached\n"); | ||
1010 | return -ENODEV; | ||
1011 | } | ||
1012 | temp |= PORT_LPM; | ||
1013 | ehci_writel(ehci, temp, portsc); | ||
1014 | printk(KERN_INFO "force enable LPM for port %lu\n", port); | ||
1015 | } else if (strncmp(buf, "hird=", 5) == 0) { | ||
1016 | unsigned long hird; | ||
1017 | if (strict_strtoul(buf + 5, 16, &hird)) | ||
1018 | return -EINVAL; | ||
1019 | printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird); | ||
1020 | temp = ehci_readl(ehci, &ehci->regs->command); | ||
1021 | temp &= ~CMD_HIRD; | ||
1022 | temp |= hird << 24; | ||
1023 | ehci_writel(ehci, temp, &ehci->regs->command); | ||
1024 | } else if (strncmp(buf, "disable", 7) == 0) { | ||
1025 | if (strict_strtoul(buf + 8, 10, &port)) | ||
1026 | return -EINVAL; | ||
1027 | params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
1028 | if (port > HCS_N_PORTS(params)) { | ||
1029 | ehci_dbg(ehci, "ERR: LPM off bad port %lu\n", port); | ||
1030 | return -ENODEV; | ||
1031 | } | ||
1032 | portsc = &ehci->regs->port_status[port-1]; | ||
1033 | temp = ehci_readl(ehci, portsc); | ||
1034 | if (!(temp & PORT_DEV_ADDR)) { | ||
1035 | ehci_dbg(ehci, "ERR: no device attached\n"); | ||
1036 | return -ENODEV; | ||
1037 | } | ||
1038 | temp &= ~PORT_LPM; | ||
1039 | ehci_writel(ehci, temp, portsc); | ||
1040 | printk(KERN_INFO "disabled LPM for port %lu\n", port); | ||
1041 | } else | ||
1042 | return -EOPNOTSUPP; | ||
1043 | return count; | ||
1044 | } | ||
1045 | |||
920 | static inline void create_debug_files (struct ehci_hcd *ehci) | 1046 | static inline void create_debug_files (struct ehci_hcd *ehci) |
921 | { | 1047 | { |
922 | struct usb_bus *bus = &ehci_to_hcd(ehci)->self; | 1048 | struct usb_bus *bus = &ehci_to_hcd(ehci)->self; |
923 | 1049 | ||
924 | ehci->debug_dir = debugfs_create_dir(bus->bus_name, ehci_debug_root); | 1050 | ehci->debug_dir = debugfs_create_dir(bus->bus_name, ehci_debug_root); |
925 | if (!ehci->debug_dir) | 1051 | if (!ehci->debug_dir) |
926 | goto dir_error; | 1052 | return; |
927 | 1053 | ||
928 | ehci->debug_async = debugfs_create_file("async", S_IRUGO, | 1054 | if (!debugfs_create_file("async", S_IRUGO, ehci->debug_dir, bus, |
929 | ehci->debug_dir, bus, | 1055 | &debug_async_fops)) |
930 | &debug_async_fops); | 1056 | goto file_error; |
931 | if (!ehci->debug_async) | 1057 | |
932 | goto async_error; | 1058 | if (!debugfs_create_file("periodic", S_IRUGO, ehci->debug_dir, bus, |
933 | 1059 | &debug_periodic_fops)) | |
934 | ehci->debug_periodic = debugfs_create_file("periodic", S_IRUGO, | 1060 | goto file_error; |
935 | ehci->debug_dir, bus, | 1061 | |
936 | &debug_periodic_fops); | 1062 | if (!debugfs_create_file("registers", S_IRUGO, ehci->debug_dir, bus, |
937 | if (!ehci->debug_periodic) | 1063 | &debug_registers_fops)) |
938 | goto periodic_error; | 1064 | goto file_error; |
939 | 1065 | ||
940 | ehci->debug_registers = debugfs_create_file("registers", S_IRUGO, | 1066 | if (!debugfs_create_file("lpm", S_IRUGO|S_IWUGO, ehci->debug_dir, bus, |
941 | ehci->debug_dir, bus, | 1067 | &debug_lpm_fops)) |
942 | &debug_registers_fops); | 1068 | goto file_error; |
943 | if (!ehci->debug_registers) | 1069 | |
944 | goto registers_error; | ||
945 | return; | 1070 | return; |
946 | 1071 | ||
947 | registers_error: | 1072 | file_error: |
948 | debugfs_remove(ehci->debug_periodic); | 1073 | debugfs_remove_recursive(ehci->debug_dir); |
949 | periodic_error: | ||
950 | debugfs_remove(ehci->debug_async); | ||
951 | async_error: | ||
952 | debugfs_remove(ehci->debug_dir); | ||
953 | dir_error: | ||
954 | ehci->debug_periodic = NULL; | ||
955 | ehci->debug_async = NULL; | ||
956 | ehci->debug_dir = NULL; | ||
957 | } | 1074 | } |
958 | 1075 | ||
959 | static inline void remove_debug_files (struct ehci_hcd *ehci) | 1076 | static inline void remove_debug_files (struct ehci_hcd *ehci) |
960 | { | 1077 | { |
961 | debugfs_remove(ehci->debug_registers); | 1078 | debugfs_remove_recursive(ehci->debug_dir); |
962 | debugfs_remove(ehci->debug_periodic); | ||
963 | debugfs_remove(ehci->debug_async); | ||
964 | debugfs_remove(ehci->debug_dir); | ||
965 | } | 1079 | } |
966 | 1080 | ||
967 | #endif /* STUB_DEBUG_FILES */ | 1081 | #endif /* STUB_DEBUG_FILES */ |
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 5cd967d28938..a416421abfa2 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -313,7 +313,8 @@ static int ehci_fsl_drv_suspend(struct device *dev) | |||
313 | struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd); | 313 | struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd); |
314 | void __iomem *non_ehci = hcd->regs; | 314 | void __iomem *non_ehci = hcd->regs; |
315 | 315 | ||
316 | ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd)); | 316 | ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), |
317 | device_may_wakeup(dev)); | ||
317 | if (!fsl_deep_sleep()) | 318 | if (!fsl_deep_sleep()) |
318 | return 0; | 319 | return 0; |
319 | 320 | ||
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a3ef2a9d9dc2..34a928d3b7d2 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/dma-mapping.h> | 36 | #include <linux/dma-mapping.h> |
37 | #include <linux/debugfs.h> | 37 | #include <linux/debugfs.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/uaccess.h> | ||
39 | 40 | ||
40 | #include <asm/byteorder.h> | 41 | #include <asm/byteorder.h> |
41 | #include <asm/io.h> | 42 | #include <asm/io.h> |
@@ -78,7 +79,13 @@ static const char hcd_name [] = "ehci_hcd"; | |||
78 | #define EHCI_TUNE_RL_TT 0 | 79 | #define EHCI_TUNE_RL_TT 0 |
79 | #define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ | 80 | #define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ |
80 | #define EHCI_TUNE_MULT_TT 1 | 81 | #define EHCI_TUNE_MULT_TT 1 |
81 | #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ | 82 | /* |
83 | * Some drivers think it's safe to schedule isochronous transfers more than | ||
84 | * 256 ms into the future (partly as a result of an old bug in the scheduling | ||
85 | * code). In an attempt to avoid trouble, we will use a minimum scheduling | ||
86 | * length of 512 frames instead of 256. | ||
87 | */ | ||
88 | #define EHCI_TUNE_FLS 1 /* (medium) 512-frame schedule */ | ||
82 | 89 | ||
83 | #define EHCI_IAA_MSECS 10 /* arbitrary */ | 90 | #define EHCI_IAA_MSECS 10 /* arbitrary */ |
84 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ | 91 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ |
@@ -100,6 +107,11 @@ static int ignore_oc = 0; | |||
100 | module_param (ignore_oc, bool, S_IRUGO); | 107 | module_param (ignore_oc, bool, S_IRUGO); |
101 | MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); | 108 | MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); |
102 | 109 | ||
110 | /* for link power management(LPM) feature */ | ||
111 | static unsigned int hird; | ||
112 | module_param(hird, int, S_IRUGO); | ||
113 | MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us\n"); | ||
114 | |||
103 | #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) | 115 | #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) |
104 | 116 | ||
105 | /*-------------------------------------------------------------------------*/ | 117 | /*-------------------------------------------------------------------------*/ |
@@ -304,6 +316,7 @@ static void end_unlink_async(struct ehci_hcd *ehci); | |||
304 | static void ehci_work(struct ehci_hcd *ehci); | 316 | static void ehci_work(struct ehci_hcd *ehci); |
305 | 317 | ||
306 | #include "ehci-hub.c" | 318 | #include "ehci-hub.c" |
319 | #include "ehci-lpm.c" | ||
307 | #include "ehci-mem.c" | 320 | #include "ehci-mem.c" |
308 | #include "ehci-q.c" | 321 | #include "ehci-q.c" |
309 | #include "ehci-sched.c" | 322 | #include "ehci-sched.c" |
@@ -577,6 +590,11 @@ static int ehci_init(struct usb_hcd *hcd) | |||
577 | if (log2_irq_thresh < 0 || log2_irq_thresh > 6) | 590 | if (log2_irq_thresh < 0 || log2_irq_thresh > 6) |
578 | log2_irq_thresh = 0; | 591 | log2_irq_thresh = 0; |
579 | temp = 1 << (16 + log2_irq_thresh); | 592 | temp = 1 << (16 + log2_irq_thresh); |
593 | if (HCC_PER_PORT_CHANGE_EVENT(hcc_params)) { | ||
594 | ehci->has_ppcd = 1; | ||
595 | ehci_dbg(ehci, "enable per-port change event\n"); | ||
596 | temp |= CMD_PPCEE; | ||
597 | } | ||
580 | if (HCC_CANPARK(hcc_params)) { | 598 | if (HCC_CANPARK(hcc_params)) { |
581 | /* HW default park == 3, on hardware that supports it (like | 599 | /* HW default park == 3, on hardware that supports it (like |
582 | * NVidia and ALI silicon), maximizes throughput on the async | 600 | * NVidia and ALI silicon), maximizes throughput on the async |
@@ -603,10 +621,22 @@ static int ehci_init(struct usb_hcd *hcd) | |||
603 | default: BUG(); | 621 | default: BUG(); |
604 | } | 622 | } |
605 | } | 623 | } |
624 | if (HCC_LPM(hcc_params)) { | ||
625 | /* support link power management EHCI 1.1 addendum */ | ||
626 | ehci_dbg(ehci, "support lpm\n"); | ||
627 | ehci->has_lpm = 1; | ||
628 | if (hird > 0xf) { | ||
629 | ehci_dbg(ehci, "hird %d invalid, use default 0", | ||
630 | hird); | ||
631 | hird = 0; | ||
632 | } | ||
633 | temp |= hird << 24; | ||
634 | } | ||
606 | ehci->command = temp; | 635 | ehci->command = temp; |
607 | 636 | ||
608 | /* Accept arbitrarily long scatter-gather lists */ | 637 | /* Accept arbitrarily long scatter-gather lists */ |
609 | hcd->self.sg_tablesize = ~0; | 638 | if (!(hcd->driver->flags & HCD_LOCAL_MEM)) |
639 | hcd->self.sg_tablesize = ~0; | ||
610 | return 0; | 640 | return 0; |
611 | } | 641 | } |
612 | 642 | ||
@@ -619,7 +649,6 @@ static int ehci_run (struct usb_hcd *hcd) | |||
619 | u32 hcc_params; | 649 | u32 hcc_params; |
620 | 650 | ||
621 | hcd->uses_new_polling = 1; | 651 | hcd->uses_new_polling = 1; |
622 | hcd->poll_rh = 0; | ||
623 | 652 | ||
624 | /* EHCI spec section 4.1 */ | 653 | /* EHCI spec section 4.1 */ |
625 | if ((retval = ehci_reset(ehci)) != 0) { | 654 | if ((retval = ehci_reset(ehci)) != 0) { |
@@ -764,6 +793,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
764 | /* remote wakeup [4.3.1] */ | 793 | /* remote wakeup [4.3.1] */ |
765 | if (status & STS_PCD) { | 794 | if (status & STS_PCD) { |
766 | unsigned i = HCS_N_PORTS (ehci->hcs_params); | 795 | unsigned i = HCS_N_PORTS (ehci->hcs_params); |
796 | u32 ppcd = 0; | ||
767 | 797 | ||
768 | /* kick root hub later */ | 798 | /* kick root hub later */ |
769 | pcd_status = status; | 799 | pcd_status = status; |
@@ -772,9 +802,18 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
772 | if (!(cmd & CMD_RUN)) | 802 | if (!(cmd & CMD_RUN)) |
773 | usb_hcd_resume_root_hub(hcd); | 803 | usb_hcd_resume_root_hub(hcd); |
774 | 804 | ||
805 | /* get per-port change detect bits */ | ||
806 | if (ehci->has_ppcd) | ||
807 | ppcd = status >> 16; | ||
808 | |||
775 | while (i--) { | 809 | while (i--) { |
776 | int pstatus = ehci_readl(ehci, | 810 | int pstatus; |
777 | &ehci->regs->port_status [i]); | 811 | |
812 | /* leverage per-port change bits feature */ | ||
813 | if (ehci->has_ppcd && !(ppcd & (1 << i))) | ||
814 | continue; | ||
815 | pstatus = ehci_readl(ehci, | ||
816 | &ehci->regs->port_status[i]); | ||
778 | 817 | ||
779 | if (pstatus & PORT_OWNER) | 818 | if (pstatus & PORT_OWNER) |
780 | continue; | 819 | continue; |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index e7d3d8def282..796ea0c8900f 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -107,7 +107,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) | |||
107 | } | 107 | } |
108 | 108 | ||
109 | static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | 109 | static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, |
110 | bool suspending) | 110 | bool suspending, bool do_wakeup) |
111 | { | 111 | { |
112 | int port; | 112 | int port; |
113 | u32 temp; | 113 | u32 temp; |
@@ -117,8 +117,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | |||
117 | * when the controller is suspended or resumed. In all other | 117 | * when the controller is suspended or resumed. In all other |
118 | * cases they don't need to be changed. | 118 | * cases they don't need to be changed. |
119 | */ | 119 | */ |
120 | if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || | 120 | if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup) |
121 | device_may_wakeup(ehci_to_hcd(ehci)->self.controller)) | ||
122 | return; | 121 | return; |
123 | 122 | ||
124 | /* clear phy low-power mode before changing wakeup flags */ | 123 | /* clear phy low-power mode before changing wakeup flags */ |
@@ -167,6 +166,10 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | |||
167 | ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); | 166 | ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); |
168 | } | 167 | } |
169 | } | 168 | } |
169 | |||
170 | /* Does the root hub have a port wakeup pending? */ | ||
171 | if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD)) | ||
172 | usb_hcd_resume_root_hub(ehci_to_hcd(ehci)); | ||
170 | } | 173 | } |
171 | 174 | ||
172 | static int ehci_bus_suspend (struct usb_hcd *hcd) | 175 | static int ehci_bus_suspend (struct usb_hcd *hcd) |
@@ -316,7 +319,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
316 | if (time_before (jiffies, ehci->next_statechange)) | 319 | if (time_before (jiffies, ehci->next_statechange)) |
317 | msleep(5); | 320 | msleep(5); |
318 | spin_lock_irq (&ehci->lock); | 321 | spin_lock_irq (&ehci->lock); |
319 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | 322 | if (!HCD_HW_ACCESSIBLE(hcd)) { |
320 | spin_unlock_irq(&ehci->lock); | 323 | spin_unlock_irq(&ehci->lock); |
321 | return -ESHUTDOWN; | 324 | return -ESHUTDOWN; |
322 | } | 325 | } |
@@ -603,6 +606,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
603 | u32 mask; | 606 | u32 mask; |
604 | int ports, i, retval = 1; | 607 | int ports, i, retval = 1; |
605 | unsigned long flags; | 608 | unsigned long flags; |
609 | u32 ppcd = 0; | ||
606 | 610 | ||
607 | /* if !USB_SUSPEND, root hub timers won't get shut down ... */ | 611 | /* if !USB_SUSPEND, root hub timers won't get shut down ... */ |
608 | if (!HC_IS_RUNNING(hcd->state)) | 612 | if (!HC_IS_RUNNING(hcd->state)) |
@@ -632,7 +636,15 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
632 | 636 | ||
633 | /* port N changes (bit N)? */ | 637 | /* port N changes (bit N)? */ |
634 | spin_lock_irqsave (&ehci->lock, flags); | 638 | spin_lock_irqsave (&ehci->lock, flags); |
639 | |||
640 | /* get per-port change detect bits */ | ||
641 | if (ehci->has_ppcd) | ||
642 | ppcd = ehci_readl(ehci, &ehci->regs->status) >> 16; | ||
643 | |||
635 | for (i = 0; i < ports; i++) { | 644 | for (i = 0; i < ports; i++) { |
645 | /* leverage per-port change bits feature */ | ||
646 | if (ehci->has_ppcd && !(ppcd & (1 << i))) | ||
647 | continue; | ||
636 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); | 648 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); |
637 | 649 | ||
638 | /* | 650 | /* |
@@ -790,6 +802,11 @@ static int ehci_hub_control ( | |||
790 | status_reg); | 802 | status_reg); |
791 | break; | 803 | break; |
792 | case USB_PORT_FEAT_C_CONNECTION: | 804 | case USB_PORT_FEAT_C_CONNECTION: |
805 | if (ehci->has_lpm) { | ||
806 | /* clear PORTSC bits on disconnect */ | ||
807 | temp &= ~PORT_LPM; | ||
808 | temp &= ~PORT_DEV_ADDR; | ||
809 | } | ||
793 | ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC, | 810 | ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC, |
794 | status_reg); | 811 | status_reg); |
795 | break; | 812 | break; |
diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c new file mode 100644 index 000000000000..b4d4d63c13ed --- /dev/null +++ b/drivers/usb/host/ehci-lpm.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /* ehci-lpm.c EHCI HCD LPM support code | ||
2 | * Copyright (c) 2008 - 2010, Intel Corporation. | ||
3 | * Author: Jacob Pan <jacob.jun.pan@intel.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | /* this file is part of ehci-hcd.c */ | ||
20 | static int ehci_lpm_set_da(struct ehci_hcd *ehci, int dev_addr, int port_num) | ||
21 | { | ||
22 | u32 __iomem portsc; | ||
23 | |||
24 | ehci_dbg(ehci, "set dev address %d for port %d\n", dev_addr, port_num); | ||
25 | if (port_num > HCS_N_PORTS(ehci->hcs_params)) { | ||
26 | ehci_dbg(ehci, "invalid port number %d\n", port_num); | ||
27 | return -ENODEV; | ||
28 | } | ||
29 | portsc = ehci_readl(ehci, &ehci->regs->port_status[port_num-1]); | ||
30 | portsc &= ~PORT_DEV_ADDR; | ||
31 | portsc |= dev_addr<<25; | ||
32 | ehci_writel(ehci, portsc, &ehci->regs->port_status[port_num-1]); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | /* | ||
37 | * this function is used to check if the device support LPM | ||
38 | * if yes, mark the PORTSC register with PORT_LPM bit | ||
39 | */ | ||
40 | static int ehci_lpm_check(struct ehci_hcd *ehci, int port) | ||
41 | { | ||
42 | u32 __iomem *portsc ; | ||
43 | u32 val32; | ||
44 | int retval; | ||
45 | |||
46 | portsc = &ehci->regs->port_status[port-1]; | ||
47 | val32 = ehci_readl(ehci, portsc); | ||
48 | if (!(val32 & PORT_DEV_ADDR)) { | ||
49 | ehci_dbg(ehci, "LPM: no device attached\n"); | ||
50 | return -ENODEV; | ||
51 | } | ||
52 | val32 |= PORT_LPM; | ||
53 | ehci_writel(ehci, val32, portsc); | ||
54 | msleep(5); | ||
55 | val32 |= PORT_SUSPEND; | ||
56 | ehci_dbg(ehci, "Sending LPM 0x%08x to port %d\n", val32, port); | ||
57 | ehci_writel(ehci, val32, portsc); | ||
58 | /* wait for ACK */ | ||
59 | msleep(10); | ||
60 | retval = handshake(ehci, &ehci->regs->port_status[port-1], PORT_SSTS, | ||
61 | PORTSC_SUSPEND_STS_ACK, 125); | ||
62 | dbg_port(ehci, "LPM", port, val32); | ||
63 | if (retval != -ETIMEDOUT) { | ||
64 | ehci_dbg(ehci, "LPM: device ACK for LPM\n"); | ||
65 | val32 |= PORT_LPM; | ||
66 | /* | ||
67 | * now device should be in L1 sleep, let's wake up the device | ||
68 | * so that we can complete enumeration. | ||
69 | */ | ||
70 | ehci_writel(ehci, val32, portsc); | ||
71 | msleep(10); | ||
72 | val32 |= PORT_RESUME; | ||
73 | ehci_writel(ehci, val32, portsc); | ||
74 | } else { | ||
75 | ehci_dbg(ehci, "LPM: device does not ACK, disable LPM %d\n", | ||
76 | retval); | ||
77 | val32 &= ~PORT_LPM; | ||
78 | retval = -ETIMEDOUT; | ||
79 | ehci_writel(ehci, val32, portsc); | ||
80 | } | ||
81 | |||
82 | return retval; | ||
83 | } | ||
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 5450e628157f..116ae280053a 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/gpio.h> | 38 | #include <linux/gpio.h> |
39 | #include <linux/regulator/consumer.h> | 39 | #include <linux/regulator/consumer.h> |
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <linux/usb/ulpi.h> | ||
41 | #include <plat/usb.h> | 42 | #include <plat/usb.h> |
42 | 43 | ||
43 | /* | 44 | /* |
@@ -236,6 +237,35 @@ static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask) | |||
236 | 237 | ||
237 | /*-------------------------------------------------------------------------*/ | 238 | /*-------------------------------------------------------------------------*/ |
238 | 239 | ||
240 | static void omap_ehci_soft_phy_reset(struct ehci_hcd_omap *omap, u8 port) | ||
241 | { | ||
242 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); | ||
243 | unsigned reg = 0; | ||
244 | |||
245 | reg = ULPI_FUNC_CTRL_RESET | ||
246 | /* FUNCTION_CTRL_SET register */ | ||
247 | | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT) | ||
248 | /* Write */ | ||
249 | | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) | ||
250 | /* PORTn */ | ||
251 | | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) | ||
252 | /* start ULPI access*/ | ||
253 | | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT); | ||
254 | |||
255 | ehci_omap_writel(omap->ehci_base, EHCI_INSNREG05_ULPI, reg); | ||
256 | |||
257 | /* Wait for ULPI access completion */ | ||
258 | while ((ehci_omap_readl(omap->ehci_base, EHCI_INSNREG05_ULPI) | ||
259 | & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) { | ||
260 | cpu_relax(); | ||
261 | |||
262 | if (time_after(jiffies, timeout)) { | ||
263 | dev_dbg(omap->dev, "phy reset operation timed out\n"); | ||
264 | break; | ||
265 | } | ||
266 | } | ||
267 | } | ||
268 | |||
239 | /* omap_start_ehc | 269 | /* omap_start_ehc |
240 | * - Start the TI USBHOST controller | 270 | * - Start the TI USBHOST controller |
241 | */ | 271 | */ |
@@ -425,6 +455,12 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
425 | gpio_set_value(omap->reset_gpio_port[1], 1); | 455 | gpio_set_value(omap->reset_gpio_port[1], 1); |
426 | } | 456 | } |
427 | 457 | ||
458 | /* Soft reset the PHY using PHY reset command over ULPI */ | ||
459 | if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) | ||
460 | omap_ehci_soft_phy_reset(omap, 0); | ||
461 | if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) | ||
462 | omap_ehci_soft_phy_reset(omap, 1); | ||
463 | |||
428 | return 0; | 464 | return 0; |
429 | 465 | ||
430 | err_sys_status: | 466 | err_sys_status: |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index d43d176161aa..58b72d741d93 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -114,6 +114,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
114 | break; | 114 | break; |
115 | case PCI_VENDOR_ID_INTEL: | 115 | case PCI_VENDOR_ID_INTEL: |
116 | ehci->need_io_watchdog = 0; | 116 | ehci->need_io_watchdog = 0; |
117 | ehci->fs_i_thresh = 1; | ||
117 | if (pdev->device == 0x27cc) { | 118 | if (pdev->device == 0x27cc) { |
118 | ehci->broken_periodic = 1; | 119 | ehci->broken_periodic = 1; |
119 | ehci_info(ehci, "using broken periodic workaround\n"); | 120 | ehci_info(ehci, "using broken periodic workaround\n"); |
@@ -277,7 +278,7 @@ done: | |||
277 | * Also they depend on separate root hub suspend/resume. | 278 | * Also they depend on separate root hub suspend/resume. |
278 | */ | 279 | */ |
279 | 280 | ||
280 | static int ehci_pci_suspend(struct usb_hcd *hcd) | 281 | static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) |
281 | { | 282 | { |
282 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 283 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
283 | unsigned long flags; | 284 | unsigned long flags; |
@@ -291,7 +292,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd) | |||
291 | * the root hub is either suspended or stopped. | 292 | * the root hub is either suspended or stopped. |
292 | */ | 293 | */ |
293 | spin_lock_irqsave (&ehci->lock, flags); | 294 | spin_lock_irqsave (&ehci->lock, flags); |
294 | ehci_prepare_ports_for_controller_suspend(ehci); | 295 | ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup); |
295 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); | 296 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
296 | (void)ehci_readl(ehci, &ehci->regs->intr_enable); | 297 | (void)ehci_readl(ehci, &ehci->regs->intr_enable); |
297 | 298 | ||
@@ -361,6 +362,22 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) | |||
361 | } | 362 | } |
362 | #endif | 363 | #endif |
363 | 364 | ||
365 | static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev) | ||
366 | { | ||
367 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
368 | int rc = 0; | ||
369 | |||
370 | if (!udev->parent) /* udev is root hub itself, impossible */ | ||
371 | rc = -1; | ||
372 | /* we only support lpm device connected to root hub yet */ | ||
373 | if (ehci->has_lpm && !udev->parent->parent) { | ||
374 | rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum); | ||
375 | if (!rc) | ||
376 | rc = ehci_lpm_check(ehci, udev->portnum); | ||
377 | } | ||
378 | return rc; | ||
379 | } | ||
380 | |||
364 | static const struct hc_driver ehci_pci_hc_driver = { | 381 | static const struct hc_driver ehci_pci_hc_driver = { |
365 | .description = hcd_name, | 382 | .description = hcd_name, |
366 | .product_desc = "EHCI Host Controller", | 383 | .product_desc = "EHCI Host Controller", |
@@ -407,6 +424,11 @@ static const struct hc_driver ehci_pci_hc_driver = { | |||
407 | .relinquish_port = ehci_relinquish_port, | 424 | .relinquish_port = ehci_relinquish_port, |
408 | .port_handed_over = ehci_port_handed_over, | 425 | .port_handed_over = ehci_port_handed_over, |
409 | 426 | ||
427 | /* | ||
428 | * call back when device connected and addressed | ||
429 | */ | ||
430 | .update_device = ehci_update_device, | ||
431 | |||
410 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | 432 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, |
411 | }; | 433 | }; |
412 | 434 | ||
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 11a79c4f4a9d..233c288e3f93 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -1126,8 +1126,7 @@ submit_async ( | |||
1126 | #endif | 1126 | #endif |
1127 | 1127 | ||
1128 | spin_lock_irqsave (&ehci->lock, flags); | 1128 | spin_lock_irqsave (&ehci->lock, flags); |
1129 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | 1129 | if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { |
1130 | &ehci_to_hcd(ehci)->flags))) { | ||
1131 | rc = -ESHUTDOWN; | 1130 | rc = -ESHUTDOWN; |
1132 | goto done; | 1131 | goto done; |
1133 | } | 1132 | } |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 805ec633a652..a92526d6e5ae 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -880,8 +880,7 @@ static int intr_submit ( | |||
880 | 880 | ||
881 | spin_lock_irqsave (&ehci->lock, flags); | 881 | spin_lock_irqsave (&ehci->lock, flags); |
882 | 882 | ||
883 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | 883 | if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { |
884 | &ehci_to_hcd(ehci)->flags))) { | ||
885 | status = -ESHUTDOWN; | 884 | status = -ESHUTDOWN; |
886 | goto done_not_linked; | 885 | goto done_not_linked; |
887 | } | 886 | } |
@@ -1075,15 +1074,6 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream) | |||
1075 | if (stream->ep) | 1074 | if (stream->ep) |
1076 | stream->ep->hcpriv = NULL; | 1075 | stream->ep->hcpriv = NULL; |
1077 | 1076 | ||
1078 | if (stream->rescheduled) { | ||
1079 | ehci_info (ehci, "ep%d%s-iso rescheduled " | ||
1080 | "%lu times in %lu seconds\n", | ||
1081 | stream->bEndpointAddress, is_in ? "in" : "out", | ||
1082 | stream->rescheduled, | ||
1083 | ((jiffies - stream->start)/HZ) | ||
1084 | ); | ||
1085 | } | ||
1086 | |||
1087 | kfree(stream); | 1077 | kfree(stream); |
1088 | } | 1078 | } |
1089 | } | 1079 | } |
@@ -1396,30 +1386,25 @@ iso_stream_schedule ( | |||
1396 | struct ehci_iso_stream *stream | 1386 | struct ehci_iso_stream *stream |
1397 | ) | 1387 | ) |
1398 | { | 1388 | { |
1399 | u32 now, next, start, period; | 1389 | u32 now, next, start, period, span; |
1400 | int status; | 1390 | int status; |
1401 | unsigned mod = ehci->periodic_size << 3; | 1391 | unsigned mod = ehci->periodic_size << 3; |
1402 | struct ehci_iso_sched *sched = urb->hcpriv; | 1392 | struct ehci_iso_sched *sched = urb->hcpriv; |
1403 | struct pci_dev *pdev; | ||
1404 | 1393 | ||
1405 | if (sched->span > (mod - SCHEDULE_SLOP)) { | 1394 | period = urb->interval; |
1406 | ehci_dbg (ehci, "iso request %p too long\n", urb); | 1395 | span = sched->span; |
1407 | status = -EFBIG; | 1396 | if (!stream->highspeed) { |
1408 | goto fail; | 1397 | period <<= 3; |
1398 | span <<= 3; | ||
1409 | } | 1399 | } |
1410 | 1400 | ||
1411 | if ((stream->depth + sched->span) > mod) { | 1401 | if (span > mod - SCHEDULE_SLOP) { |
1412 | ehci_dbg (ehci, "request %p would overflow (%d+%d>%d)\n", | 1402 | ehci_dbg (ehci, "iso request %p too long\n", urb); |
1413 | urb, stream->depth, sched->span, mod); | ||
1414 | status = -EFBIG; | 1403 | status = -EFBIG; |
1415 | goto fail; | 1404 | goto fail; |
1416 | } | 1405 | } |
1417 | 1406 | ||
1418 | period = urb->interval; | 1407 | now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1); |
1419 | if (!stream->highspeed) | ||
1420 | period <<= 3; | ||
1421 | |||
1422 | now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; | ||
1423 | 1408 | ||
1424 | /* Typical case: reuse current schedule, stream is still active. | 1409 | /* Typical case: reuse current schedule, stream is still active. |
1425 | * Hopefully there are no gaps from the host falling behind | 1410 | * Hopefully there are no gaps from the host falling behind |
@@ -1427,34 +1412,35 @@ iso_stream_schedule ( | |||
1427 | * slot in the schedule, implicitly assuming URB_ISO_ASAP. | 1412 | * slot in the schedule, implicitly assuming URB_ISO_ASAP. |
1428 | */ | 1413 | */ |
1429 | if (likely (!list_empty (&stream->td_list))) { | 1414 | if (likely (!list_empty (&stream->td_list))) { |
1430 | pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); | 1415 | u32 excess; |
1431 | start = stream->next_uframe; | ||
1432 | 1416 | ||
1433 | /* For high speed devices, allow scheduling within the | 1417 | /* For high speed devices, allow scheduling within the |
1434 | * isochronous scheduling threshold. For full speed devices, | 1418 | * isochronous scheduling threshold. For full speed devices |
1435 | * don't. (Work around for Intel ICH9 bug.) | 1419 | * and Intel PCI-based controllers, don't (work around for |
1420 | * Intel ICH9 bug). | ||
1436 | */ | 1421 | */ |
1437 | if (!stream->highspeed && | 1422 | if (!stream->highspeed && ehci->fs_i_thresh) |
1438 | pdev->vendor == PCI_VENDOR_ID_INTEL) | ||
1439 | next = now + ehci->i_thresh; | 1423 | next = now + ehci->i_thresh; |
1440 | else | 1424 | else |
1441 | next = now; | 1425 | next = now; |
1442 | 1426 | ||
1443 | /* Fell behind (by up to twice the slop amount)? */ | 1427 | /* Fell behind (by up to twice the slop amount)? |
1444 | if (((start - next) & (mod - 1)) >= | 1428 | * We decide based on the time of the last currently-scheduled |
1445 | mod - 2 * SCHEDULE_SLOP) | 1429 | * slot, not the time of the next available slot. |
1446 | start += period * DIV_ROUND_UP( | 1430 | */ |
1447 | (next - start) & (mod - 1), | 1431 | excess = (stream->next_uframe - period - next) & (mod - 1); |
1448 | period); | 1432 | if (excess >= mod - 2 * SCHEDULE_SLOP) |
1449 | 1433 | start = next + excess - mod + period * | |
1450 | /* Tried to schedule too far into the future? */ | 1434 | DIV_ROUND_UP(mod - excess, period); |
1451 | if (unlikely(((start - now) & (mod - 1)) + sched->span | 1435 | else |
1452 | >= mod - 2 * SCHEDULE_SLOP)) { | 1436 | start = next + excess + period; |
1437 | if (start - now >= mod) { | ||
1438 | ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n", | ||
1439 | urb, start - now - period, period, | ||
1440 | mod); | ||
1453 | status = -EFBIG; | 1441 | status = -EFBIG; |
1454 | goto fail; | 1442 | goto fail; |
1455 | } | 1443 | } |
1456 | stream->next_uframe = start; | ||
1457 | goto ready; | ||
1458 | } | 1444 | } |
1459 | 1445 | ||
1460 | /* need to schedule; when's the next (u)frame we could start? | 1446 | /* need to schedule; when's the next (u)frame we could start? |
@@ -1463,51 +1449,60 @@ iso_stream_schedule ( | |||
1463 | * can also help high bandwidth if the dma and irq loads don't | 1449 | * can also help high bandwidth if the dma and irq loads don't |
1464 | * jump until after the queue is primed. | 1450 | * jump until after the queue is primed. |
1465 | */ | 1451 | */ |
1466 | start = SCHEDULE_SLOP + (now & ~0x07); | 1452 | else { |
1467 | start %= mod; | 1453 | start = SCHEDULE_SLOP + (now & ~0x07); |
1468 | stream->next_uframe = start; | 1454 | |
1469 | 1455 | /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ | |
1470 | /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ | 1456 | |
1471 | 1457 | /* find a uframe slot with enough bandwidth */ | |
1472 | /* find a uframe slot with enough bandwidth */ | 1458 | next = start + period; |
1473 | for (; start < (stream->next_uframe + period); start++) { | 1459 | for (; start < next; start++) { |
1474 | int enough_space; | 1460 | |
1475 | 1461 | /* check schedule: enough space? */ | |
1476 | /* check schedule: enough space? */ | 1462 | if (stream->highspeed) { |
1477 | if (stream->highspeed) | 1463 | if (itd_slot_ok(ehci, mod, start, |
1478 | enough_space = itd_slot_ok (ehci, mod, start, | 1464 | stream->usecs, period)) |
1479 | stream->usecs, period); | 1465 | break; |
1480 | else { | 1466 | } else { |
1481 | if ((start % 8) >= 6) | 1467 | if ((start % 8) >= 6) |
1482 | continue; | 1468 | continue; |
1483 | enough_space = sitd_slot_ok (ehci, mod, stream, | 1469 | if (sitd_slot_ok(ehci, mod, stream, |
1484 | start, sched, period); | 1470 | start, sched, period)) |
1471 | break; | ||
1472 | } | ||
1485 | } | 1473 | } |
1486 | 1474 | ||
1487 | /* schedule it here if there's enough bandwidth */ | 1475 | /* no room in the schedule */ |
1488 | if (enough_space) { | 1476 | if (start == next) { |
1489 | stream->next_uframe = start % mod; | 1477 | ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n", |
1490 | goto ready; | 1478 | urb, now, now + mod); |
1479 | status = -ENOSPC; | ||
1480 | goto fail; | ||
1491 | } | 1481 | } |
1492 | } | 1482 | } |
1493 | 1483 | ||
1494 | /* no room in the schedule */ | 1484 | /* Tried to schedule too far into the future? */ |
1495 | ehci_dbg (ehci, "iso %ssched full %p (now %d max %d)\n", | 1485 | if (unlikely(start - now + span - period |
1496 | list_empty (&stream->td_list) ? "" : "re", | 1486 | >= mod - 2 * SCHEDULE_SLOP)) { |
1497 | urb, now, now + mod); | 1487 | ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n", |
1498 | status = -ENOSPC; | 1488 | urb, start - now, span - period, |
1489 | mod - 2 * SCHEDULE_SLOP); | ||
1490 | status = -EFBIG; | ||
1491 | goto fail; | ||
1492 | } | ||
1499 | 1493 | ||
1500 | fail: | 1494 | stream->next_uframe = start & (mod - 1); |
1501 | iso_sched_free (stream, sched); | ||
1502 | urb->hcpriv = NULL; | ||
1503 | return status; | ||
1504 | 1495 | ||
1505 | ready: | ||
1506 | /* report high speed start in uframes; full speed, in frames */ | 1496 | /* report high speed start in uframes; full speed, in frames */ |
1507 | urb->start_frame = stream->next_uframe; | 1497 | urb->start_frame = stream->next_uframe; |
1508 | if (!stream->highspeed) | 1498 | if (!stream->highspeed) |
1509 | urb->start_frame >>= 3; | 1499 | urb->start_frame >>= 3; |
1510 | return 0; | 1500 | return 0; |
1501 | |||
1502 | fail: | ||
1503 | iso_sched_free(stream, sched); | ||
1504 | urb->hcpriv = NULL; | ||
1505 | return status; | ||
1511 | } | 1506 | } |
1512 | 1507 | ||
1513 | /*-------------------------------------------------------------------------*/ | 1508 | /*-------------------------------------------------------------------------*/ |
@@ -1602,7 +1597,7 @@ itd_link_urb ( | |||
1602 | struct ehci_iso_sched *iso_sched = urb->hcpriv; | 1597 | struct ehci_iso_sched *iso_sched = urb->hcpriv; |
1603 | struct ehci_itd *itd; | 1598 | struct ehci_itd *itd; |
1604 | 1599 | ||
1605 | next_uframe = stream->next_uframe % mod; | 1600 | next_uframe = stream->next_uframe & (mod - 1); |
1606 | 1601 | ||
1607 | if (unlikely (list_empty(&stream->td_list))) { | 1602 | if (unlikely (list_empty(&stream->td_list))) { |
1608 | ehci_to_hcd(ehci)->self.bandwidth_allocated | 1603 | ehci_to_hcd(ehci)->self.bandwidth_allocated |
@@ -1613,7 +1608,6 @@ itd_link_urb ( | |||
1613 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", | 1608 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", |
1614 | urb->interval, | 1609 | urb->interval, |
1615 | next_uframe >> 3, next_uframe & 0x7); | 1610 | next_uframe >> 3, next_uframe & 0x7); |
1616 | stream->start = jiffies; | ||
1617 | } | 1611 | } |
1618 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; | 1612 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; |
1619 | 1613 | ||
@@ -1639,14 +1633,13 @@ itd_link_urb ( | |||
1639 | itd_patch(ehci, itd, iso_sched, packet, uframe); | 1633 | itd_patch(ehci, itd, iso_sched, packet, uframe); |
1640 | 1634 | ||
1641 | next_uframe += stream->interval; | 1635 | next_uframe += stream->interval; |
1642 | stream->depth += stream->interval; | 1636 | next_uframe &= mod - 1; |
1643 | next_uframe %= mod; | ||
1644 | packet++; | 1637 | packet++; |
1645 | 1638 | ||
1646 | /* link completed itds into the schedule */ | 1639 | /* link completed itds into the schedule */ |
1647 | if (((next_uframe >> 3) != frame) | 1640 | if (((next_uframe >> 3) != frame) |
1648 | || packet == urb->number_of_packets) { | 1641 | || packet == urb->number_of_packets) { |
1649 | itd_link (ehci, frame % ehci->periodic_size, itd); | 1642 | itd_link(ehci, frame & (ehci->periodic_size - 1), itd); |
1650 | itd = NULL; | 1643 | itd = NULL; |
1651 | } | 1644 | } |
1652 | } | 1645 | } |
@@ -1695,7 +1688,6 @@ itd_complete ( | |||
1695 | 1688 | ||
1696 | t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]); | 1689 | t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]); |
1697 | itd->hw_transaction [uframe] = 0; | 1690 | itd->hw_transaction [uframe] = 0; |
1698 | stream->depth -= stream->interval; | ||
1699 | 1691 | ||
1700 | /* report transfer status */ | 1692 | /* report transfer status */ |
1701 | if (unlikely (t & ISO_ERRS)) { | 1693 | if (unlikely (t & ISO_ERRS)) { |
@@ -1815,8 +1807,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, | |||
1815 | 1807 | ||
1816 | /* schedule ... need to lock */ | 1808 | /* schedule ... need to lock */ |
1817 | spin_lock_irqsave (&ehci->lock, flags); | 1809 | spin_lock_irqsave (&ehci->lock, flags); |
1818 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | 1810 | if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { |
1819 | &ehci_to_hcd(ehci)->flags))) { | ||
1820 | status = -ESHUTDOWN; | 1811 | status = -ESHUTDOWN; |
1821 | goto done_not_linked; | 1812 | goto done_not_linked; |
1822 | } | 1813 | } |
@@ -2024,9 +2015,8 @@ sitd_link_urb ( | |||
2024 | "sched devp %s ep%d%s-iso [%d] %dms/%04x\n", | 2015 | "sched devp %s ep%d%s-iso [%d] %dms/%04x\n", |
2025 | urb->dev->devpath, stream->bEndpointAddress & 0x0f, | 2016 | urb->dev->devpath, stream->bEndpointAddress & 0x0f, |
2026 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", | 2017 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", |
2027 | (next_uframe >> 3) % ehci->periodic_size, | 2018 | (next_uframe >> 3) & (ehci->periodic_size - 1), |
2028 | stream->interval, hc32_to_cpu(ehci, stream->splits)); | 2019 | stream->interval, hc32_to_cpu(ehci, stream->splits)); |
2029 | stream->start = jiffies; | ||
2030 | } | 2020 | } |
2031 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; | 2021 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; |
2032 | 2022 | ||
@@ -2047,13 +2037,12 @@ sitd_link_urb ( | |||
2047 | sitd->urb = urb; | 2037 | sitd->urb = urb; |
2048 | 2038 | ||
2049 | sitd_patch(ehci, stream, sitd, sched, packet); | 2039 | sitd_patch(ehci, stream, sitd, sched, packet); |
2050 | sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, | 2040 | sitd_link(ehci, (next_uframe >> 3) & (ehci->periodic_size - 1), |
2051 | sitd); | 2041 | sitd); |
2052 | 2042 | ||
2053 | next_uframe += stream->interval << 3; | 2043 | next_uframe += stream->interval << 3; |
2054 | stream->depth += stream->interval << 3; | ||
2055 | } | 2044 | } |
2056 | stream->next_uframe = next_uframe % mod; | 2045 | stream->next_uframe = next_uframe & (mod - 1); |
2057 | 2046 | ||
2058 | /* don't need that schedule data any more */ | 2047 | /* don't need that schedule data any more */ |
2059 | iso_sched_free (stream, sched); | 2048 | iso_sched_free (stream, sched); |
@@ -2111,7 +2100,6 @@ sitd_complete ( | |||
2111 | desc->actual_length = desc->length - SITD_LENGTH(t); | 2100 | desc->actual_length = desc->length - SITD_LENGTH(t); |
2112 | urb->actual_length += desc->actual_length; | 2101 | urb->actual_length += desc->actual_length; |
2113 | } | 2102 | } |
2114 | stream->depth -= stream->interval << 3; | ||
2115 | 2103 | ||
2116 | /* handle completion now? */ | 2104 | /* handle completion now? */ |
2117 | if ((urb_index + 1) != urb->number_of_packets) | 2105 | if ((urb_index + 1) != urb->number_of_packets) |
@@ -2201,8 +2189,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, | |||
2201 | 2189 | ||
2202 | /* schedule ... need to lock */ | 2190 | /* schedule ... need to lock */ |
2203 | spin_lock_irqsave (&ehci->lock, flags); | 2191 | spin_lock_irqsave (&ehci->lock, flags); |
2204 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | 2192 | if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { |
2205 | &ehci_to_hcd(ehci)->flags))) { | ||
2206 | status = -ESHUTDOWN; | 2193 | status = -ESHUTDOWN; |
2207 | goto done_not_linked; | 2194 | goto done_not_linked; |
2208 | } | 2195 | } |
@@ -2263,7 +2250,7 @@ scan_periodic (struct ehci_hcd *ehci) | |||
2263 | now_uframe = ehci->next_uframe; | 2250 | now_uframe = ehci->next_uframe; |
2264 | if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { | 2251 | if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { |
2265 | clock = ehci_readl(ehci, &ehci->regs->frame_index); | 2252 | clock = ehci_readl(ehci, &ehci->regs->frame_index); |
2266 | clock_frame = (clock >> 3) % ehci->periodic_size; | 2253 | clock_frame = (clock >> 3) & (ehci->periodic_size - 1); |
2267 | } else { | 2254 | } else { |
2268 | clock = now_uframe + mod - 1; | 2255 | clock = now_uframe + mod - 1; |
2269 | clock_frame = -1; | 2256 | clock_frame = -1; |
@@ -2272,7 +2259,7 @@ scan_periodic (struct ehci_hcd *ehci) | |||
2272 | free_cached_lists(ehci); | 2259 | free_cached_lists(ehci); |
2273 | ehci->clock_frame = clock_frame; | 2260 | ehci->clock_frame = clock_frame; |
2274 | } | 2261 | } |
2275 | clock %= mod; | 2262 | clock &= mod - 1; |
2276 | clock_frame = clock >> 3; | 2263 | clock_frame = clock >> 3; |
2277 | 2264 | ||
2278 | for (;;) { | 2265 | for (;;) { |
@@ -2361,7 +2348,7 @@ restart: | |||
2361 | * frame is current. | 2348 | * frame is current. |
2362 | */ | 2349 | */ |
2363 | if (((frame == clock_frame) || | 2350 | if (((frame == clock_frame) || |
2364 | (((frame + 1) % ehci->periodic_size) | 2351 | (((frame + 1) & (ehci->periodic_size - 1)) |
2365 | == clock_frame)) | 2352 | == clock_frame)) |
2366 | && live | 2353 | && live |
2367 | && (q.sitd->hw_results & | 2354 | && (q.sitd->hw_results & |
@@ -2428,7 +2415,8 @@ restart: | |||
2428 | || ehci->periodic_sched == 0) | 2415 | || ehci->periodic_sched == 0) |
2429 | break; | 2416 | break; |
2430 | ehci->next_uframe = now_uframe; | 2417 | ehci->next_uframe = now_uframe; |
2431 | now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; | 2418 | now = ehci_readl(ehci, &ehci->regs->frame_index) & |
2419 | (mod - 1); | ||
2432 | if (now_uframe == now) | 2420 | if (now_uframe == now) |
2433 | break; | 2421 | break; |
2434 | 2422 | ||
@@ -2441,7 +2429,7 @@ restart: | |||
2441 | } | 2429 | } |
2442 | } else { | 2430 | } else { |
2443 | now_uframe++; | 2431 | now_uframe++; |
2444 | now_uframe %= mod; | 2432 | now_uframe &= mod - 1; |
2445 | } | 2433 | } |
2446 | } | 2434 | } |
2447 | } | 2435 | } |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 650a687f2854..bde823f704e9 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -130,6 +130,7 @@ struct ehci_hcd { /* one per controller */ | |||
130 | unsigned has_amcc_usb23:1; | 130 | unsigned has_amcc_usb23:1; |
131 | unsigned need_io_watchdog:1; | 131 | unsigned need_io_watchdog:1; |
132 | unsigned broken_periodic:1; | 132 | unsigned broken_periodic:1; |
133 | unsigned fs_i_thresh:1; /* Intel iso scheduling */ | ||
133 | 134 | ||
134 | /* required for usb32 quirk */ | 135 | /* required for usb32 quirk */ |
135 | #define OHCI_CTRL_HCFS (3 << 6) | 136 | #define OHCI_CTRL_HCFS (3 << 6) |
@@ -140,7 +141,8 @@ struct ehci_hcd { /* one per controller */ | |||
140 | #define OHCI_HCCTRL_LEN 0x4 | 141 | #define OHCI_HCCTRL_LEN 0x4 |
141 | __hc32 *ohci_hcctrl_reg; | 142 | __hc32 *ohci_hcctrl_reg; |
142 | unsigned has_hostpc:1; | 143 | unsigned has_hostpc:1; |
143 | 144 | unsigned has_lpm:1; /* support link power management */ | |
145 | unsigned has_ppcd:1; /* support per-port change bits */ | ||
144 | u8 sbrn; /* packed release number */ | 146 | u8 sbrn; /* packed release number */ |
145 | 147 | ||
146 | /* irq statistics */ | 148 | /* irq statistics */ |
@@ -154,9 +156,6 @@ struct ehci_hcd { /* one per controller */ | |||
154 | /* debug files */ | 156 | /* debug files */ |
155 | #ifdef DEBUG | 157 | #ifdef DEBUG |
156 | struct dentry *debug_dir; | 158 | struct dentry *debug_dir; |
157 | struct dentry *debug_async; | ||
158 | struct dentry *debug_periodic; | ||
159 | struct dentry *debug_registers; | ||
160 | #endif | 159 | #endif |
161 | }; | 160 | }; |
162 | 161 | ||
@@ -401,15 +400,12 @@ struct ehci_iso_stream { | |||
401 | u32 refcount; | 400 | u32 refcount; |
402 | u8 bEndpointAddress; | 401 | u8 bEndpointAddress; |
403 | u8 highspeed; | 402 | u8 highspeed; |
404 | u16 depth; /* depth in uframes */ | ||
405 | struct list_head td_list; /* queued itds/sitds */ | 403 | struct list_head td_list; /* queued itds/sitds */ |
406 | struct list_head free_list; /* list of unused itds/sitds */ | 404 | struct list_head free_list; /* list of unused itds/sitds */ |
407 | struct usb_device *udev; | 405 | struct usb_device *udev; |
408 | struct usb_host_endpoint *ep; | 406 | struct usb_host_endpoint *ep; |
409 | 407 | ||
410 | /* output of (re)scheduling */ | 408 | /* output of (re)scheduling */ |
411 | unsigned long start; /* jiffies */ | ||
412 | unsigned long rescheduled; | ||
413 | int next_uframe; | 409 | int next_uframe; |
414 | __hc32 splits; | 410 | __hc32 splits; |
415 | 411 | ||
@@ -538,11 +534,11 @@ struct ehci_fstn { | |||
538 | 534 | ||
539 | /* Prepare the PORTSC wakeup flags during controller suspend/resume */ | 535 | /* Prepare the PORTSC wakeup flags during controller suspend/resume */ |
540 | 536 | ||
541 | #define ehci_prepare_ports_for_controller_suspend(ehci) \ | 537 | #define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup) \ |
542 | ehci_adjust_port_wakeup_flags(ehci, true); | 538 | ehci_adjust_port_wakeup_flags(ehci, true, do_wakeup); |
543 | 539 | ||
544 | #define ehci_prepare_ports_for_controller_resume(ehci) \ | 540 | #define ehci_prepare_ports_for_controller_resume(ehci) \ |
545 | ehci_adjust_port_wakeup_flags(ehci, false); | 541 | ehci_adjust_port_wakeup_flags(ehci, false, false); |
546 | 542 | ||
547 | /*-------------------------------------------------------------------------*/ | 543 | /*-------------------------------------------------------------------------*/ |
548 | 544 | ||
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 35742f8c7cda..9bfac657572e 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c | |||
@@ -159,7 +159,7 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd) | |||
159 | goto error_set_cluster_id; | 159 | goto error_set_cluster_id; |
160 | 160 | ||
161 | usb_hcd->uses_new_polling = 1; | 161 | usb_hcd->uses_new_polling = 1; |
162 | usb_hcd->poll_rh = 1; | 162 | set_bit(HCD_FLAG_POLL_RH, &usb_hcd->flags); |
163 | usb_hcd->state = HC_STATE_RUNNING; | 163 | usb_hcd->state = HC_STATE_RUNNING; |
164 | result = 0; | 164 | result = 0; |
165 | out: | 165 | out: |
@@ -776,7 +776,7 @@ static int hwahc_probe(struct usb_interface *usb_iface, | |||
776 | goto error_alloc; | 776 | goto error_alloc; |
777 | } | 777 | } |
778 | usb_hcd->wireless = 1; | 778 | usb_hcd->wireless = 1; |
779 | usb_hcd->flags |= HCD_FLAG_SAW_IRQ; | 779 | set_bit(HCD_FLAG_SAW_IRQ, &usb_hcd->flags); |
780 | wusbhc = usb_hcd_to_wusbhc(usb_hcd); | 780 | wusbhc = usb_hcd_to_wusbhc(usb_hcd); |
781 | hwahc = container_of(wusbhc, struct hwahc, wusbhc); | 781 | hwahc = container_of(wusbhc, struct hwahc, wusbhc); |
782 | hwahc_init(hwahc); | 782 | hwahc_init(hwahc); |
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index ca0e98d8e1f4..3e5630369c31 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c | |||
@@ -1521,7 +1521,7 @@ static int imx21_hc_reset(struct usb_hcd *hcd) | |||
1521 | return -ETIMEDOUT; | 1521 | return -ETIMEDOUT; |
1522 | } | 1522 | } |
1523 | spin_unlock_irq(&imx21->lock); | 1523 | spin_unlock_irq(&imx21->lock); |
1524 | schedule_timeout(1); | 1524 | schedule_timeout_uninterruptible(1); |
1525 | spin_lock_irq(&imx21->lock); | 1525 | spin_lock_irq(&imx21->lock); |
1526 | } | 1526 | } |
1527 | spin_unlock_irqrestore(&imx21->lock, flags); | 1527 | spin_unlock_irqrestore(&imx21->lock, flags); |
diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h index d995351f9bed..0f97820e65be 100644 --- a/drivers/usb/host/isp1362.h +++ b/drivers/usb/host/isp1362.h | |||
@@ -8,29 +8,7 @@ | |||
8 | /* | 8 | /* |
9 | * Platform specific compile time options | 9 | * Platform specific compile time options |
10 | */ | 10 | */ |
11 | #if defined(CONFIG_ARCH_KARO) | 11 | #if defined(CONFIG_BLACKFIN) |
12 | #include <asm/arch/hardware.h> | ||
13 | #include <asm/arch/pxa-regs.h> | ||
14 | #include <asm/arch/karo.h> | ||
15 | |||
16 | #define USE_32BIT 1 | ||
17 | |||
18 | |||
19 | /* These options are mutually eclusive */ | ||
20 | #define USE_PLATFORM_DELAY 1 | ||
21 | #define USE_NDELAY 0 | ||
22 | /* | ||
23 | * MAX_ROOT_PORTS: Number of downstream ports | ||
24 | * | ||
25 | * The chip has two USB ports, one of which can be configured as | ||
26 | * an USB device port, so the value of this constant is implementation | ||
27 | * specific. | ||
28 | */ | ||
29 | #define MAX_ROOT_PORTS 2 | ||
30 | #define DUMMY_DELAY_ACCESS do {} while (0) | ||
31 | |||
32 | /* insert platform specific definitions for other machines here */ | ||
33 | #elif defined(CONFIG_BLACKFIN) | ||
34 | 12 | ||
35 | #include <linux/io.h> | 13 | #include <linux/io.h> |
36 | #define USE_32BIT 0 | 14 | #define USE_32BIT 0 |
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index dbcafa29c775..d1a3dfc9a408 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c | |||
@@ -482,7 +482,6 @@ static int isp1760_run(struct usb_hcd *hcd) | |||
482 | u32 chipid; | 482 | u32 chipid; |
483 | 483 | ||
484 | hcd->uses_new_polling = 1; | 484 | hcd->uses_new_polling = 1; |
485 | hcd->poll_rh = 0; | ||
486 | 485 | ||
487 | hcd->state = HC_STATE_RUNNING; | 486 | hcd->state = HC_STATE_RUNNING; |
488 | isp1760_enable_interrupts(hcd); | 487 | isp1760_enable_interrupts(hcd); |
@@ -1450,7 +1449,7 @@ static int isp1760_prepare_enqueue(struct isp1760_hcd *priv, struct urb *urb, | |||
1450 | epnum = urb->ep->desc.bEndpointAddress; | 1449 | epnum = urb->ep->desc.bEndpointAddress; |
1451 | 1450 | ||
1452 | spin_lock_irqsave(&priv->lock, flags); | 1451 | spin_lock_irqsave(&priv->lock, flags); |
1453 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &priv_to_hcd(priv)->flags)) { | 1452 | if (!HCD_HW_ACCESSIBLE(priv_to_hcd(priv))) { |
1454 | rc = -ESHUTDOWN; | 1453 | rc = -ESHUTDOWN; |
1455 | goto done; | 1454 | goto done; |
1456 | } | 1455 | } |
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 8ad2441b0284..36abd2baa3ea 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c | |||
@@ -645,7 +645,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) | |||
645 | hcd->product_desc, | 645 | hcd->product_desc, |
646 | hcd_name); | 646 | hcd_name); |
647 | 647 | ||
648 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | 648 | if (!HCD_HW_ACCESSIBLE(hcd)) { |
649 | size -= scnprintf (next, size, | 649 | size -= scnprintf (next, size, |
650 | "SUSPENDED (no register access)\n"); | 650 | "SUSPENDED (no register access)\n"); |
651 | goto done; | 651 | goto done; |
@@ -687,7 +687,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) | |||
687 | next += temp; | 687 | next += temp; |
688 | 688 | ||
689 | temp = scnprintf (next, size, "hub poll timer %s\n", | 689 | temp = scnprintf (next, size, "hub poll timer %s\n", |
690 | ohci_to_hcd(ohci)->poll_rh ? "ON" : "off"); | 690 | HCD_POLL_RH(ohci_to_hcd(ohci)) ? "ON" : "off"); |
691 | size -= temp; | 691 | size -= temp; |
692 | next += temp; | 692 | next += temp; |
693 | 693 | ||
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 02864a237a2c..c3b4ccc7337b 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -212,7 +212,7 @@ static int ohci_urb_enqueue ( | |||
212 | spin_lock_irqsave (&ohci->lock, flags); | 212 | spin_lock_irqsave (&ohci->lock, flags); |
213 | 213 | ||
214 | /* don't submit to a dead HC */ | 214 | /* don't submit to a dead HC */ |
215 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | 215 | if (!HCD_HW_ACCESSIBLE(hcd)) { |
216 | retval = -ENODEV; | 216 | retval = -ENODEV; |
217 | goto fail; | 217 | goto fail; |
218 | } | 218 | } |
@@ -685,7 +685,7 @@ retry: | |||
685 | } | 685 | } |
686 | 686 | ||
687 | /* use rhsc irqs after khubd is fully initialized */ | 687 | /* use rhsc irqs after khubd is fully initialized */ |
688 | hcd->poll_rh = 1; | 688 | set_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
689 | hcd->uses_new_polling = 1; | 689 | hcd->uses_new_polling = 1; |
690 | 690 | ||
691 | /* start controller operations */ | 691 | /* start controller operations */ |
@@ -822,7 +822,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) | |||
822 | else if (ints & OHCI_INTR_RD) { | 822 | else if (ints & OHCI_INTR_RD) { |
823 | ohci_vdbg(ohci, "resume detect\n"); | 823 | ohci_vdbg(ohci, "resume detect\n"); |
824 | ohci_writel(ohci, OHCI_INTR_RD, ®s->intrstatus); | 824 | ohci_writel(ohci, OHCI_INTR_RD, ®s->intrstatus); |
825 | hcd->poll_rh = 1; | 825 | set_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
826 | if (ohci->autostop) { | 826 | if (ohci->autostop) { |
827 | spin_lock (&ohci->lock); | 827 | spin_lock (&ohci->lock); |
828 | ohci_rh_resume (ohci); | 828 | ohci_rh_resume (ohci); |
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 65cac8cc8921..cddcda95b579 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c | |||
@@ -284,7 +284,7 @@ static int ohci_bus_suspend (struct usb_hcd *hcd) | |||
284 | 284 | ||
285 | spin_lock_irq (&ohci->lock); | 285 | spin_lock_irq (&ohci->lock); |
286 | 286 | ||
287 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) | 287 | if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) |
288 | rc = -ESHUTDOWN; | 288 | rc = -ESHUTDOWN; |
289 | else | 289 | else |
290 | rc = ohci_rh_suspend (ohci, 0); | 290 | rc = ohci_rh_suspend (ohci, 0); |
@@ -302,7 +302,7 @@ static int ohci_bus_resume (struct usb_hcd *hcd) | |||
302 | 302 | ||
303 | spin_lock_irq (&ohci->lock); | 303 | spin_lock_irq (&ohci->lock); |
304 | 304 | ||
305 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) | 305 | if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) |
306 | rc = -ESHUTDOWN; | 306 | rc = -ESHUTDOWN; |
307 | else | 307 | else |
308 | rc = ohci_rh_resume (ohci); | 308 | rc = ohci_rh_resume (ohci); |
@@ -355,6 +355,11 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd) | |||
355 | ohci_readl(ohci, &ohci->regs->intrenable); | 355 | ohci_readl(ohci, &ohci->regs->intrenable); |
356 | msleep(20); | 356 | msleep(20); |
357 | } | 357 | } |
358 | |||
359 | /* Does the root hub have a port wakeup pending? */ | ||
360 | if (ohci_readl(ohci, &ohci->regs->intrstatus) & | ||
361 | (OHCI_INTR_RD | OHCI_INTR_RHSC)) | ||
362 | usb_hcd_resume_root_hub(hcd); | ||
358 | } | 363 | } |
359 | 364 | ||
360 | /* Carry out polling-, autostop-, and autoresume-related state changes */ | 365 | /* Carry out polling-, autostop-, and autoresume-related state changes */ |
@@ -364,7 +369,7 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, | |||
364 | int poll_rh = 1; | 369 | int poll_rh = 1; |
365 | int rhsc_enable; | 370 | int rhsc_enable; |
366 | 371 | ||
367 | /* Some broken controllers never turn off RHCS in the interrupt | 372 | /* Some broken controllers never turn off RHSC in the interrupt |
368 | * status register. For their sake we won't re-enable RHSC | 373 | * status register. For their sake we won't re-enable RHSC |
369 | * interrupts if the interrupt bit is already active. | 374 | * interrupts if the interrupt bit is already active. |
370 | */ | 375 | */ |
@@ -489,7 +494,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
489 | unsigned long flags; | 494 | unsigned long flags; |
490 | 495 | ||
491 | spin_lock_irqsave (&ohci->lock, flags); | 496 | spin_lock_irqsave (&ohci->lock, flags); |
492 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) | 497 | if (!HCD_HW_ACCESSIBLE(hcd)) |
493 | goto done; | 498 | goto done; |
494 | 499 | ||
495 | /* undocumented erratum seen on at least rev D */ | 500 | /* undocumented erratum seen on at least rev D */ |
@@ -533,8 +538,12 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
533 | } | 538 | } |
534 | } | 539 | } |
535 | 540 | ||
536 | hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed, | 541 | if (ohci_root_hub_state_changes(ohci, changed, |
537 | any_connected, rhsc_status); | 542 | any_connected, rhsc_status)) |
543 | set_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
544 | else | ||
545 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
546 | |||
538 | 547 | ||
539 | done: | 548 | done: |
540 | spin_unlock_irqrestore (&ohci->lock, flags); | 549 | spin_unlock_irqrestore (&ohci->lock, flags); |
@@ -701,7 +710,7 @@ static int ohci_hub_control ( | |||
701 | u32 temp; | 710 | u32 temp; |
702 | int retval = 0; | 711 | int retval = 0; |
703 | 712 | ||
704 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) | 713 | if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) |
705 | return -ESHUTDOWN; | 714 | return -ESHUTDOWN; |
706 | 715 | ||
707 | switch (typeReq) { | 716 | switch (typeReq) { |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index b8a1148f248e..6bdc8b25a6a1 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -392,7 +392,7 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd) | |||
392 | 392 | ||
393 | #ifdef CONFIG_PM | 393 | #ifdef CONFIG_PM |
394 | 394 | ||
395 | static int ohci_pci_suspend(struct usb_hcd *hcd) | 395 | static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) |
396 | { | 396 | { |
397 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 397 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
398 | unsigned long flags; | 398 | unsigned long flags; |
diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c index 23fd6a886bdd..48ee6943bf35 100644 --- a/drivers/usb/host/ohci-ssb.c +++ b/drivers/usb/host/ohci-ssb.c | |||
@@ -93,8 +93,11 @@ static void ssb_ohci_detach(struct ssb_device *dev) | |||
93 | { | 93 | { |
94 | struct usb_hcd *hcd = ssb_get_drvdata(dev); | 94 | struct usb_hcd *hcd = ssb_get_drvdata(dev); |
95 | 95 | ||
96 | if (hcd->driver->shutdown) | ||
97 | hcd->driver->shutdown(hcd); | ||
96 | usb_remove_hcd(hcd); | 98 | usb_remove_hcd(hcd); |
97 | iounmap(hcd->regs); | 99 | iounmap(hcd->regs); |
100 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
98 | usb_put_hcd(hcd); | 101 | usb_put_hcd(hcd); |
99 | ssb_device_disable(dev, 0); | 102 | ssb_device_disable(dev, 0); |
100 | } | 103 | } |
@@ -106,10 +109,52 @@ static int ssb_ohci_attach(struct ssb_device *dev) | |||
106 | int err = -ENOMEM; | 109 | int err = -ENOMEM; |
107 | u32 tmp, flags = 0; | 110 | u32 tmp, flags = 0; |
108 | 111 | ||
109 | if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) | 112 | if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) || |
110 | flags |= SSB_OHCI_TMSLOW_HOSTMODE; | 113 | dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32))) |
114 | return -EOPNOTSUPP; | ||
111 | 115 | ||
112 | ssb_device_enable(dev, flags); | 116 | if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) { |
117 | /* Put the device into host-mode. */ | ||
118 | flags |= SSB_OHCI_TMSLOW_HOSTMODE; | ||
119 | ssb_device_enable(dev, flags); | ||
120 | } else if (dev->id.coreid == SSB_DEV_USB20_HOST) { | ||
121 | /* | ||
122 | * USB 2.0 special considerations: | ||
123 | * | ||
124 | * In addition to the standard SSB reset sequence, the Host | ||
125 | * Control Register must be programmed to bring the USB core | ||
126 | * and various phy components out of reset. | ||
127 | */ | ||
128 | ssb_device_enable(dev, 0); | ||
129 | ssb_write32(dev, 0x200, 0x7ff); | ||
130 | |||
131 | /* Change Flush control reg */ | ||
132 | tmp = ssb_read32(dev, 0x400); | ||
133 | tmp &= ~8; | ||
134 | ssb_write32(dev, 0x400, tmp); | ||
135 | tmp = ssb_read32(dev, 0x400); | ||
136 | |||
137 | /* Change Shim control reg */ | ||
138 | tmp = ssb_read32(dev, 0x304); | ||
139 | tmp &= ~0x100; | ||
140 | ssb_write32(dev, 0x304, tmp); | ||
141 | tmp = ssb_read32(dev, 0x304); | ||
142 | |||
143 | udelay(1); | ||
144 | |||
145 | /* Work around for 5354 failures */ | ||
146 | if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) { | ||
147 | /* Change syn01 reg */ | ||
148 | tmp = 0x00fe00fe; | ||
149 | ssb_write32(dev, 0x894, tmp); | ||
150 | |||
151 | /* Change syn03 reg */ | ||
152 | tmp = ssb_read32(dev, 0x89c); | ||
153 | tmp |= 0x1; | ||
154 | ssb_write32(dev, 0x89c, tmp); | ||
155 | } | ||
156 | } else | ||
157 | ssb_device_enable(dev, 0); | ||
113 | 158 | ||
114 | hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev, | 159 | hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev, |
115 | dev_name(dev->dev)); | 160 | dev_name(dev->dev)); |
@@ -200,6 +245,7 @@ static int ssb_ohci_resume(struct ssb_device *dev) | |||
200 | static const struct ssb_device_id ssb_ohci_table[] = { | 245 | static const struct ssb_device_id ssb_ohci_table[] = { |
201 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), | 246 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), |
202 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), | 247 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), |
248 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), | ||
203 | SSB_DEVTABLE_END | 249 | SSB_DEVTABLE_END |
204 | }; | 250 | }; |
205 | MODULE_DEVICE_TABLE(ssb, ssb_ohci_table); | 251 | MODULE_DEVICE_TABLE(ssb, ssb_ohci_table); |
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index f608dfd09a8a..d9c85a292737 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c | |||
@@ -1641,8 +1641,7 @@ static int submit_async(struct oxu_hcd *oxu, struct urb *urb, | |||
1641 | #endif | 1641 | #endif |
1642 | 1642 | ||
1643 | spin_lock_irqsave(&oxu->lock, flags); | 1643 | spin_lock_irqsave(&oxu->lock, flags); |
1644 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | 1644 | if (unlikely(!HCD_HW_ACCESSIBLE(oxu_to_hcd(oxu)))) { |
1645 | &oxu_to_hcd(oxu)->flags))) { | ||
1646 | rc = -ESHUTDOWN; | 1645 | rc = -ESHUTDOWN; |
1647 | goto done; | 1646 | goto done; |
1648 | } | 1647 | } |
@@ -2209,8 +2208,7 @@ static int intr_submit(struct oxu_hcd *oxu, struct urb *urb, | |||
2209 | 2208 | ||
2210 | spin_lock_irqsave(&oxu->lock, flags); | 2209 | spin_lock_irqsave(&oxu->lock, flags); |
2211 | 2210 | ||
2212 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | 2211 | if (unlikely(!HCD_HW_ACCESSIBLE(oxu_to_hcd(oxu)))) { |
2213 | &oxu_to_hcd(oxu)->flags))) { | ||
2214 | status = -ESHUTDOWN; | 2212 | status = -ESHUTDOWN; |
2215 | goto done; | 2213 | goto done; |
2216 | } | 2214 | } |
@@ -2715,7 +2713,6 @@ static int oxu_run(struct usb_hcd *hcd) | |||
2715 | u32 temp, hcc_params; | 2713 | u32 temp, hcc_params; |
2716 | 2714 | ||
2717 | hcd->uses_new_polling = 1; | 2715 | hcd->uses_new_polling = 1; |
2718 | hcd->poll_rh = 0; | ||
2719 | 2716 | ||
2720 | /* EHCI spec section 4.1 */ | 2717 | /* EHCI spec section 4.1 */ |
2721 | retval = ehci_reset(oxu); | 2718 | retval = ehci_reset(oxu); |
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index bcf9f0e809de..990f06b89eaa 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c | |||
@@ -813,8 +813,11 @@ static int sl811h_urb_enqueue( | |||
813 | #endif | 813 | #endif |
814 | 814 | ||
815 | /* avoid all allocations within spinlocks */ | 815 | /* avoid all allocations within spinlocks */ |
816 | if (!hep->hcpriv) | 816 | if (!hep->hcpriv) { |
817 | ep = kzalloc(sizeof *ep, mem_flags); | 817 | ep = kzalloc(sizeof *ep, mem_flags); |
818 | if (ep == NULL) | ||
819 | return -ENOMEM; | ||
820 | } | ||
818 | 821 | ||
819 | spin_lock_irqsave(&sl811->lock, flags); | 822 | spin_lock_irqsave(&sl811->lock, flags); |
820 | 823 | ||
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 98cf0b26b968..6e7fb5f38db6 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
@@ -17,7 +17,6 @@ | |||
17 | 17 | ||
18 | #include "uhci-hcd.h" | 18 | #include "uhci-hcd.h" |
19 | 19 | ||
20 | #define uhci_debug_operations (* (const struct file_operations *) NULL) | ||
21 | static struct dentry *uhci_debugfs_root; | 20 | static struct dentry *uhci_debugfs_root; |
22 | 21 | ||
23 | #ifdef DEBUG | 22 | #ifdef DEBUG |
@@ -495,18 +494,16 @@ static int uhci_debug_open(struct inode *inode, struct file *file) | |||
495 | { | 494 | { |
496 | struct uhci_hcd *uhci = inode->i_private; | 495 | struct uhci_hcd *uhci = inode->i_private; |
497 | struct uhci_debug *up; | 496 | struct uhci_debug *up; |
498 | int ret = -ENOMEM; | ||
499 | unsigned long flags; | 497 | unsigned long flags; |
500 | 498 | ||
501 | lock_kernel(); | ||
502 | up = kmalloc(sizeof(*up), GFP_KERNEL); | 499 | up = kmalloc(sizeof(*up), GFP_KERNEL); |
503 | if (!up) | 500 | if (!up) |
504 | goto out; | 501 | return -ENOMEM; |
505 | 502 | ||
506 | up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL); | 503 | up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL); |
507 | if (!up->data) { | 504 | if (!up->data) { |
508 | kfree(up); | 505 | kfree(up); |
509 | goto out; | 506 | return -ENOMEM; |
510 | } | 507 | } |
511 | 508 | ||
512 | up->size = 0; | 509 | up->size = 0; |
@@ -517,10 +514,7 @@ static int uhci_debug_open(struct inode *inode, struct file *file) | |||
517 | 514 | ||
518 | file->private_data = up; | 515 | file->private_data = up; |
519 | 516 | ||
520 | ret = 0; | 517 | return 0; |
521 | out: | ||
522 | unlock_kernel(); | ||
523 | return ret; | ||
524 | } | 518 | } |
525 | 519 | ||
526 | static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence) | 520 | static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence) |
@@ -528,9 +522,9 @@ static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence) | |||
528 | struct uhci_debug *up; | 522 | struct uhci_debug *up; |
529 | loff_t new = -1; | 523 | loff_t new = -1; |
530 | 524 | ||
531 | lock_kernel(); | ||
532 | up = file->private_data; | 525 | up = file->private_data; |
533 | 526 | ||
527 | /* XXX: atomic 64bit seek access, but that needs to be fixed in the VFS */ | ||
534 | switch (whence) { | 528 | switch (whence) { |
535 | case 0: | 529 | case 0: |
536 | new = off; | 530 | new = off; |
@@ -539,11 +533,10 @@ static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence) | |||
539 | new = file->f_pos + off; | 533 | new = file->f_pos + off; |
540 | break; | 534 | break; |
541 | } | 535 | } |
542 | if (new < 0 || new > up->size) { | 536 | |
543 | unlock_kernel(); | 537 | if (new < 0 || new > up->size) |
544 | return -EINVAL; | 538 | return -EINVAL; |
545 | } | 539 | |
546 | unlock_kernel(); | ||
547 | return (file->f_pos = new); | 540 | return (file->f_pos = new); |
548 | } | 541 | } |
549 | 542 | ||
@@ -564,7 +557,6 @@ static int uhci_debug_release(struct inode *inode, struct file *file) | |||
564 | return 0; | 557 | return 0; |
565 | } | 558 | } |
566 | 559 | ||
567 | #undef uhci_debug_operations | ||
568 | static const struct file_operations uhci_debug_operations = { | 560 | static const struct file_operations uhci_debug_operations = { |
569 | .owner = THIS_MODULE, | 561 | .owner = THIS_MODULE, |
570 | .open = uhci_debug_open, | 562 | .open = uhci_debug_open, |
@@ -572,6 +564,7 @@ static const struct file_operations uhci_debug_operations = { | |||
572 | .read = uhci_debug_read, | 564 | .read = uhci_debug_read, |
573 | .release = uhci_debug_release, | 565 | .release = uhci_debug_release, |
574 | }; | 566 | }; |
567 | #define UHCI_DEBUG_OPS | ||
575 | 568 | ||
576 | #endif /* CONFIG_DEBUG_FS */ | 569 | #endif /* CONFIG_DEBUG_FS */ |
577 | 570 | ||
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 6637e52736dd..f52d04db28f4 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -140,7 +140,7 @@ static void finish_reset(struct uhci_hcd *uhci) | |||
140 | uhci->rh_state = UHCI_RH_RESET; | 140 | uhci->rh_state = UHCI_RH_RESET; |
141 | uhci->is_stopped = UHCI_IS_STOPPED; | 141 | uhci->is_stopped = UHCI_IS_STOPPED; |
142 | uhci_to_hcd(uhci)->state = HC_STATE_HALT; | 142 | uhci_to_hcd(uhci)->state = HC_STATE_HALT; |
143 | uhci_to_hcd(uhci)->poll_rh = 0; | 143 | clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); |
144 | 144 | ||
145 | uhci->dead = 0; /* Full reset resurrects the controller */ | 145 | uhci->dead = 0; /* Full reset resurrects the controller */ |
146 | } | 146 | } |
@@ -176,6 +176,8 @@ static void check_and_reset_hc(struct uhci_hcd *uhci) | |||
176 | */ | 176 | */ |
177 | static void configure_hc(struct uhci_hcd *uhci) | 177 | static void configure_hc(struct uhci_hcd *uhci) |
178 | { | 178 | { |
179 | struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci)); | ||
180 | |||
179 | /* Set the frame length to the default: 1 ms exactly */ | 181 | /* Set the frame length to the default: 1 ms exactly */ |
180 | outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); | 182 | outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); |
181 | 183 | ||
@@ -191,8 +193,11 @@ static void configure_hc(struct uhci_hcd *uhci) | |||
191 | mb(); | 193 | mb(); |
192 | 194 | ||
193 | /* Enable PIRQ */ | 195 | /* Enable PIRQ */ |
194 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, | 196 | pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT); |
195 | USBLEGSUP_DEFAULT); | 197 | |
198 | /* Disable platform-specific non-PME# wakeup */ | ||
199 | if (pdev->vendor == PCI_VENDOR_ID_INTEL) | ||
200 | pci_write_config_byte(pdev, USBRES_INTEL, 0); | ||
196 | } | 201 | } |
197 | 202 | ||
198 | 203 | ||
@@ -344,7 +349,10 @@ __acquires(uhci->lock) | |||
344 | /* If interrupts don't work and remote wakeup is enabled then | 349 | /* If interrupts don't work and remote wakeup is enabled then |
345 | * the suspended root hub needs to be polled. | 350 | * the suspended root hub needs to be polled. |
346 | */ | 351 | */ |
347 | uhci_to_hcd(uhci)->poll_rh = (!int_enable && wakeup_enable); | 352 | if (!int_enable && wakeup_enable) |
353 | set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); | ||
354 | else | ||
355 | clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); | ||
348 | 356 | ||
349 | uhci_scan_schedule(uhci); | 357 | uhci_scan_schedule(uhci); |
350 | uhci_fsbr_off(uhci); | 358 | uhci_fsbr_off(uhci); |
@@ -363,7 +371,7 @@ static void start_rh(struct uhci_hcd *uhci) | |||
363 | uhci->io_addr + USBINTR); | 371 | uhci->io_addr + USBINTR); |
364 | mb(); | 372 | mb(); |
365 | uhci->rh_state = UHCI_RH_RUNNING; | 373 | uhci->rh_state = UHCI_RH_RUNNING; |
366 | uhci_to_hcd(uhci)->poll_rh = 1; | 374 | set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); |
367 | } | 375 | } |
368 | 376 | ||
369 | static void wakeup_rh(struct uhci_hcd *uhci) | 377 | static void wakeup_rh(struct uhci_hcd *uhci) |
@@ -589,7 +597,7 @@ static int uhci_start(struct usb_hcd *hcd) | |||
589 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 597 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
590 | int retval = -EBUSY; | 598 | int retval = -EBUSY; |
591 | int i; | 599 | int i; |
592 | struct dentry *dentry; | 600 | struct dentry __maybe_unused *dentry; |
593 | 601 | ||
594 | hcd->uses_new_polling = 1; | 602 | hcd->uses_new_polling = 1; |
595 | 603 | ||
@@ -599,18 +607,16 @@ static int uhci_start(struct usb_hcd *hcd) | |||
599 | INIT_LIST_HEAD(&uhci->idle_qh_list); | 607 | INIT_LIST_HEAD(&uhci->idle_qh_list); |
600 | init_waitqueue_head(&uhci->waitqh); | 608 | init_waitqueue_head(&uhci->waitqh); |
601 | 609 | ||
602 | if (DEBUG_CONFIGURED) { | 610 | #ifdef UHCI_DEBUG_OPS |
603 | dentry = debugfs_create_file(hcd->self.bus_name, | 611 | dentry = debugfs_create_file(hcd->self.bus_name, |
604 | S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, | 612 | S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, |
605 | uhci, &uhci_debug_operations); | 613 | uhci, &uhci_debug_operations); |
606 | if (!dentry) { | 614 | if (!dentry) { |
607 | dev_err(uhci_dev(uhci), "couldn't create uhci " | 615 | dev_err(uhci_dev(uhci), "couldn't create uhci debugfs entry\n"); |
608 | "debugfs entry\n"); | 616 | return -ENOMEM; |
609 | retval = -ENOMEM; | ||
610 | goto err_create_debug_entry; | ||
611 | } | ||
612 | uhci->dentry = dentry; | ||
613 | } | 617 | } |
618 | uhci->dentry = dentry; | ||
619 | #endif | ||
614 | 620 | ||
615 | uhci->frame = dma_alloc_coherent(uhci_dev(uhci), | 621 | uhci->frame = dma_alloc_coherent(uhci_dev(uhci), |
616 | UHCI_NUMFRAMES * sizeof(*uhci->frame), | 622 | UHCI_NUMFRAMES * sizeof(*uhci->frame), |
@@ -691,7 +697,9 @@ static int uhci_start(struct usb_hcd *hcd) | |||
691 | 697 | ||
692 | configure_hc(uhci); | 698 | configure_hc(uhci); |
693 | uhci->is_initialized = 1; | 699 | uhci->is_initialized = 1; |
700 | spin_lock_irq(&uhci->lock); | ||
694 | start_rh(uhci); | 701 | start_rh(uhci); |
702 | spin_unlock_irq(&uhci->lock); | ||
695 | return 0; | 703 | return 0; |
696 | 704 | ||
697 | /* | 705 | /* |
@@ -722,7 +730,6 @@ err_alloc_frame_cpu: | |||
722 | err_alloc_frame: | 730 | err_alloc_frame: |
723 | debugfs_remove(uhci->dentry); | 731 | debugfs_remove(uhci->dentry); |
724 | 732 | ||
725 | err_create_debug_entry: | ||
726 | return retval; | 733 | return retval; |
727 | } | 734 | } |
728 | 735 | ||
@@ -731,7 +738,7 @@ static void uhci_stop(struct usb_hcd *hcd) | |||
731 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 738 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
732 | 739 | ||
733 | spin_lock_irq(&uhci->lock); | 740 | spin_lock_irq(&uhci->lock); |
734 | if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead) | 741 | if (HCD_HW_ACCESSIBLE(hcd) && !uhci->dead) |
735 | uhci_hc_died(uhci); | 742 | uhci_hc_died(uhci); |
736 | uhci_scan_schedule(uhci); | 743 | uhci_scan_schedule(uhci); |
737 | spin_unlock_irq(&uhci->lock); | 744 | spin_unlock_irq(&uhci->lock); |
@@ -748,7 +755,7 @@ static int uhci_rh_suspend(struct usb_hcd *hcd) | |||
748 | int rc = 0; | 755 | int rc = 0; |
749 | 756 | ||
750 | spin_lock_irq(&uhci->lock); | 757 | spin_lock_irq(&uhci->lock); |
751 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) | 758 | if (!HCD_HW_ACCESSIBLE(hcd)) |
752 | rc = -ESHUTDOWN; | 759 | rc = -ESHUTDOWN; |
753 | else if (uhci->dead) | 760 | else if (uhci->dead) |
754 | ; /* Dead controllers tell no tales */ | 761 | ; /* Dead controllers tell no tales */ |
@@ -775,7 +782,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd) | |||
775 | int rc = 0; | 782 | int rc = 0; |
776 | 783 | ||
777 | spin_lock_irq(&uhci->lock); | 784 | spin_lock_irq(&uhci->lock); |
778 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) | 785 | if (!HCD_HW_ACCESSIBLE(hcd)) |
779 | rc = -ESHUTDOWN; | 786 | rc = -ESHUTDOWN; |
780 | else if (!uhci->dead) | 787 | else if (!uhci->dead) |
781 | wakeup_rh(uhci); | 788 | wakeup_rh(uhci); |
@@ -783,15 +790,16 @@ static int uhci_rh_resume(struct usb_hcd *hcd) | |||
783 | return rc; | 790 | return rc; |
784 | } | 791 | } |
785 | 792 | ||
786 | static int uhci_pci_suspend(struct usb_hcd *hcd) | 793 | static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) |
787 | { | 794 | { |
788 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 795 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
796 | struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci)); | ||
789 | int rc = 0; | 797 | int rc = 0; |
790 | 798 | ||
791 | dev_dbg(uhci_dev(uhci), "%s\n", __func__); | 799 | dev_dbg(uhci_dev(uhci), "%s\n", __func__); |
792 | 800 | ||
793 | spin_lock_irq(&uhci->lock); | 801 | spin_lock_irq(&uhci->lock); |
794 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) | 802 | if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead) |
795 | goto done_okay; /* Already suspended or dead */ | 803 | goto done_okay; /* Already suspended or dead */ |
796 | 804 | ||
797 | if (uhci->rh_state > UHCI_RH_SUSPENDED) { | 805 | if (uhci->rh_state > UHCI_RH_SUSPENDED) { |
@@ -803,11 +811,15 @@ static int uhci_pci_suspend(struct usb_hcd *hcd) | |||
803 | /* All PCI host controllers are required to disable IRQ generation | 811 | /* All PCI host controllers are required to disable IRQ generation |
804 | * at the source, so we must turn off PIRQ. | 812 | * at the source, so we must turn off PIRQ. |
805 | */ | 813 | */ |
806 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); | 814 | pci_write_config_word(pdev, USBLEGSUP, 0); |
807 | mb(); | 815 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
808 | hcd->poll_rh = 0; | 816 | |
809 | 817 | /* Enable platform-specific non-PME# wakeup */ | |
810 | /* FIXME: Enable non-PME# remote wakeup? */ | 818 | if (do_wakeup) { |
819 | if (pdev->vendor == PCI_VENDOR_ID_INTEL) | ||
820 | pci_write_config_byte(pdev, USBRES_INTEL, | ||
821 | USBPORT1EN | USBPORT2EN); | ||
822 | } | ||
811 | 823 | ||
812 | done_okay: | 824 | done_okay: |
813 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 825 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
@@ -826,7 +838,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) | |||
826 | * even if the controller was dead. | 838 | * even if the controller was dead. |
827 | */ | 839 | */ |
828 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 840 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
829 | mb(); | ||
830 | 841 | ||
831 | spin_lock_irq(&uhci->lock); | 842 | spin_lock_irq(&uhci->lock); |
832 | 843 | ||
@@ -834,8 +845,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) | |||
834 | if (hibernated) | 845 | if (hibernated) |
835 | uhci_hc_died(uhci); | 846 | uhci_hc_died(uhci); |
836 | 847 | ||
837 | /* FIXME: Disable non-PME# remote wakeup? */ | ||
838 | |||
839 | /* The firmware or a boot kernel may have changed the controller | 848 | /* The firmware or a boot kernel may have changed the controller |
840 | * settings during a system wakeup. Check it and reconfigure | 849 | * settings during a system wakeup. Check it and reconfigure |
841 | * to avoid problems. | 850 | * to avoid problems. |
@@ -845,22 +854,20 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) | |||
845 | /* If the controller was dead before, it's back alive now */ | 854 | /* If the controller was dead before, it's back alive now */ |
846 | configure_hc(uhci); | 855 | configure_hc(uhci); |
847 | 856 | ||
848 | if (uhci->rh_state == UHCI_RH_RESET) { | 857 | /* Tell the core if the controller had to be reset */ |
849 | 858 | if (uhci->rh_state == UHCI_RH_RESET) | |
850 | /* The controller had to be reset */ | ||
851 | usb_root_hub_lost_power(hcd->self.root_hub); | 859 | usb_root_hub_lost_power(hcd->self.root_hub); |
852 | suspend_rh(uhci, UHCI_RH_SUSPENDED); | ||
853 | } | ||
854 | 860 | ||
855 | spin_unlock_irq(&uhci->lock); | 861 | spin_unlock_irq(&uhci->lock); |
856 | 862 | ||
857 | /* If interrupts don't work and remote wakeup is enabled then | 863 | /* If interrupts don't work and remote wakeup is enabled then |
858 | * the suspended root hub needs to be polled. | 864 | * the suspended root hub needs to be polled. |
859 | */ | 865 | */ |
860 | if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) { | 866 | if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) |
861 | hcd->poll_rh = 1; | 867 | set_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
862 | usb_hcd_poll_rh_status(hcd); | 868 | |
863 | } | 869 | /* Does the root hub have a port wakeup pending? */ |
870 | usb_hcd_poll_rh_status(hcd); | ||
864 | return 0; | 871 | return 0; |
865 | } | 872 | } |
866 | #endif | 873 | #endif |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 26bd1b2bcbfc..49bf2790f9c2 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -67,12 +67,17 @@ | |||
67 | #define USBPORTSC_RES3 0x4000 /* reserved, write zeroes */ | 67 | #define USBPORTSC_RES3 0x4000 /* reserved, write zeroes */ |
68 | #define USBPORTSC_RES4 0x8000 /* reserved, write zeroes */ | 68 | #define USBPORTSC_RES4 0x8000 /* reserved, write zeroes */ |
69 | 69 | ||
70 | /* Legacy support register */ | 70 | /* PCI legacy support register */ |
71 | #define USBLEGSUP 0xc0 | 71 | #define USBLEGSUP 0xc0 |
72 | #define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ | 72 | #define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ |
73 | #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ | 73 | #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ |
74 | #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ | 74 | #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ |
75 | 75 | ||
76 | /* PCI Intel-specific resume-enable register */ | ||
77 | #define USBRES_INTEL 0xc4 | ||
78 | #define USBPORT1EN 0x01 | ||
79 | #define USBPORT2EN 0x02 | ||
80 | |||
76 | #define UHCI_PTR_BITS cpu_to_le32(0x000F) | 81 | #define UHCI_PTR_BITS cpu_to_le32(0x000F) |
77 | #define UHCI_PTR_TERM cpu_to_le32(0x0001) | 82 | #define UHCI_PTR_TERM cpu_to_le32(0x0001) |
78 | #define UHCI_PTR_QH cpu_to_le32(0x0002) | 83 | #define UHCI_PTR_QH cpu_to_le32(0x0002) |
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 8270055848ca..6d59c0f77f25 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c | |||
@@ -190,7 +190,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
190 | spin_lock_irqsave(&uhci->lock, flags); | 190 | spin_lock_irqsave(&uhci->lock, flags); |
191 | 191 | ||
192 | uhci_scan_schedule(uhci); | 192 | uhci_scan_schedule(uhci); |
193 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) | 193 | if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead) |
194 | goto done; | 194 | goto done; |
195 | uhci_check_ports(uhci); | 195 | uhci_check_ports(uhci); |
196 | 196 | ||
@@ -200,7 +200,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
200 | case UHCI_RH_SUSPENDING: | 200 | case UHCI_RH_SUSPENDING: |
201 | case UHCI_RH_SUSPENDED: | 201 | case UHCI_RH_SUSPENDED: |
202 | /* if port change, ask to be resumed */ | 202 | /* if port change, ask to be resumed */ |
203 | if (status) | 203 | if (status || uhci->resuming_ports) |
204 | usb_hcd_resume_root_hub(hcd); | 204 | usb_hcd_resume_root_hub(hcd); |
205 | break; | 205 | break; |
206 | 206 | ||
@@ -246,7 +246,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
246 | u16 wPortChange, wPortStatus; | 246 | u16 wPortChange, wPortStatus; |
247 | unsigned long flags; | 247 | unsigned long flags; |
248 | 248 | ||
249 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) | 249 | if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead) |
250 | return -ETIMEDOUT; | 250 | return -ETIMEDOUT; |
251 | 251 | ||
252 | spin_lock_irqsave(&uhci->lock, flags); | 252 | spin_lock_irqsave(&uhci->lock, flags); |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index acd582c02802..d3ade4018487 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -565,7 +565,7 @@ static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
565 | qh->unlink_frame = uhci->frame_number; | 565 | qh->unlink_frame = uhci->frame_number; |
566 | 566 | ||
567 | /* Force an interrupt so we know when the QH is fully unlinked */ | 567 | /* Force an interrupt so we know when the QH is fully unlinked */ |
568 | if (list_empty(&uhci->skel_unlink_qh->node)) | 568 | if (list_empty(&uhci->skel_unlink_qh->node) || uhci->is_stopped) |
569 | uhci_set_next_interrupt(uhci); | 569 | uhci_set_next_interrupt(uhci); |
570 | 570 | ||
571 | /* Move the QH from its old list to the end of the unlinking list */ | 571 | /* Move the QH from its old list to the end of the unlinking list */ |
@@ -1667,7 +1667,7 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
1667 | qh->advance_jiffies = jiffies; | 1667 | qh->advance_jiffies = jiffies; |
1668 | goto done; | 1668 | goto done; |
1669 | } | 1669 | } |
1670 | ret = 0; | 1670 | ret = uhci->is_stopped; |
1671 | } | 1671 | } |
1672 | 1672 | ||
1673 | /* The queue hasn't advanced; check for timeout */ | 1673 | /* The queue hasn't advanced; check for timeout */ |
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index e0d3401285c8..72b6892fda67 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c | |||
@@ -68,7 +68,7 @@ static int whc_start(struct usb_hcd *usb_hcd) | |||
68 | whc_write_wusbcmd(whc, WUSBCMD_RUN, WUSBCMD_RUN); | 68 | whc_write_wusbcmd(whc, WUSBCMD_RUN, WUSBCMD_RUN); |
69 | 69 | ||
70 | usb_hcd->uses_new_polling = 1; | 70 | usb_hcd->uses_new_polling = 1; |
71 | usb_hcd->poll_rh = 1; | 71 | set_bit(HCD_FLAG_POLL_RH, &usb_hcd->flags); |
72 | usb_hcd->state = HC_STATE_RUNNING; | 72 | usb_hcd->state = HC_STATE_RUNNING; |
73 | 73 | ||
74 | out: | 74 | out: |
diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index ab5a14fbfeeb..dc0ab8382f5d 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c | |||
@@ -475,7 +475,7 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u | |||
475 | || (prev_end & (WHCI_PAGE_SIZE-1)) | 475 | || (prev_end & (WHCI_PAGE_SIZE-1)) |
476 | || (dma_addr & (WHCI_PAGE_SIZE-1)) | 476 | || (dma_addr & (WHCI_PAGE_SIZE-1)) |
477 | || std->len + WHCI_PAGE_SIZE > QTD_MAX_XFER_SIZE) { | 477 | || std->len + WHCI_PAGE_SIZE > QTD_MAX_XFER_SIZE) { |
478 | if (std->len % qset->max_packet != 0) | 478 | if (std && std->len % qset->max_packet != 0) |
479 | return -EINVAL; | 479 | return -EINVAL; |
480 | std = qset_new_std(whc, qset, urb, mem_flags); | 480 | std = qset_new_std(whc, qset, urb, mem_flags); |
481 | if (std == NULL) { | 481 | if (std == NULL) { |
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 2eb658d26394..4e51343ddffc 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -391,49 +391,6 @@ struct xhci_ring *xhci_stream_id_to_ring( | |||
391 | return ep->stream_info->stream_rings[stream_id]; | 391 | return ep->stream_info->stream_rings[stream_id]; |
392 | } | 392 | } |
393 | 393 | ||
394 | struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, | ||
395 | unsigned int slot_id, unsigned int ep_index, | ||
396 | unsigned int stream_id) | ||
397 | { | ||
398 | struct xhci_virt_ep *ep; | ||
399 | |||
400 | ep = &xhci->devs[slot_id]->eps[ep_index]; | ||
401 | /* Common case: no streams */ | ||
402 | if (!(ep->ep_state & EP_HAS_STREAMS)) | ||
403 | return ep->ring; | ||
404 | |||
405 | if (stream_id == 0) { | ||
406 | xhci_warn(xhci, | ||
407 | "WARN: Slot ID %u, ep index %u has streams, " | ||
408 | "but URB has no stream ID.\n", | ||
409 | slot_id, ep_index); | ||
410 | return NULL; | ||
411 | } | ||
412 | |||
413 | if (stream_id < ep->stream_info->num_streams) | ||
414 | return ep->stream_info->stream_rings[stream_id]; | ||
415 | |||
416 | xhci_warn(xhci, | ||
417 | "WARN: Slot ID %u, ep index %u has " | ||
418 | "stream IDs 1 to %u allocated, " | ||
419 | "but stream ID %u is requested.\n", | ||
420 | slot_id, ep_index, | ||
421 | ep->stream_info->num_streams - 1, | ||
422 | stream_id); | ||
423 | return NULL; | ||
424 | } | ||
425 | |||
426 | /* Get the right ring for the given URB. | ||
427 | * If the endpoint supports streams, boundary check the URB's stream ID. | ||
428 | * If the endpoint doesn't support streams, return the singular endpoint ring. | ||
429 | */ | ||
430 | struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, | ||
431 | struct urb *urb) | ||
432 | { | ||
433 | return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id, | ||
434 | xhci_get_endpoint_index(&urb->ep->desc), urb->stream_id); | ||
435 | } | ||
436 | |||
437 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING | 394 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING |
438 | static int xhci_test_radix_tree(struct xhci_hcd *xhci, | 395 | static int xhci_test_radix_tree(struct xhci_hcd *xhci, |
439 | unsigned int num_streams, | 396 | unsigned int num_streams, |
@@ -1112,8 +1069,18 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, | |||
1112 | ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); | 1069 | ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); |
1113 | 1070 | ||
1114 | /* Set up the endpoint ring */ | 1071 | /* Set up the endpoint ring */ |
1115 | virt_dev->eps[ep_index].new_ring = | 1072 | /* |
1116 | xhci_ring_alloc(xhci, 1, true, mem_flags); | 1073 | * Isochronous endpoint ring needs bigger size because one isoc URB |
1074 | * carries multiple packets and it will insert multiple tds to the | ||
1075 | * ring. | ||
1076 | * This should be replaced with dynamic ring resizing in the future. | ||
1077 | */ | ||
1078 | if (usb_endpoint_xfer_isoc(&ep->desc)) | ||
1079 | virt_dev->eps[ep_index].new_ring = | ||
1080 | xhci_ring_alloc(xhci, 8, true, mem_flags); | ||
1081 | else | ||
1082 | virt_dev->eps[ep_index].new_ring = | ||
1083 | xhci_ring_alloc(xhci, 1, true, mem_flags); | ||
1117 | if (!virt_dev->eps[ep_index].new_ring) { | 1084 | if (!virt_dev->eps[ep_index].new_ring) { |
1118 | /* Attempt to use the ring cache */ | 1085 | /* Attempt to use the ring cache */ |
1119 | if (virt_dev->num_rings_cached == 0) | 1086 | if (virt_dev->num_rings_cached == 0) |
@@ -1124,6 +1091,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, | |||
1124 | virt_dev->num_rings_cached--; | 1091 | virt_dev->num_rings_cached--; |
1125 | xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring); | 1092 | xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring); |
1126 | } | 1093 | } |
1094 | virt_dev->eps[ep_index].skip = false; | ||
1127 | ep_ring = virt_dev->eps[ep_index].new_ring; | 1095 | ep_ring = virt_dev->eps[ep_index].new_ring; |
1128 | ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state; | 1096 | ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state; |
1129 | 1097 | ||
@@ -1389,6 +1357,22 @@ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, | |||
1389 | return command; | 1357 | return command; |
1390 | } | 1358 | } |
1391 | 1359 | ||
1360 | void xhci_urb_free_priv(struct xhci_hcd *xhci, struct urb_priv *urb_priv) | ||
1361 | { | ||
1362 | int last; | ||
1363 | |||
1364 | if (!urb_priv) | ||
1365 | return; | ||
1366 | |||
1367 | last = urb_priv->length - 1; | ||
1368 | if (last >= 0) { | ||
1369 | int i; | ||
1370 | for (i = 0; i <= last; i++) | ||
1371 | kfree(urb_priv->td[i]); | ||
1372 | } | ||
1373 | kfree(urb_priv); | ||
1374 | } | ||
1375 | |||
1392 | void xhci_free_command(struct xhci_hcd *xhci, | 1376 | void xhci_free_command(struct xhci_hcd *xhci, |
1393 | struct xhci_command *command) | 1377 | struct xhci_command *command) |
1394 | { | 1378 | { |
@@ -1588,7 +1572,7 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags) | |||
1588 | unsigned int num_tests; | 1572 | unsigned int num_tests; |
1589 | int i, ret; | 1573 | int i, ret; |
1590 | 1574 | ||
1591 | num_tests = sizeof(simple_test_vector) / sizeof(simple_test_vector[0]); | 1575 | num_tests = ARRAY_SIZE(simple_test_vector); |
1592 | for (i = 0; i < num_tests; i++) { | 1576 | for (i = 0; i < num_tests; i++) { |
1593 | ret = xhci_test_trb_in_td(xhci, | 1577 | ret = xhci_test_trb_in_td(xhci, |
1594 | xhci->event_ring->first_seg, | 1578 | xhci->event_ring->first_seg, |
@@ -1601,7 +1585,7 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags) | |||
1601 | return ret; | 1585 | return ret; |
1602 | } | 1586 | } |
1603 | 1587 | ||
1604 | num_tests = sizeof(complex_test_vector) / sizeof(complex_test_vector[0]); | 1588 | num_tests = ARRAY_SIZE(complex_test_vector); |
1605 | for (i = 0; i < num_tests; i++) { | 1589 | for (i = 0; i < num_tests; i++) { |
1606 | ret = xhci_test_trb_in_td(xhci, | 1590 | ret = xhci_test_trb_in_td(xhci, |
1607 | complex_test_vector[i].input_seg, | 1591 | complex_test_vector[i].input_seg, |
@@ -1617,6 +1601,29 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags) | |||
1617 | return 0; | 1601 | return 0; |
1618 | } | 1602 | } |
1619 | 1603 | ||
1604 | static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) | ||
1605 | { | ||
1606 | u64 temp; | ||
1607 | dma_addr_t deq; | ||
1608 | |||
1609 | deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, | ||
1610 | xhci->event_ring->dequeue); | ||
1611 | if (deq == 0 && !in_interrupt()) | ||
1612 | xhci_warn(xhci, "WARN something wrong with SW event ring " | ||
1613 | "dequeue ptr.\n"); | ||
1614 | /* Update HC event ring dequeue pointer */ | ||
1615 | temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); | ||
1616 | temp &= ERST_PTR_MASK; | ||
1617 | /* Don't clear the EHB bit (which is RW1C) because | ||
1618 | * there might be more events to service. | ||
1619 | */ | ||
1620 | temp &= ~ERST_EHB; | ||
1621 | xhci_dbg(xhci, "// Write event ring dequeue pointer, " | ||
1622 | "preserving EHB bit\n"); | ||
1623 | xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, | ||
1624 | &xhci->ir_set->erst_dequeue); | ||
1625 | } | ||
1626 | |||
1620 | 1627 | ||
1621 | int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | 1628 | int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) |
1622 | { | 1629 | { |
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 11482b6b9381..f7efe025beda 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c | |||
@@ -53,6 +53,7 @@ static int xhci_pci_setup(struct usb_hcd *hcd) | |||
53 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 53 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
54 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | 54 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); |
55 | int retval; | 55 | int retval; |
56 | u32 temp; | ||
56 | 57 | ||
57 | hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2; | 58 | hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2; |
58 | 59 | ||
@@ -93,6 +94,14 @@ static int xhci_pci_setup(struct usb_hcd *hcd) | |||
93 | return retval; | 94 | return retval; |
94 | xhci_dbg(xhci, "Reset complete\n"); | 95 | xhci_dbg(xhci, "Reset complete\n"); |
95 | 96 | ||
97 | temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params); | ||
98 | if (HCC_64BIT_ADDR(temp)) { | ||
99 | xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n"); | ||
100 | dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64)); | ||
101 | } else { | ||
102 | dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32)); | ||
103 | } | ||
104 | |||
96 | xhci_dbg(xhci, "Calling HCD init\n"); | 105 | xhci_dbg(xhci, "Calling HCD init\n"); |
97 | /* Initialize HCD and host controller data structures. */ | 106 | /* Initialize HCD and host controller data structures. */ |
98 | retval = xhci_init(hcd); | 107 | retval = xhci_init(hcd); |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index bfc99a939455..bc3f4f427065 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -301,28 +301,6 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, | |||
301 | return 1; | 301 | return 1; |
302 | } | 302 | } |
303 | 303 | ||
304 | void xhci_set_hc_event_deq(struct xhci_hcd *xhci) | ||
305 | { | ||
306 | u64 temp; | ||
307 | dma_addr_t deq; | ||
308 | |||
309 | deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, | ||
310 | xhci->event_ring->dequeue); | ||
311 | if (deq == 0 && !in_interrupt()) | ||
312 | xhci_warn(xhci, "WARN something wrong with SW event ring " | ||
313 | "dequeue ptr.\n"); | ||
314 | /* Update HC event ring dequeue pointer */ | ||
315 | temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); | ||
316 | temp &= ERST_PTR_MASK; | ||
317 | /* Don't clear the EHB bit (which is RW1C) because | ||
318 | * there might be more events to service. | ||
319 | */ | ||
320 | temp &= ~ERST_EHB; | ||
321 | xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n"); | ||
322 | xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, | ||
323 | &xhci->ir_set->erst_dequeue); | ||
324 | } | ||
325 | |||
326 | /* Ring the host controller doorbell after placing a command on the ring */ | 304 | /* Ring the host controller doorbell after placing a command on the ring */ |
327 | void xhci_ring_cmd_db(struct xhci_hcd *xhci) | 305 | void xhci_ring_cmd_db(struct xhci_hcd *xhci) |
328 | { | 306 | { |
@@ -359,11 +337,6 @@ static void ring_ep_doorbell(struct xhci_hcd *xhci, | |||
359 | field = xhci_readl(xhci, db_addr) & DB_MASK; | 337 | field = xhci_readl(xhci, db_addr) & DB_MASK; |
360 | field |= EPI_TO_DB(ep_index) | STREAM_ID_TO_DB(stream_id); | 338 | field |= EPI_TO_DB(ep_index) | STREAM_ID_TO_DB(stream_id); |
361 | xhci_writel(xhci, field, db_addr); | 339 | xhci_writel(xhci, field, db_addr); |
362 | /* Flush PCI posted writes - FIXME Matthew Wilcox says this | ||
363 | * isn't time-critical and we shouldn't make the CPU wait for | ||
364 | * the flush. | ||
365 | */ | ||
366 | xhci_readl(xhci, db_addr); | ||
367 | } | 340 | } |
368 | } | 341 | } |
369 | 342 | ||
@@ -419,6 +392,50 @@ static struct xhci_segment *find_trb_seg( | |||
419 | return cur_seg; | 392 | return cur_seg; |
420 | } | 393 | } |
421 | 394 | ||
395 | |||
396 | static struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, | ||
397 | unsigned int slot_id, unsigned int ep_index, | ||
398 | unsigned int stream_id) | ||
399 | { | ||
400 | struct xhci_virt_ep *ep; | ||
401 | |||
402 | ep = &xhci->devs[slot_id]->eps[ep_index]; | ||
403 | /* Common case: no streams */ | ||
404 | if (!(ep->ep_state & EP_HAS_STREAMS)) | ||
405 | return ep->ring; | ||
406 | |||
407 | if (stream_id == 0) { | ||
408 | xhci_warn(xhci, | ||
409 | "WARN: Slot ID %u, ep index %u has streams, " | ||
410 | "but URB has no stream ID.\n", | ||
411 | slot_id, ep_index); | ||
412 | return NULL; | ||
413 | } | ||
414 | |||
415 | if (stream_id < ep->stream_info->num_streams) | ||
416 | return ep->stream_info->stream_rings[stream_id]; | ||
417 | |||
418 | xhci_warn(xhci, | ||
419 | "WARN: Slot ID %u, ep index %u has " | ||
420 | "stream IDs 1 to %u allocated, " | ||
421 | "but stream ID %u is requested.\n", | ||
422 | slot_id, ep_index, | ||
423 | ep->stream_info->num_streams - 1, | ||
424 | stream_id); | ||
425 | return NULL; | ||
426 | } | ||
427 | |||
428 | /* Get the right ring for the given URB. | ||
429 | * If the endpoint supports streams, boundary check the URB's stream ID. | ||
430 | * If the endpoint doesn't support streams, return the singular endpoint ring. | ||
431 | */ | ||
432 | static struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, | ||
433 | struct urb *urb) | ||
434 | { | ||
435 | return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id, | ||
436 | xhci_get_endpoint_index(&urb->ep->desc), urb->stream_id); | ||
437 | } | ||
438 | |||
422 | /* | 439 | /* |
423 | * Move the xHC's endpoint ring dequeue pointer past cur_td. | 440 | * Move the xHC's endpoint ring dequeue pointer past cur_td. |
424 | * Record the new state of the xHC's endpoint ring dequeue segment, | 441 | * Record the new state of the xHC's endpoint ring dequeue segment, |
@@ -578,16 +595,24 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci, | |||
578 | struct xhci_td *cur_td, int status, char *adjective) | 595 | struct xhci_td *cur_td, int status, char *adjective) |
579 | { | 596 | { |
580 | struct usb_hcd *hcd = xhci_to_hcd(xhci); | 597 | struct usb_hcd *hcd = xhci_to_hcd(xhci); |
598 | struct urb *urb; | ||
599 | struct urb_priv *urb_priv; | ||
581 | 600 | ||
582 | cur_td->urb->hcpriv = NULL; | 601 | urb = cur_td->urb; |
583 | usb_hcd_unlink_urb_from_ep(hcd, cur_td->urb); | 602 | urb_priv = urb->hcpriv; |
584 | xhci_dbg(xhci, "Giveback %s URB %p\n", adjective, cur_td->urb); | 603 | urb_priv->td_cnt++; |
585 | 604 | ||
586 | spin_unlock(&xhci->lock); | 605 | /* Only giveback urb when this is the last td in urb */ |
587 | usb_hcd_giveback_urb(hcd, cur_td->urb, status); | 606 | if (urb_priv->td_cnt == urb_priv->length) { |
588 | kfree(cur_td); | 607 | usb_hcd_unlink_urb_from_ep(hcd, urb); |
589 | spin_lock(&xhci->lock); | 608 | xhci_dbg(xhci, "Giveback %s URB %p\n", adjective, urb); |
590 | xhci_dbg(xhci, "%s URB given back\n", adjective); | 609 | |
610 | spin_unlock(&xhci->lock); | ||
611 | usb_hcd_giveback_urb(hcd, urb, status); | ||
612 | xhci_urb_free_priv(xhci, urb_priv); | ||
613 | spin_lock(&xhci->lock); | ||
614 | xhci_dbg(xhci, "%s URB given back\n", adjective); | ||
615 | } | ||
591 | } | 616 | } |
592 | 617 | ||
593 | /* | 618 | /* |
@@ -1132,7 +1157,6 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1132 | 1157 | ||
1133 | /* Update event ring dequeue pointer before dropping the lock */ | 1158 | /* Update event ring dequeue pointer before dropping the lock */ |
1134 | inc_deq(xhci, xhci->event_ring, true); | 1159 | inc_deq(xhci, xhci->event_ring, true); |
1135 | xhci_set_hc_event_deq(xhci); | ||
1136 | 1160 | ||
1137 | spin_unlock(&xhci->lock); | 1161 | spin_unlock(&xhci->lock); |
1138 | /* Pass this up to the core */ | 1162 | /* Pass this up to the core */ |
@@ -1258,6 +1282,421 @@ int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code) | |||
1258 | } | 1282 | } |
1259 | 1283 | ||
1260 | /* | 1284 | /* |
1285 | * Finish the td processing, remove the td from td list; | ||
1286 | * Return 1 if the urb can be given back. | ||
1287 | */ | ||
1288 | static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, | ||
1289 | union xhci_trb *event_trb, struct xhci_transfer_event *event, | ||
1290 | struct xhci_virt_ep *ep, int *status, bool skip) | ||
1291 | { | ||
1292 | struct xhci_virt_device *xdev; | ||
1293 | struct xhci_ring *ep_ring; | ||
1294 | unsigned int slot_id; | ||
1295 | int ep_index; | ||
1296 | struct urb *urb = NULL; | ||
1297 | struct xhci_ep_ctx *ep_ctx; | ||
1298 | int ret = 0; | ||
1299 | struct urb_priv *urb_priv; | ||
1300 | u32 trb_comp_code; | ||
1301 | |||
1302 | slot_id = TRB_TO_SLOT_ID(event->flags); | ||
1303 | xdev = xhci->devs[slot_id]; | ||
1304 | ep_index = TRB_TO_EP_ID(event->flags) - 1; | ||
1305 | ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); | ||
1306 | ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); | ||
1307 | trb_comp_code = GET_COMP_CODE(event->transfer_len); | ||
1308 | |||
1309 | if (skip) | ||
1310 | goto td_cleanup; | ||
1311 | |||
1312 | if (trb_comp_code == COMP_STOP_INVAL || | ||
1313 | trb_comp_code == COMP_STOP) { | ||
1314 | /* The Endpoint Stop Command completion will take care of any | ||
1315 | * stopped TDs. A stopped TD may be restarted, so don't update | ||
1316 | * the ring dequeue pointer or take this TD off any lists yet. | ||
1317 | */ | ||
1318 | ep->stopped_td = td; | ||
1319 | ep->stopped_trb = event_trb; | ||
1320 | return 0; | ||
1321 | } else { | ||
1322 | if (trb_comp_code == COMP_STALL) { | ||
1323 | /* The transfer is completed from the driver's | ||
1324 | * perspective, but we need to issue a set dequeue | ||
1325 | * command for this stalled endpoint to move the dequeue | ||
1326 | * pointer past the TD. We can't do that here because | ||
1327 | * the halt condition must be cleared first. Let the | ||
1328 | * USB class driver clear the stall later. | ||
1329 | */ | ||
1330 | ep->stopped_td = td; | ||
1331 | ep->stopped_trb = event_trb; | ||
1332 | ep->stopped_stream = ep_ring->stream_id; | ||
1333 | } else if (xhci_requires_manual_halt_cleanup(xhci, | ||
1334 | ep_ctx, trb_comp_code)) { | ||
1335 | /* Other types of errors halt the endpoint, but the | ||
1336 | * class driver doesn't call usb_reset_endpoint() unless | ||
1337 | * the error is -EPIPE. Clear the halted status in the | ||
1338 | * xHCI hardware manually. | ||
1339 | */ | ||
1340 | xhci_cleanup_halted_endpoint(xhci, | ||
1341 | slot_id, ep_index, ep_ring->stream_id, | ||
1342 | td, event_trb); | ||
1343 | } else { | ||
1344 | /* Update ring dequeue pointer */ | ||
1345 | while (ep_ring->dequeue != td->last_trb) | ||
1346 | inc_deq(xhci, ep_ring, false); | ||
1347 | inc_deq(xhci, ep_ring, false); | ||
1348 | } | ||
1349 | |||
1350 | td_cleanup: | ||
1351 | /* Clean up the endpoint's TD list */ | ||
1352 | urb = td->urb; | ||
1353 | urb_priv = urb->hcpriv; | ||
1354 | |||
1355 | /* Do one last check of the actual transfer length. | ||
1356 | * If the host controller said we transferred more data than | ||
1357 | * the buffer length, urb->actual_length will be a very big | ||
1358 | * number (since it's unsigned). Play it safe and say we didn't | ||
1359 | * transfer anything. | ||
1360 | */ | ||
1361 | if (urb->actual_length > urb->transfer_buffer_length) { | ||
1362 | xhci_warn(xhci, "URB transfer length is wrong, " | ||
1363 | "xHC issue? req. len = %u, " | ||
1364 | "act. len = %u\n", | ||
1365 | urb->transfer_buffer_length, | ||
1366 | urb->actual_length); | ||
1367 | urb->actual_length = 0; | ||
1368 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1369 | *status = -EREMOTEIO; | ||
1370 | else | ||
1371 | *status = 0; | ||
1372 | } | ||
1373 | list_del(&td->td_list); | ||
1374 | /* Was this TD slated to be cancelled but completed anyway? */ | ||
1375 | if (!list_empty(&td->cancelled_td_list)) | ||
1376 | list_del(&td->cancelled_td_list); | ||
1377 | |||
1378 | urb_priv->td_cnt++; | ||
1379 | /* Giveback the urb when all the tds are completed */ | ||
1380 | if (urb_priv->td_cnt == urb_priv->length) | ||
1381 | ret = 1; | ||
1382 | } | ||
1383 | |||
1384 | return ret; | ||
1385 | } | ||
1386 | |||
1387 | /* | ||
1388 | * Process control tds, update urb status and actual_length. | ||
1389 | */ | ||
1390 | static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, | ||
1391 | union xhci_trb *event_trb, struct xhci_transfer_event *event, | ||
1392 | struct xhci_virt_ep *ep, int *status) | ||
1393 | { | ||
1394 | struct xhci_virt_device *xdev; | ||
1395 | struct xhci_ring *ep_ring; | ||
1396 | unsigned int slot_id; | ||
1397 | int ep_index; | ||
1398 | struct xhci_ep_ctx *ep_ctx; | ||
1399 | u32 trb_comp_code; | ||
1400 | |||
1401 | slot_id = TRB_TO_SLOT_ID(event->flags); | ||
1402 | xdev = xhci->devs[slot_id]; | ||
1403 | ep_index = TRB_TO_EP_ID(event->flags) - 1; | ||
1404 | ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); | ||
1405 | ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); | ||
1406 | trb_comp_code = GET_COMP_CODE(event->transfer_len); | ||
1407 | |||
1408 | xhci_debug_trb(xhci, xhci->event_ring->dequeue); | ||
1409 | switch (trb_comp_code) { | ||
1410 | case COMP_SUCCESS: | ||
1411 | if (event_trb == ep_ring->dequeue) { | ||
1412 | xhci_warn(xhci, "WARN: Success on ctrl setup TRB " | ||
1413 | "without IOC set??\n"); | ||
1414 | *status = -ESHUTDOWN; | ||
1415 | } else if (event_trb != td->last_trb) { | ||
1416 | xhci_warn(xhci, "WARN: Success on ctrl data TRB " | ||
1417 | "without IOC set??\n"); | ||
1418 | *status = -ESHUTDOWN; | ||
1419 | } else { | ||
1420 | xhci_dbg(xhci, "Successful control transfer!\n"); | ||
1421 | *status = 0; | ||
1422 | } | ||
1423 | break; | ||
1424 | case COMP_SHORT_TX: | ||
1425 | xhci_warn(xhci, "WARN: short transfer on control ep\n"); | ||
1426 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1427 | *status = -EREMOTEIO; | ||
1428 | else | ||
1429 | *status = 0; | ||
1430 | break; | ||
1431 | default: | ||
1432 | if (!xhci_requires_manual_halt_cleanup(xhci, | ||
1433 | ep_ctx, trb_comp_code)) | ||
1434 | break; | ||
1435 | xhci_dbg(xhci, "TRB error code %u, " | ||
1436 | "halted endpoint index = %u\n", | ||
1437 | trb_comp_code, ep_index); | ||
1438 | /* else fall through */ | ||
1439 | case COMP_STALL: | ||
1440 | /* Did we transfer part of the data (middle) phase? */ | ||
1441 | if (event_trb != ep_ring->dequeue && | ||
1442 | event_trb != td->last_trb) | ||
1443 | td->urb->actual_length = | ||
1444 | td->urb->transfer_buffer_length | ||
1445 | - TRB_LEN(event->transfer_len); | ||
1446 | else | ||
1447 | td->urb->actual_length = 0; | ||
1448 | |||
1449 | xhci_cleanup_halted_endpoint(xhci, | ||
1450 | slot_id, ep_index, 0, td, event_trb); | ||
1451 | return finish_td(xhci, td, event_trb, event, ep, status, true); | ||
1452 | } | ||
1453 | /* | ||
1454 | * Did we transfer any data, despite the errors that might have | ||
1455 | * happened? I.e. did we get past the setup stage? | ||
1456 | */ | ||
1457 | if (event_trb != ep_ring->dequeue) { | ||
1458 | /* The event was for the status stage */ | ||
1459 | if (event_trb == td->last_trb) { | ||
1460 | if (td->urb->actual_length != 0) { | ||
1461 | /* Don't overwrite a previously set error code | ||
1462 | */ | ||
1463 | if ((*status == -EINPROGRESS || *status == 0) && | ||
1464 | (td->urb->transfer_flags | ||
1465 | & URB_SHORT_NOT_OK)) | ||
1466 | /* Did we already see a short data | ||
1467 | * stage? */ | ||
1468 | *status = -EREMOTEIO; | ||
1469 | } else { | ||
1470 | td->urb->actual_length = | ||
1471 | td->urb->transfer_buffer_length; | ||
1472 | } | ||
1473 | } else { | ||
1474 | /* Maybe the event was for the data stage? */ | ||
1475 | if (trb_comp_code != COMP_STOP_INVAL) { | ||
1476 | /* We didn't stop on a link TRB in the middle */ | ||
1477 | td->urb->actual_length = | ||
1478 | td->urb->transfer_buffer_length - | ||
1479 | TRB_LEN(event->transfer_len); | ||
1480 | xhci_dbg(xhci, "Waiting for status " | ||
1481 | "stage event\n"); | ||
1482 | return 0; | ||
1483 | } | ||
1484 | } | ||
1485 | } | ||
1486 | |||
1487 | return finish_td(xhci, td, event_trb, event, ep, status, false); | ||
1488 | } | ||
1489 | |||
1490 | /* | ||
1491 | * Process isochronous tds, update urb packet status and actual_length. | ||
1492 | */ | ||
1493 | static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, | ||
1494 | union xhci_trb *event_trb, struct xhci_transfer_event *event, | ||
1495 | struct xhci_virt_ep *ep, int *status) | ||
1496 | { | ||
1497 | struct xhci_ring *ep_ring; | ||
1498 | struct urb_priv *urb_priv; | ||
1499 | int idx; | ||
1500 | int len = 0; | ||
1501 | int skip_td = 0; | ||
1502 | union xhci_trb *cur_trb; | ||
1503 | struct xhci_segment *cur_seg; | ||
1504 | u32 trb_comp_code; | ||
1505 | |||
1506 | ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); | ||
1507 | trb_comp_code = GET_COMP_CODE(event->transfer_len); | ||
1508 | urb_priv = td->urb->hcpriv; | ||
1509 | idx = urb_priv->td_cnt; | ||
1510 | |||
1511 | if (ep->skip) { | ||
1512 | /* The transfer is partly done */ | ||
1513 | *status = -EXDEV; | ||
1514 | td->urb->iso_frame_desc[idx].status = -EXDEV; | ||
1515 | } else { | ||
1516 | /* handle completion code */ | ||
1517 | switch (trb_comp_code) { | ||
1518 | case COMP_SUCCESS: | ||
1519 | td->urb->iso_frame_desc[idx].status = 0; | ||
1520 | xhci_dbg(xhci, "Successful isoc transfer!\n"); | ||
1521 | break; | ||
1522 | case COMP_SHORT_TX: | ||
1523 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1524 | td->urb->iso_frame_desc[idx].status = | ||
1525 | -EREMOTEIO; | ||
1526 | else | ||
1527 | td->urb->iso_frame_desc[idx].status = 0; | ||
1528 | break; | ||
1529 | case COMP_BW_OVER: | ||
1530 | td->urb->iso_frame_desc[idx].status = -ECOMM; | ||
1531 | skip_td = 1; | ||
1532 | break; | ||
1533 | case COMP_BUFF_OVER: | ||
1534 | case COMP_BABBLE: | ||
1535 | td->urb->iso_frame_desc[idx].status = -EOVERFLOW; | ||
1536 | skip_td = 1; | ||
1537 | break; | ||
1538 | case COMP_STALL: | ||
1539 | td->urb->iso_frame_desc[idx].status = -EPROTO; | ||
1540 | skip_td = 1; | ||
1541 | break; | ||
1542 | case COMP_STOP: | ||
1543 | case COMP_STOP_INVAL: | ||
1544 | break; | ||
1545 | default: | ||
1546 | td->urb->iso_frame_desc[idx].status = -1; | ||
1547 | break; | ||
1548 | } | ||
1549 | } | ||
1550 | |||
1551 | /* calc actual length */ | ||
1552 | if (ep->skip) { | ||
1553 | td->urb->iso_frame_desc[idx].actual_length = 0; | ||
1554 | return finish_td(xhci, td, event_trb, event, ep, status, true); | ||
1555 | } | ||
1556 | |||
1557 | if (trb_comp_code == COMP_SUCCESS || skip_td == 1) { | ||
1558 | td->urb->iso_frame_desc[idx].actual_length = | ||
1559 | td->urb->iso_frame_desc[idx].length; | ||
1560 | td->urb->actual_length += | ||
1561 | td->urb->iso_frame_desc[idx].length; | ||
1562 | } else { | ||
1563 | for (cur_trb = ep_ring->dequeue, | ||
1564 | cur_seg = ep_ring->deq_seg; cur_trb != event_trb; | ||
1565 | next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) { | ||
1566 | if ((cur_trb->generic.field[3] & | ||
1567 | TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) && | ||
1568 | (cur_trb->generic.field[3] & | ||
1569 | TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK)) | ||
1570 | len += | ||
1571 | TRB_LEN(cur_trb->generic.field[2]); | ||
1572 | } | ||
1573 | len += TRB_LEN(cur_trb->generic.field[2]) - | ||
1574 | TRB_LEN(event->transfer_len); | ||
1575 | |||
1576 | if (trb_comp_code != COMP_STOP_INVAL) { | ||
1577 | td->urb->iso_frame_desc[idx].actual_length = len; | ||
1578 | td->urb->actual_length += len; | ||
1579 | } | ||
1580 | } | ||
1581 | |||
1582 | if ((idx == urb_priv->length - 1) && *status == -EINPROGRESS) | ||
1583 | *status = 0; | ||
1584 | |||
1585 | return finish_td(xhci, td, event_trb, event, ep, status, false); | ||
1586 | } | ||
1587 | |||
1588 | /* | ||
1589 | * Process bulk and interrupt tds, update urb status and actual_length. | ||
1590 | */ | ||
1591 | static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, | ||
1592 | union xhci_trb *event_trb, struct xhci_transfer_event *event, | ||
1593 | struct xhci_virt_ep *ep, int *status) | ||
1594 | { | ||
1595 | struct xhci_ring *ep_ring; | ||
1596 | union xhci_trb *cur_trb; | ||
1597 | struct xhci_segment *cur_seg; | ||
1598 | u32 trb_comp_code; | ||
1599 | |||
1600 | ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); | ||
1601 | trb_comp_code = GET_COMP_CODE(event->transfer_len); | ||
1602 | |||
1603 | switch (trb_comp_code) { | ||
1604 | case COMP_SUCCESS: | ||
1605 | /* Double check that the HW transferred everything. */ | ||
1606 | if (event_trb != td->last_trb) { | ||
1607 | xhci_warn(xhci, "WARN Successful completion " | ||
1608 | "on short TX\n"); | ||
1609 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1610 | *status = -EREMOTEIO; | ||
1611 | else | ||
1612 | *status = 0; | ||
1613 | } else { | ||
1614 | if (usb_endpoint_xfer_bulk(&td->urb->ep->desc)) | ||
1615 | xhci_dbg(xhci, "Successful bulk " | ||
1616 | "transfer!\n"); | ||
1617 | else | ||
1618 | xhci_dbg(xhci, "Successful interrupt " | ||
1619 | "transfer!\n"); | ||
1620 | *status = 0; | ||
1621 | } | ||
1622 | break; | ||
1623 | case COMP_SHORT_TX: | ||
1624 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1625 | *status = -EREMOTEIO; | ||
1626 | else | ||
1627 | *status = 0; | ||
1628 | break; | ||
1629 | default: | ||
1630 | /* Others already handled above */ | ||
1631 | break; | ||
1632 | } | ||
1633 | dev_dbg(&td->urb->dev->dev, | ||
1634 | "ep %#x - asked for %d bytes, " | ||
1635 | "%d bytes untransferred\n", | ||
1636 | td->urb->ep->desc.bEndpointAddress, | ||
1637 | td->urb->transfer_buffer_length, | ||
1638 | TRB_LEN(event->transfer_len)); | ||
1639 | /* Fast path - was this the last TRB in the TD for this URB? */ | ||
1640 | if (event_trb == td->last_trb) { | ||
1641 | if (TRB_LEN(event->transfer_len) != 0) { | ||
1642 | td->urb->actual_length = | ||
1643 | td->urb->transfer_buffer_length - | ||
1644 | TRB_LEN(event->transfer_len); | ||
1645 | if (td->urb->transfer_buffer_length < | ||
1646 | td->urb->actual_length) { | ||
1647 | xhci_warn(xhci, "HC gave bad length " | ||
1648 | "of %d bytes left\n", | ||
1649 | TRB_LEN(event->transfer_len)); | ||
1650 | td->urb->actual_length = 0; | ||
1651 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1652 | *status = -EREMOTEIO; | ||
1653 | else | ||
1654 | *status = 0; | ||
1655 | } | ||
1656 | /* Don't overwrite a previously set error code */ | ||
1657 | if (*status == -EINPROGRESS) { | ||
1658 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1659 | *status = -EREMOTEIO; | ||
1660 | else | ||
1661 | *status = 0; | ||
1662 | } | ||
1663 | } else { | ||
1664 | td->urb->actual_length = | ||
1665 | td->urb->transfer_buffer_length; | ||
1666 | /* Ignore a short packet completion if the | ||
1667 | * untransferred length was zero. | ||
1668 | */ | ||
1669 | if (*status == -EREMOTEIO) | ||
1670 | *status = 0; | ||
1671 | } | ||
1672 | } else { | ||
1673 | /* Slow path - walk the list, starting from the dequeue | ||
1674 | * pointer, to get the actual length transferred. | ||
1675 | */ | ||
1676 | td->urb->actual_length = 0; | ||
1677 | for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg; | ||
1678 | cur_trb != event_trb; | ||
1679 | next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) { | ||
1680 | if ((cur_trb->generic.field[3] & | ||
1681 | TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) && | ||
1682 | (cur_trb->generic.field[3] & | ||
1683 | TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK)) | ||
1684 | td->urb->actual_length += | ||
1685 | TRB_LEN(cur_trb->generic.field[2]); | ||
1686 | } | ||
1687 | /* If the ring didn't stop on a Link or No-op TRB, add | ||
1688 | * in the actual bytes transferred from the Normal TRB | ||
1689 | */ | ||
1690 | if (trb_comp_code != COMP_STOP_INVAL) | ||
1691 | td->urb->actual_length += | ||
1692 | TRB_LEN(cur_trb->generic.field[2]) - | ||
1693 | TRB_LEN(event->transfer_len); | ||
1694 | } | ||
1695 | |||
1696 | return finish_td(xhci, td, event_trb, event, ep, status, false); | ||
1697 | } | ||
1698 | |||
1699 | /* | ||
1261 | * If this function returns an error condition, it means it got a Transfer | 1700 | * If this function returns an error condition, it means it got a Transfer |
1262 | * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address. | 1701 | * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address. |
1263 | * At this point, the host controller is probably hosed and should be reset. | 1702 | * At this point, the host controller is probably hosed and should be reset. |
@@ -1276,10 +1715,11 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1276 | union xhci_trb *event_trb; | 1715 | union xhci_trb *event_trb; |
1277 | struct urb *urb = NULL; | 1716 | struct urb *urb = NULL; |
1278 | int status = -EINPROGRESS; | 1717 | int status = -EINPROGRESS; |
1718 | struct urb_priv *urb_priv; | ||
1279 | struct xhci_ep_ctx *ep_ctx; | 1719 | struct xhci_ep_ctx *ep_ctx; |
1280 | u32 trb_comp_code; | 1720 | u32 trb_comp_code; |
1721 | int ret = 0; | ||
1281 | 1722 | ||
1282 | xhci_dbg(xhci, "In %s\n", __func__); | ||
1283 | slot_id = TRB_TO_SLOT_ID(event->flags); | 1723 | slot_id = TRB_TO_SLOT_ID(event->flags); |
1284 | xdev = xhci->devs[slot_id]; | 1724 | xdev = xhci->devs[slot_id]; |
1285 | if (!xdev) { | 1725 | if (!xdev) { |
@@ -1293,51 +1733,16 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1293 | ep = &xdev->eps[ep_index]; | 1733 | ep = &xdev->eps[ep_index]; |
1294 | ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); | 1734 | ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); |
1295 | ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); | 1735 | ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); |
1296 | if (!ep_ring || (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) { | 1736 | if (!ep_ring || |
1737 | (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) { | ||
1297 | xhci_err(xhci, "ERROR Transfer event for disabled endpoint " | 1738 | xhci_err(xhci, "ERROR Transfer event for disabled endpoint " |
1298 | "or incorrect stream ring\n"); | 1739 | "or incorrect stream ring\n"); |
1299 | return -ENODEV; | 1740 | return -ENODEV; |
1300 | } | 1741 | } |
1301 | 1742 | ||
1302 | event_dma = event->buffer; | 1743 | event_dma = event->buffer; |
1303 | /* This TRB should be in the TD at the head of this ring's TD list */ | ||
1304 | xhci_dbg(xhci, "%s - checking for list empty\n", __func__); | ||
1305 | if (list_empty(&ep_ring->td_list)) { | ||
1306 | xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", | ||
1307 | TRB_TO_SLOT_ID(event->flags), ep_index); | ||
1308 | xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", | ||
1309 | (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10); | ||
1310 | xhci_print_trb_offsets(xhci, (union xhci_trb *) event); | ||
1311 | urb = NULL; | ||
1312 | goto cleanup; | ||
1313 | } | ||
1314 | xhci_dbg(xhci, "%s - getting list entry\n", __func__); | ||
1315 | td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list); | ||
1316 | |||
1317 | /* Is this a TRB in the currently executing TD? */ | ||
1318 | xhci_dbg(xhci, "%s - looking for TD\n", __func__); | ||
1319 | event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue, | ||
1320 | td->last_trb, event_dma); | ||
1321 | xhci_dbg(xhci, "%s - found event_seg = %p\n", __func__, event_seg); | ||
1322 | if (!event_seg) { | ||
1323 | /* HC is busted, give up! */ | ||
1324 | xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not part of current TD\n"); | ||
1325 | return -ESHUTDOWN; | ||
1326 | } | ||
1327 | event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)]; | ||
1328 | xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", | ||
1329 | (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10); | ||
1330 | xhci_dbg(xhci, "Offset 0x00 (buffer lo) = 0x%x\n", | ||
1331 | lower_32_bits(event->buffer)); | ||
1332 | xhci_dbg(xhci, "Offset 0x04 (buffer hi) = 0x%x\n", | ||
1333 | upper_32_bits(event->buffer)); | ||
1334 | xhci_dbg(xhci, "Offset 0x08 (transfer length) = 0x%x\n", | ||
1335 | (unsigned int) event->transfer_len); | ||
1336 | xhci_dbg(xhci, "Offset 0x0C (flags) = 0x%x\n", | ||
1337 | (unsigned int) event->flags); | ||
1338 | |||
1339 | /* Look for common error cases */ | ||
1340 | trb_comp_code = GET_COMP_CODE(event->transfer_len); | 1744 | trb_comp_code = GET_COMP_CODE(event->transfer_len); |
1745 | /* Look for common error cases */ | ||
1341 | switch (trb_comp_code) { | 1746 | switch (trb_comp_code) { |
1342 | /* Skip codes that require special handling depending on | 1747 | /* Skip codes that require special handling depending on |
1343 | * transfer type | 1748 | * transfer type |
@@ -1373,278 +1778,156 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1373 | xhci_warn(xhci, "WARN: HC couldn't access mem fast enough\n"); | 1778 | xhci_warn(xhci, "WARN: HC couldn't access mem fast enough\n"); |
1374 | status = -ENOSR; | 1779 | status = -ENOSR; |
1375 | break; | 1780 | break; |
1781 | case COMP_BW_OVER: | ||
1782 | xhci_warn(xhci, "WARN: bandwidth overrun event on endpoint\n"); | ||
1783 | break; | ||
1784 | case COMP_BUFF_OVER: | ||
1785 | xhci_warn(xhci, "WARN: buffer overrun event on endpoint\n"); | ||
1786 | break; | ||
1787 | case COMP_UNDERRUN: | ||
1788 | /* | ||
1789 | * When the Isoch ring is empty, the xHC will generate | ||
1790 | * a Ring Overrun Event for IN Isoch endpoint or Ring | ||
1791 | * Underrun Event for OUT Isoch endpoint. | ||
1792 | */ | ||
1793 | xhci_dbg(xhci, "underrun event on endpoint\n"); | ||
1794 | if (!list_empty(&ep_ring->td_list)) | ||
1795 | xhci_dbg(xhci, "Underrun Event for slot %d ep %d " | ||
1796 | "still with TDs queued?\n", | ||
1797 | TRB_TO_SLOT_ID(event->flags), ep_index); | ||
1798 | goto cleanup; | ||
1799 | case COMP_OVERRUN: | ||
1800 | xhci_dbg(xhci, "overrun event on endpoint\n"); | ||
1801 | if (!list_empty(&ep_ring->td_list)) | ||
1802 | xhci_dbg(xhci, "Overrun Event for slot %d ep %d " | ||
1803 | "still with TDs queued?\n", | ||
1804 | TRB_TO_SLOT_ID(event->flags), ep_index); | ||
1805 | goto cleanup; | ||
1806 | case COMP_MISSED_INT: | ||
1807 | /* | ||
1808 | * When encounter missed service error, one or more isoc tds | ||
1809 | * may be missed by xHC. | ||
1810 | * Set skip flag of the ep_ring; Complete the missed tds as | ||
1811 | * short transfer when process the ep_ring next time. | ||
1812 | */ | ||
1813 | ep->skip = true; | ||
1814 | xhci_dbg(xhci, "Miss service interval error, set skip flag\n"); | ||
1815 | goto cleanup; | ||
1376 | default: | 1816 | default: |
1377 | if (xhci_is_vendor_info_code(xhci, trb_comp_code)) { | 1817 | if (xhci_is_vendor_info_code(xhci, trb_comp_code)) { |
1378 | status = 0; | 1818 | status = 0; |
1379 | break; | 1819 | break; |
1380 | } | 1820 | } |
1381 | xhci_warn(xhci, "ERROR Unknown event condition, HC probably busted\n"); | 1821 | xhci_warn(xhci, "ERROR Unknown event condition, HC probably " |
1382 | urb = NULL; | 1822 | "busted\n"); |
1383 | goto cleanup; | 1823 | goto cleanup; |
1384 | } | 1824 | } |
1385 | /* Now update the urb's actual_length and give back to the core */ | ||
1386 | /* Was this a control transfer? */ | ||
1387 | if (usb_endpoint_xfer_control(&td->urb->ep->desc)) { | ||
1388 | xhci_debug_trb(xhci, xhci->event_ring->dequeue); | ||
1389 | switch (trb_comp_code) { | ||
1390 | case COMP_SUCCESS: | ||
1391 | if (event_trb == ep_ring->dequeue) { | ||
1392 | xhci_warn(xhci, "WARN: Success on ctrl setup TRB without IOC set??\n"); | ||
1393 | status = -ESHUTDOWN; | ||
1394 | } else if (event_trb != td->last_trb) { | ||
1395 | xhci_warn(xhci, "WARN: Success on ctrl data TRB without IOC set??\n"); | ||
1396 | status = -ESHUTDOWN; | ||
1397 | } else { | ||
1398 | xhci_dbg(xhci, "Successful control transfer!\n"); | ||
1399 | status = 0; | ||
1400 | } | ||
1401 | break; | ||
1402 | case COMP_SHORT_TX: | ||
1403 | xhci_warn(xhci, "WARN: short transfer on control ep\n"); | ||
1404 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1405 | status = -EREMOTEIO; | ||
1406 | else | ||
1407 | status = 0; | ||
1408 | break; | ||
1409 | 1825 | ||
1410 | default: | 1826 | do { |
1411 | if (!xhci_requires_manual_halt_cleanup(xhci, | 1827 | /* This TRB should be in the TD at the head of this ring's |
1412 | ep_ctx, trb_comp_code)) | 1828 | * TD list. |
1413 | break; | ||
1414 | xhci_dbg(xhci, "TRB error code %u, " | ||
1415 | "halted endpoint index = %u\n", | ||
1416 | trb_comp_code, ep_index); | ||
1417 | /* else fall through */ | ||
1418 | case COMP_STALL: | ||
1419 | /* Did we transfer part of the data (middle) phase? */ | ||
1420 | if (event_trb != ep_ring->dequeue && | ||
1421 | event_trb != td->last_trb) | ||
1422 | td->urb->actual_length = | ||
1423 | td->urb->transfer_buffer_length | ||
1424 | - TRB_LEN(event->transfer_len); | ||
1425 | else | ||
1426 | td->urb->actual_length = 0; | ||
1427 | |||
1428 | xhci_cleanup_halted_endpoint(xhci, | ||
1429 | slot_id, ep_index, 0, td, event_trb); | ||
1430 | goto td_cleanup; | ||
1431 | } | ||
1432 | /* | ||
1433 | * Did we transfer any data, despite the errors that might have | ||
1434 | * happened? I.e. did we get past the setup stage? | ||
1435 | */ | 1829 | */ |
1436 | if (event_trb != ep_ring->dequeue) { | 1830 | if (list_empty(&ep_ring->td_list)) { |
1437 | /* The event was for the status stage */ | 1831 | xhci_warn(xhci, "WARN Event TRB for slot %d ep %d " |
1438 | if (event_trb == td->last_trb) { | 1832 | "with no TDs queued?\n", |
1439 | if (td->urb->actual_length != 0) { | 1833 | TRB_TO_SLOT_ID(event->flags), ep_index); |
1440 | /* Don't overwrite a previously set error code */ | 1834 | xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", |
1441 | if ((status == -EINPROGRESS || | 1835 | (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10); |
1442 | status == 0) && | 1836 | xhci_print_trb_offsets(xhci, (union xhci_trb *) event); |
1443 | (td->urb->transfer_flags | 1837 | if (ep->skip) { |
1444 | & URB_SHORT_NOT_OK)) | 1838 | ep->skip = false; |
1445 | /* Did we already see a short data stage? */ | 1839 | xhci_dbg(xhci, "td_list is empty while skip " |
1446 | status = -EREMOTEIO; | 1840 | "flag set. Clear skip flag.\n"); |
1447 | } else { | ||
1448 | td->urb->actual_length = | ||
1449 | td->urb->transfer_buffer_length; | ||
1450 | } | ||
1451 | } else { | ||
1452 | /* Maybe the event was for the data stage? */ | ||
1453 | if (trb_comp_code != COMP_STOP_INVAL) { | ||
1454 | /* We didn't stop on a link TRB in the middle */ | ||
1455 | td->urb->actual_length = | ||
1456 | td->urb->transfer_buffer_length - | ||
1457 | TRB_LEN(event->transfer_len); | ||
1458 | xhci_dbg(xhci, "Waiting for status stage event\n"); | ||
1459 | urb = NULL; | ||
1460 | goto cleanup; | ||
1461 | } | ||
1462 | } | 1841 | } |
1842 | ret = 0; | ||
1843 | goto cleanup; | ||
1463 | } | 1844 | } |
1464 | } else { | 1845 | |
1465 | switch (trb_comp_code) { | 1846 | td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list); |
1466 | case COMP_SUCCESS: | 1847 | /* Is this a TRB in the currently executing TD? */ |
1467 | /* Double check that the HW transferred everything. */ | 1848 | event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue, |
1468 | if (event_trb != td->last_trb) { | 1849 | td->last_trb, event_dma); |
1469 | xhci_warn(xhci, "WARN Successful completion " | 1850 | if (event_seg && ep->skip) { |
1470 | "on short TX\n"); | 1851 | xhci_dbg(xhci, "Found td. Clear skip flag.\n"); |
1471 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | 1852 | ep->skip = false; |
1472 | status = -EREMOTEIO; | 1853 | } |
1473 | else | 1854 | if (!event_seg && |
1474 | status = 0; | 1855 | (!ep->skip || !usb_endpoint_xfer_isoc(&td->urb->ep->desc))) { |
1475 | } else { | 1856 | /* HC is busted, give up! */ |
1476 | if (usb_endpoint_xfer_bulk(&td->urb->ep->desc)) | 1857 | xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not " |
1477 | xhci_dbg(xhci, "Successful bulk " | 1858 | "part of current TD\n"); |
1478 | "transfer!\n"); | 1859 | return -ESHUTDOWN; |
1479 | else | ||
1480 | xhci_dbg(xhci, "Successful interrupt " | ||
1481 | "transfer!\n"); | ||
1482 | status = 0; | ||
1483 | } | ||
1484 | break; | ||
1485 | case COMP_SHORT_TX: | ||
1486 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1487 | status = -EREMOTEIO; | ||
1488 | else | ||
1489 | status = 0; | ||
1490 | break; | ||
1491 | default: | ||
1492 | /* Others already handled above */ | ||
1493 | break; | ||
1494 | } | 1860 | } |
1495 | dev_dbg(&td->urb->dev->dev, | ||
1496 | "ep %#x - asked for %d bytes, " | ||
1497 | "%d bytes untransferred\n", | ||
1498 | td->urb->ep->desc.bEndpointAddress, | ||
1499 | td->urb->transfer_buffer_length, | ||
1500 | TRB_LEN(event->transfer_len)); | ||
1501 | /* Fast path - was this the last TRB in the TD for this URB? */ | ||
1502 | if (event_trb == td->last_trb) { | ||
1503 | if (TRB_LEN(event->transfer_len) != 0) { | ||
1504 | td->urb->actual_length = | ||
1505 | td->urb->transfer_buffer_length - | ||
1506 | TRB_LEN(event->transfer_len); | ||
1507 | if (td->urb->transfer_buffer_length < | ||
1508 | td->urb->actual_length) { | ||
1509 | xhci_warn(xhci, "HC gave bad length " | ||
1510 | "of %d bytes left\n", | ||
1511 | TRB_LEN(event->transfer_len)); | ||
1512 | td->urb->actual_length = 0; | ||
1513 | if (td->urb->transfer_flags & | ||
1514 | URB_SHORT_NOT_OK) | ||
1515 | status = -EREMOTEIO; | ||
1516 | else | ||
1517 | status = 0; | ||
1518 | } | ||
1519 | /* Don't overwrite a previously set error code */ | ||
1520 | if (status == -EINPROGRESS) { | ||
1521 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1522 | status = -EREMOTEIO; | ||
1523 | else | ||
1524 | status = 0; | ||
1525 | } | ||
1526 | } else { | ||
1527 | td->urb->actual_length = td->urb->transfer_buffer_length; | ||
1528 | /* Ignore a short packet completion if the | ||
1529 | * untransferred length was zero. | ||
1530 | */ | ||
1531 | if (status == -EREMOTEIO) | ||
1532 | status = 0; | ||
1533 | } | ||
1534 | } else { | ||
1535 | /* Slow path - walk the list, starting from the dequeue | ||
1536 | * pointer, to get the actual length transferred. | ||
1537 | */ | ||
1538 | union xhci_trb *cur_trb; | ||
1539 | struct xhci_segment *cur_seg; | ||
1540 | 1861 | ||
1541 | td->urb->actual_length = 0; | 1862 | if (event_seg) { |
1542 | for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg; | 1863 | event_trb = &event_seg->trbs[(event_dma - |
1543 | cur_trb != event_trb; | 1864 | event_seg->dma) / sizeof(*event_trb)]; |
1544 | next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) { | 1865 | /* |
1545 | if ((cur_trb->generic.field[3] & | 1866 | * No-op TRB should not trigger interrupts. |
1546 | TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) && | 1867 | * If event_trb is a no-op TRB, it means the |
1547 | (cur_trb->generic.field[3] & | 1868 | * corresponding TD has been cancelled. Just ignore |
1548 | TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK)) | 1869 | * the TD. |
1549 | td->urb->actual_length += | ||
1550 | TRB_LEN(cur_trb->generic.field[2]); | ||
1551 | } | ||
1552 | /* If the ring didn't stop on a Link or No-op TRB, add | ||
1553 | * in the actual bytes transferred from the Normal TRB | ||
1554 | */ | 1870 | */ |
1555 | if (trb_comp_code != COMP_STOP_INVAL) | 1871 | if ((event_trb->generic.field[3] & TRB_TYPE_BITMASK) |
1556 | td->urb->actual_length += | 1872 | == TRB_TYPE(TRB_TR_NOOP)) { |
1557 | TRB_LEN(cur_trb->generic.field[2]) - | 1873 | xhci_dbg(xhci, "event_trb is a no-op TRB. " |
1558 | TRB_LEN(event->transfer_len); | 1874 | "Skip it\n"); |
1875 | goto cleanup; | ||
1876 | } | ||
1559 | } | 1877 | } |
1560 | } | 1878 | |
1561 | if (trb_comp_code == COMP_STOP_INVAL || | 1879 | /* Now update the urb's actual_length and give back to |
1562 | trb_comp_code == COMP_STOP) { | 1880 | * the core |
1563 | /* The Endpoint Stop Command completion will take care of any | ||
1564 | * stopped TDs. A stopped TD may be restarted, so don't update | ||
1565 | * the ring dequeue pointer or take this TD off any lists yet. | ||
1566 | */ | 1881 | */ |
1567 | ep->stopped_td = td; | 1882 | if (usb_endpoint_xfer_control(&td->urb->ep->desc)) |
1568 | ep->stopped_trb = event_trb; | 1883 | ret = process_ctrl_td(xhci, td, event_trb, event, ep, |
1569 | } else { | 1884 | &status); |
1570 | if (trb_comp_code == COMP_STALL) { | 1885 | else if (usb_endpoint_xfer_isoc(&td->urb->ep->desc)) |
1571 | /* The transfer is completed from the driver's | 1886 | ret = process_isoc_td(xhci, td, event_trb, event, ep, |
1572 | * perspective, but we need to issue a set dequeue | 1887 | &status); |
1573 | * command for this stalled endpoint to move the dequeue | 1888 | else |
1574 | * pointer past the TD. We can't do that here because | 1889 | ret = process_bulk_intr_td(xhci, td, event_trb, event, |
1575 | * the halt condition must be cleared first. Let the | 1890 | ep, &status); |
1576 | * USB class driver clear the stall later. | ||
1577 | */ | ||
1578 | ep->stopped_td = td; | ||
1579 | ep->stopped_trb = event_trb; | ||
1580 | ep->stopped_stream = ep_ring->stream_id; | ||
1581 | } else if (xhci_requires_manual_halt_cleanup(xhci, | ||
1582 | ep_ctx, trb_comp_code)) { | ||
1583 | /* Other types of errors halt the endpoint, but the | ||
1584 | * class driver doesn't call usb_reset_endpoint() unless | ||
1585 | * the error is -EPIPE. Clear the halted status in the | ||
1586 | * xHCI hardware manually. | ||
1587 | */ | ||
1588 | xhci_cleanup_halted_endpoint(xhci, | ||
1589 | slot_id, ep_index, ep_ring->stream_id, td, event_trb); | ||
1590 | } else { | ||
1591 | /* Update ring dequeue pointer */ | ||
1592 | while (ep_ring->dequeue != td->last_trb) | ||
1593 | inc_deq(xhci, ep_ring, false); | ||
1594 | inc_deq(xhci, ep_ring, false); | ||
1595 | } | ||
1596 | 1891 | ||
1597 | td_cleanup: | 1892 | cleanup: |
1598 | /* Clean up the endpoint's TD list */ | 1893 | /* |
1599 | urb = td->urb; | 1894 | * Do not update event ring dequeue pointer if ep->skip is set. |
1600 | /* Do one last check of the actual transfer length. | 1895 | * Will roll back to continue process missed tds. |
1601 | * If the host controller said we transferred more data than | ||
1602 | * the buffer length, urb->actual_length will be a very big | ||
1603 | * number (since it's unsigned). Play it safe and say we didn't | ||
1604 | * transfer anything. | ||
1605 | */ | 1896 | */ |
1606 | if (urb->actual_length > urb->transfer_buffer_length) { | 1897 | if (trb_comp_code == COMP_MISSED_INT || !ep->skip) { |
1607 | xhci_warn(xhci, "URB transfer length is wrong, " | 1898 | inc_deq(xhci, xhci->event_ring, true); |
1608 | "xHC issue? req. len = %u, " | ||
1609 | "act. len = %u\n", | ||
1610 | urb->transfer_buffer_length, | ||
1611 | urb->actual_length); | ||
1612 | urb->actual_length = 0; | ||
1613 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1614 | status = -EREMOTEIO; | ||
1615 | else | ||
1616 | status = 0; | ||
1617 | } | 1899 | } |
1618 | list_del(&td->td_list); | ||
1619 | /* Was this TD slated to be cancelled but completed anyway? */ | ||
1620 | if (!list_empty(&td->cancelled_td_list)) | ||
1621 | list_del(&td->cancelled_td_list); | ||
1622 | 1900 | ||
1623 | /* Leave the TD around for the reset endpoint function to use | 1901 | if (ret) { |
1624 | * (but only if it's not a control endpoint, since we already | 1902 | urb = td->urb; |
1625 | * queued the Set TR dequeue pointer command for stalled | 1903 | urb_priv = urb->hcpriv; |
1626 | * control endpoints). | 1904 | /* Leave the TD around for the reset endpoint function |
1627 | */ | 1905 | * to use(but only if it's not a control endpoint, |
1628 | if (usb_endpoint_xfer_control(&urb->ep->desc) || | 1906 | * since we already queued the Set TR dequeue pointer |
1629 | (trb_comp_code != COMP_STALL && | 1907 | * command for stalled control endpoints). |
1630 | trb_comp_code != COMP_BABBLE)) { | 1908 | */ |
1631 | kfree(td); | 1909 | if (usb_endpoint_xfer_control(&urb->ep->desc) || |
1910 | (trb_comp_code != COMP_STALL && | ||
1911 | trb_comp_code != COMP_BABBLE)) | ||
1912 | xhci_urb_free_priv(xhci, urb_priv); | ||
1913 | |||
1914 | usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb); | ||
1915 | xhci_dbg(xhci, "Giveback URB %p, len = %d, " | ||
1916 | "status = %d\n", | ||
1917 | urb, urb->actual_length, status); | ||
1918 | spin_unlock(&xhci->lock); | ||
1919 | usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status); | ||
1920 | spin_lock(&xhci->lock); | ||
1632 | } | 1921 | } |
1633 | urb->hcpriv = NULL; | ||
1634 | } | ||
1635 | cleanup: | ||
1636 | inc_deq(xhci, xhci->event_ring, true); | ||
1637 | xhci_set_hc_event_deq(xhci); | ||
1638 | 1922 | ||
1639 | /* FIXME for multi-TD URBs (who have buffers bigger than 64MB) */ | 1923 | /* |
1640 | if (urb) { | 1924 | * If ep->skip is set, it means there are missed tds on the |
1641 | usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb); | 1925 | * endpoint ring need to take care of. |
1642 | xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n", | 1926 | * Process them as short transfer until reach the td pointed by |
1643 | urb, urb->actual_length, status); | 1927 | * the event. |
1644 | spin_unlock(&xhci->lock); | 1928 | */ |
1645 | usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status); | 1929 | } while (ep->skip && trb_comp_code != COMP_MISSED_INT); |
1646 | spin_lock(&xhci->lock); | 1930 | |
1647 | } | ||
1648 | return 0; | 1931 | return 0; |
1649 | } | 1932 | } |
1650 | 1933 | ||
@@ -1652,7 +1935,7 @@ cleanup: | |||
1652 | * This function handles all OS-owned events on the event ring. It may drop | 1935 | * This function handles all OS-owned events on the event ring. It may drop |
1653 | * xhci->lock between event processing (e.g. to pass up port status changes). | 1936 | * xhci->lock between event processing (e.g. to pass up port status changes). |
1654 | */ | 1937 | */ |
1655 | void xhci_handle_event(struct xhci_hcd *xhci) | 1938 | static void xhci_handle_event(struct xhci_hcd *xhci) |
1656 | { | 1939 | { |
1657 | union xhci_trb *event; | 1940 | union xhci_trb *event; |
1658 | int update_ptrs = 1; | 1941 | int update_ptrs = 1; |
@@ -1710,15 +1993,130 @@ void xhci_handle_event(struct xhci_hcd *xhci) | |||
1710 | return; | 1993 | return; |
1711 | } | 1994 | } |
1712 | 1995 | ||
1713 | if (update_ptrs) { | 1996 | if (update_ptrs) |
1714 | /* Update SW and HC event ring dequeue pointer */ | 1997 | /* Update SW event ring dequeue pointer */ |
1715 | inc_deq(xhci, xhci->event_ring, true); | 1998 | inc_deq(xhci, xhci->event_ring, true); |
1716 | xhci_set_hc_event_deq(xhci); | 1999 | |
1717 | } | ||
1718 | /* Are there more items on the event ring? */ | 2000 | /* Are there more items on the event ring? */ |
1719 | xhci_handle_event(xhci); | 2001 | xhci_handle_event(xhci); |
1720 | } | 2002 | } |
1721 | 2003 | ||
2004 | /* | ||
2005 | * xHCI spec says we can get an interrupt, and if the HC has an error condition, | ||
2006 | * we might get bad data out of the event ring. Section 4.10.2.7 has a list of | ||
2007 | * indicators of an event TRB error, but we check the status *first* to be safe. | ||
2008 | */ | ||
2009 | irqreturn_t xhci_irq(struct usb_hcd *hcd) | ||
2010 | { | ||
2011 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
2012 | u32 status; | ||
2013 | union xhci_trb *trb; | ||
2014 | u64 temp_64; | ||
2015 | union xhci_trb *event_ring_deq; | ||
2016 | dma_addr_t deq; | ||
2017 | |||
2018 | spin_lock(&xhci->lock); | ||
2019 | trb = xhci->event_ring->dequeue; | ||
2020 | /* Check if the xHC generated the interrupt, or the irq is shared */ | ||
2021 | status = xhci_readl(xhci, &xhci->op_regs->status); | ||
2022 | if (status == 0xffffffff) | ||
2023 | goto hw_died; | ||
2024 | |||
2025 | if (!(status & STS_EINT)) { | ||
2026 | spin_unlock(&xhci->lock); | ||
2027 | xhci_warn(xhci, "Spurious interrupt.\n"); | ||
2028 | return IRQ_NONE; | ||
2029 | } | ||
2030 | xhci_dbg(xhci, "op reg status = %08x\n", status); | ||
2031 | xhci_dbg(xhci, "Event ring dequeue ptr:\n"); | ||
2032 | xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n", | ||
2033 | (unsigned long long) | ||
2034 | xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb), | ||
2035 | lower_32_bits(trb->link.segment_ptr), | ||
2036 | upper_32_bits(trb->link.segment_ptr), | ||
2037 | (unsigned int) trb->link.intr_target, | ||
2038 | (unsigned int) trb->link.control); | ||
2039 | |||
2040 | if (status & STS_FATAL) { | ||
2041 | xhci_warn(xhci, "WARNING: Host System Error\n"); | ||
2042 | xhci_halt(xhci); | ||
2043 | hw_died: | ||
2044 | xhci_to_hcd(xhci)->state = HC_STATE_HALT; | ||
2045 | spin_unlock(&xhci->lock); | ||
2046 | return -ESHUTDOWN; | ||
2047 | } | ||
2048 | |||
2049 | /* | ||
2050 | * Clear the op reg interrupt status first, | ||
2051 | * so we can receive interrupts from other MSI-X interrupters. | ||
2052 | * Write 1 to clear the interrupt status. | ||
2053 | */ | ||
2054 | status |= STS_EINT; | ||
2055 | xhci_writel(xhci, status, &xhci->op_regs->status); | ||
2056 | /* FIXME when MSI-X is supported and there are multiple vectors */ | ||
2057 | /* Clear the MSI-X event interrupt status */ | ||
2058 | |||
2059 | if (hcd->irq != -1) { | ||
2060 | u32 irq_pending; | ||
2061 | /* Acknowledge the PCI interrupt */ | ||
2062 | irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); | ||
2063 | irq_pending |= 0x3; | ||
2064 | xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending); | ||
2065 | } | ||
2066 | |||
2067 | if (xhci->xhc_state & XHCI_STATE_DYING) { | ||
2068 | xhci_dbg(xhci, "xHCI dying, ignoring interrupt. " | ||
2069 | "Shouldn't IRQs be disabled?\n"); | ||
2070 | /* Clear the event handler busy flag (RW1C); | ||
2071 | * the event ring should be empty. | ||
2072 | */ | ||
2073 | temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); | ||
2074 | xhci_write_64(xhci, temp_64 | ERST_EHB, | ||
2075 | &xhci->ir_set->erst_dequeue); | ||
2076 | spin_unlock(&xhci->lock); | ||
2077 | |||
2078 | return IRQ_HANDLED; | ||
2079 | } | ||
2080 | |||
2081 | event_ring_deq = xhci->event_ring->dequeue; | ||
2082 | /* FIXME this should be a delayed service routine | ||
2083 | * that clears the EHB. | ||
2084 | */ | ||
2085 | xhci_handle_event(xhci); | ||
2086 | |||
2087 | temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); | ||
2088 | /* If necessary, update the HW's version of the event ring deq ptr. */ | ||
2089 | if (event_ring_deq != xhci->event_ring->dequeue) { | ||
2090 | deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, | ||
2091 | xhci->event_ring->dequeue); | ||
2092 | if (deq == 0) | ||
2093 | xhci_warn(xhci, "WARN something wrong with SW event " | ||
2094 | "ring dequeue ptr.\n"); | ||
2095 | /* Update HC event ring dequeue pointer */ | ||
2096 | temp_64 &= ERST_PTR_MASK; | ||
2097 | temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); | ||
2098 | } | ||
2099 | |||
2100 | /* Clear the event handler busy flag (RW1C); event ring is empty. */ | ||
2101 | temp_64 |= ERST_EHB; | ||
2102 | xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); | ||
2103 | |||
2104 | spin_unlock(&xhci->lock); | ||
2105 | |||
2106 | return IRQ_HANDLED; | ||
2107 | } | ||
2108 | |||
2109 | irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd) | ||
2110 | { | ||
2111 | irqreturn_t ret; | ||
2112 | |||
2113 | set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); | ||
2114 | |||
2115 | ret = xhci_irq(hcd); | ||
2116 | |||
2117 | return ret; | ||
2118 | } | ||
2119 | |||
1722 | /**** Endpoint Ring Operations ****/ | 2120 | /**** Endpoint Ring Operations ****/ |
1723 | 2121 | ||
1724 | /* | 2122 | /* |
@@ -1827,10 +2225,12 @@ static int prepare_transfer(struct xhci_hcd *xhci, | |||
1827 | unsigned int stream_id, | 2225 | unsigned int stream_id, |
1828 | unsigned int num_trbs, | 2226 | unsigned int num_trbs, |
1829 | struct urb *urb, | 2227 | struct urb *urb, |
1830 | struct xhci_td **td, | 2228 | unsigned int td_index, |
1831 | gfp_t mem_flags) | 2229 | gfp_t mem_flags) |
1832 | { | 2230 | { |
1833 | int ret; | 2231 | int ret; |
2232 | struct urb_priv *urb_priv; | ||
2233 | struct xhci_td *td; | ||
1834 | struct xhci_ring *ep_ring; | 2234 | struct xhci_ring *ep_ring; |
1835 | struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); | 2235 | struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); |
1836 | 2236 | ||
@@ -1846,24 +2246,29 @@ static int prepare_transfer(struct xhci_hcd *xhci, | |||
1846 | num_trbs, mem_flags); | 2246 | num_trbs, mem_flags); |
1847 | if (ret) | 2247 | if (ret) |
1848 | return ret; | 2248 | return ret; |
1849 | *td = kzalloc(sizeof(struct xhci_td), mem_flags); | ||
1850 | if (!*td) | ||
1851 | return -ENOMEM; | ||
1852 | INIT_LIST_HEAD(&(*td)->td_list); | ||
1853 | INIT_LIST_HEAD(&(*td)->cancelled_td_list); | ||
1854 | 2249 | ||
1855 | ret = usb_hcd_link_urb_to_ep(xhci_to_hcd(xhci), urb); | 2250 | urb_priv = urb->hcpriv; |
1856 | if (unlikely(ret)) { | 2251 | td = urb_priv->td[td_index]; |
1857 | kfree(*td); | 2252 | |
1858 | return ret; | 2253 | INIT_LIST_HEAD(&td->td_list); |
2254 | INIT_LIST_HEAD(&td->cancelled_td_list); | ||
2255 | |||
2256 | if (td_index == 0) { | ||
2257 | ret = usb_hcd_link_urb_to_ep(xhci_to_hcd(xhci), urb); | ||
2258 | if (unlikely(ret)) { | ||
2259 | xhci_urb_free_priv(xhci, urb_priv); | ||
2260 | urb->hcpriv = NULL; | ||
2261 | return ret; | ||
2262 | } | ||
1859 | } | 2263 | } |
1860 | 2264 | ||
1861 | (*td)->urb = urb; | 2265 | td->urb = urb; |
1862 | urb->hcpriv = (void *) (*td); | ||
1863 | /* Add this TD to the tail of the endpoint ring's TD list */ | 2266 | /* Add this TD to the tail of the endpoint ring's TD list */ |
1864 | list_add_tail(&(*td)->td_list, &ep_ring->td_list); | 2267 | list_add_tail(&td->td_list, &ep_ring->td_list); |
1865 | (*td)->start_seg = ep_ring->enq_seg; | 2268 | td->start_seg = ep_ring->enq_seg; |
1866 | (*td)->first_trb = ep_ring->enqueue; | 2269 | td->first_trb = ep_ring->enqueue; |
2270 | |||
2271 | urb_priv->td[td_index] = td; | ||
1867 | 2272 | ||
1868 | return 0; | 2273 | return 0; |
1869 | } | 2274 | } |
@@ -2002,6 +2407,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | |||
2002 | { | 2407 | { |
2003 | struct xhci_ring *ep_ring; | 2408 | struct xhci_ring *ep_ring; |
2004 | unsigned int num_trbs; | 2409 | unsigned int num_trbs; |
2410 | struct urb_priv *urb_priv; | ||
2005 | struct xhci_td *td; | 2411 | struct xhci_td *td; |
2006 | struct scatterlist *sg; | 2412 | struct scatterlist *sg; |
2007 | int num_sgs; | 2413 | int num_sgs; |
@@ -2022,9 +2428,13 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | |||
2022 | 2428 | ||
2023 | trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id], | 2429 | trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id], |
2024 | ep_index, urb->stream_id, | 2430 | ep_index, urb->stream_id, |
2025 | num_trbs, urb, &td, mem_flags); | 2431 | num_trbs, urb, 0, mem_flags); |
2026 | if (trb_buff_len < 0) | 2432 | if (trb_buff_len < 0) |
2027 | return trb_buff_len; | 2433 | return trb_buff_len; |
2434 | |||
2435 | urb_priv = urb->hcpriv; | ||
2436 | td = urb_priv->td[0]; | ||
2437 | |||
2028 | /* | 2438 | /* |
2029 | * Don't give the first TRB to the hardware (by toggling the cycle bit) | 2439 | * Don't give the first TRB to the hardware (by toggling the cycle bit) |
2030 | * until we've finished creating all the other TRBs. The ring's cycle | 2440 | * until we've finished creating all the other TRBs. The ring's cycle |
@@ -2145,6 +2555,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | |||
2145 | struct urb *urb, int slot_id, unsigned int ep_index) | 2555 | struct urb *urb, int slot_id, unsigned int ep_index) |
2146 | { | 2556 | { |
2147 | struct xhci_ring *ep_ring; | 2557 | struct xhci_ring *ep_ring; |
2558 | struct urb_priv *urb_priv; | ||
2148 | struct xhci_td *td; | 2559 | struct xhci_td *td; |
2149 | int num_trbs; | 2560 | int num_trbs; |
2150 | struct xhci_generic_trb *start_trb; | 2561 | struct xhci_generic_trb *start_trb; |
@@ -2190,10 +2601,13 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | |||
2190 | 2601 | ||
2191 | ret = prepare_transfer(xhci, xhci->devs[slot_id], | 2602 | ret = prepare_transfer(xhci, xhci->devs[slot_id], |
2192 | ep_index, urb->stream_id, | 2603 | ep_index, urb->stream_id, |
2193 | num_trbs, urb, &td, mem_flags); | 2604 | num_trbs, urb, 0, mem_flags); |
2194 | if (ret < 0) | 2605 | if (ret < 0) |
2195 | return ret; | 2606 | return ret; |
2196 | 2607 | ||
2608 | urb_priv = urb->hcpriv; | ||
2609 | td = urb_priv->td[0]; | ||
2610 | |||
2197 | /* | 2611 | /* |
2198 | * Don't give the first TRB to the hardware (by toggling the cycle bit) | 2612 | * Don't give the first TRB to the hardware (by toggling the cycle bit) |
2199 | * until we've finished creating all the other TRBs. The ring's cycle | 2613 | * until we've finished creating all the other TRBs. The ring's cycle |
@@ -2279,6 +2693,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | |||
2279 | struct xhci_generic_trb *start_trb; | 2693 | struct xhci_generic_trb *start_trb; |
2280 | int start_cycle; | 2694 | int start_cycle; |
2281 | u32 field, length_field; | 2695 | u32 field, length_field; |
2696 | struct urb_priv *urb_priv; | ||
2282 | struct xhci_td *td; | 2697 | struct xhci_td *td; |
2283 | 2698 | ||
2284 | ep_ring = xhci_urb_to_transfer_ring(xhci, urb); | 2699 | ep_ring = xhci_urb_to_transfer_ring(xhci, urb); |
@@ -2306,10 +2721,13 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | |||
2306 | num_trbs++; | 2721 | num_trbs++; |
2307 | ret = prepare_transfer(xhci, xhci->devs[slot_id], | 2722 | ret = prepare_transfer(xhci, xhci->devs[slot_id], |
2308 | ep_index, urb->stream_id, | 2723 | ep_index, urb->stream_id, |
2309 | num_trbs, urb, &td, mem_flags); | 2724 | num_trbs, urb, 0, mem_flags); |
2310 | if (ret < 0) | 2725 | if (ret < 0) |
2311 | return ret; | 2726 | return ret; |
2312 | 2727 | ||
2728 | urb_priv = urb->hcpriv; | ||
2729 | td = urb_priv->td[0]; | ||
2730 | |||
2313 | /* | 2731 | /* |
2314 | * Don't give the first TRB to the hardware (by toggling the cycle bit) | 2732 | * Don't give the first TRB to the hardware (by toggling the cycle bit) |
2315 | * until we've finished creating all the other TRBs. The ring's cycle | 2733 | * until we've finished creating all the other TRBs. The ring's cycle |
@@ -2366,6 +2784,224 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | |||
2366 | return 0; | 2784 | return 0; |
2367 | } | 2785 | } |
2368 | 2786 | ||
2787 | static int count_isoc_trbs_needed(struct xhci_hcd *xhci, | ||
2788 | struct urb *urb, int i) | ||
2789 | { | ||
2790 | int num_trbs = 0; | ||
2791 | u64 addr, td_len, running_total; | ||
2792 | |||
2793 | addr = (u64) (urb->transfer_dma + urb->iso_frame_desc[i].offset); | ||
2794 | td_len = urb->iso_frame_desc[i].length; | ||
2795 | |||
2796 | running_total = TRB_MAX_BUFF_SIZE - | ||
2797 | (addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1)); | ||
2798 | if (running_total != 0) | ||
2799 | num_trbs++; | ||
2800 | |||
2801 | while (running_total < td_len) { | ||
2802 | num_trbs++; | ||
2803 | running_total += TRB_MAX_BUFF_SIZE; | ||
2804 | } | ||
2805 | |||
2806 | return num_trbs; | ||
2807 | } | ||
2808 | |||
2809 | /* This is for isoc transfer */ | ||
2810 | static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | ||
2811 | struct urb *urb, int slot_id, unsigned int ep_index) | ||
2812 | { | ||
2813 | struct xhci_ring *ep_ring; | ||
2814 | struct urb_priv *urb_priv; | ||
2815 | struct xhci_td *td; | ||
2816 | int num_tds, trbs_per_td; | ||
2817 | struct xhci_generic_trb *start_trb; | ||
2818 | bool first_trb; | ||
2819 | int start_cycle; | ||
2820 | u32 field, length_field; | ||
2821 | int running_total, trb_buff_len, td_len, td_remain_len, ret; | ||
2822 | u64 start_addr, addr; | ||
2823 | int i, j; | ||
2824 | |||
2825 | ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; | ||
2826 | |||
2827 | num_tds = urb->number_of_packets; | ||
2828 | if (num_tds < 1) { | ||
2829 | xhci_dbg(xhci, "Isoc URB with zero packets?\n"); | ||
2830 | return -EINVAL; | ||
2831 | } | ||
2832 | |||
2833 | if (!in_interrupt()) | ||
2834 | dev_dbg(&urb->dev->dev, "ep %#x - urb len = %#x (%d)," | ||
2835 | " addr = %#llx, num_tds = %d\n", | ||
2836 | urb->ep->desc.bEndpointAddress, | ||
2837 | urb->transfer_buffer_length, | ||
2838 | urb->transfer_buffer_length, | ||
2839 | (unsigned long long)urb->transfer_dma, | ||
2840 | num_tds); | ||
2841 | |||
2842 | start_addr = (u64) urb->transfer_dma; | ||
2843 | start_trb = &ep_ring->enqueue->generic; | ||
2844 | start_cycle = ep_ring->cycle_state; | ||
2845 | |||
2846 | /* Queue the first TRB, even if it's zero-length */ | ||
2847 | for (i = 0; i < num_tds; i++) { | ||
2848 | first_trb = true; | ||
2849 | |||
2850 | running_total = 0; | ||
2851 | addr = start_addr + urb->iso_frame_desc[i].offset; | ||
2852 | td_len = urb->iso_frame_desc[i].length; | ||
2853 | td_remain_len = td_len; | ||
2854 | |||
2855 | trbs_per_td = count_isoc_trbs_needed(xhci, urb, i); | ||
2856 | |||
2857 | ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, | ||
2858 | urb->stream_id, trbs_per_td, urb, i, mem_flags); | ||
2859 | if (ret < 0) | ||
2860 | return ret; | ||
2861 | |||
2862 | urb_priv = urb->hcpriv; | ||
2863 | td = urb_priv->td[i]; | ||
2864 | |||
2865 | for (j = 0; j < trbs_per_td; j++) { | ||
2866 | u32 remainder = 0; | ||
2867 | field = 0; | ||
2868 | |||
2869 | if (first_trb) { | ||
2870 | /* Queue the isoc TRB */ | ||
2871 | field |= TRB_TYPE(TRB_ISOC); | ||
2872 | /* Assume URB_ISO_ASAP is set */ | ||
2873 | field |= TRB_SIA; | ||
2874 | if (i > 0) | ||
2875 | field |= ep_ring->cycle_state; | ||
2876 | first_trb = false; | ||
2877 | } else { | ||
2878 | /* Queue other normal TRBs */ | ||
2879 | field |= TRB_TYPE(TRB_NORMAL); | ||
2880 | field |= ep_ring->cycle_state; | ||
2881 | } | ||
2882 | |||
2883 | /* Chain all the TRBs together; clear the chain bit in | ||
2884 | * the last TRB to indicate it's the last TRB in the | ||
2885 | * chain. | ||
2886 | */ | ||
2887 | if (j < trbs_per_td - 1) { | ||
2888 | field |= TRB_CHAIN; | ||
2889 | } else { | ||
2890 | td->last_trb = ep_ring->enqueue; | ||
2891 | field |= TRB_IOC; | ||
2892 | } | ||
2893 | |||
2894 | /* Calculate TRB length */ | ||
2895 | trb_buff_len = TRB_MAX_BUFF_SIZE - | ||
2896 | (addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1)); | ||
2897 | if (trb_buff_len > td_remain_len) | ||
2898 | trb_buff_len = td_remain_len; | ||
2899 | |||
2900 | remainder = xhci_td_remainder(td_len - running_total); | ||
2901 | length_field = TRB_LEN(trb_buff_len) | | ||
2902 | remainder | | ||
2903 | TRB_INTR_TARGET(0); | ||
2904 | queue_trb(xhci, ep_ring, false, false, | ||
2905 | lower_32_bits(addr), | ||
2906 | upper_32_bits(addr), | ||
2907 | length_field, | ||
2908 | /* We always want to know if the TRB was short, | ||
2909 | * or we won't get an event when it completes. | ||
2910 | * (Unless we use event data TRBs, which are a | ||
2911 | * waste of space and HC resources.) | ||
2912 | */ | ||
2913 | field | TRB_ISP); | ||
2914 | running_total += trb_buff_len; | ||
2915 | |||
2916 | addr += trb_buff_len; | ||
2917 | td_remain_len -= trb_buff_len; | ||
2918 | } | ||
2919 | |||
2920 | /* Check TD length */ | ||
2921 | if (running_total != td_len) { | ||
2922 | xhci_err(xhci, "ISOC TD length unmatch\n"); | ||
2923 | return -EINVAL; | ||
2924 | } | ||
2925 | } | ||
2926 | |||
2927 | wmb(); | ||
2928 | start_trb->field[3] |= start_cycle; | ||
2929 | |||
2930 | ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id); | ||
2931 | return 0; | ||
2932 | } | ||
2933 | |||
2934 | /* | ||
2935 | * Check transfer ring to guarantee there is enough room for the urb. | ||
2936 | * Update ISO URB start_frame and interval. | ||
2937 | * Update interval as xhci_queue_intr_tx does. Just use xhci frame_index to | ||
2938 | * update the urb->start_frame by now. | ||
2939 | * Always assume URB_ISO_ASAP set, and NEVER use urb->start_frame as input. | ||
2940 | */ | ||
2941 | int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, | ||
2942 | struct urb *urb, int slot_id, unsigned int ep_index) | ||
2943 | { | ||
2944 | struct xhci_virt_device *xdev; | ||
2945 | struct xhci_ring *ep_ring; | ||
2946 | struct xhci_ep_ctx *ep_ctx; | ||
2947 | int start_frame; | ||
2948 | int xhci_interval; | ||
2949 | int ep_interval; | ||
2950 | int num_tds, num_trbs, i; | ||
2951 | int ret; | ||
2952 | |||
2953 | xdev = xhci->devs[slot_id]; | ||
2954 | ep_ring = xdev->eps[ep_index].ring; | ||
2955 | ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); | ||
2956 | |||
2957 | num_trbs = 0; | ||
2958 | num_tds = urb->number_of_packets; | ||
2959 | for (i = 0; i < num_tds; i++) | ||
2960 | num_trbs += count_isoc_trbs_needed(xhci, urb, i); | ||
2961 | |||
2962 | /* Check the ring to guarantee there is enough room for the whole urb. | ||
2963 | * Do not insert any td of the urb to the ring if the check failed. | ||
2964 | */ | ||
2965 | ret = prepare_ring(xhci, ep_ring, ep_ctx->ep_info & EP_STATE_MASK, | ||
2966 | num_trbs, mem_flags); | ||
2967 | if (ret) | ||
2968 | return ret; | ||
2969 | |||
2970 | start_frame = xhci_readl(xhci, &xhci->run_regs->microframe_index); | ||
2971 | start_frame &= 0x3fff; | ||
2972 | |||
2973 | urb->start_frame = start_frame; | ||
2974 | if (urb->dev->speed == USB_SPEED_LOW || | ||
2975 | urb->dev->speed == USB_SPEED_FULL) | ||
2976 | urb->start_frame >>= 3; | ||
2977 | |||
2978 | xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info); | ||
2979 | ep_interval = urb->interval; | ||
2980 | /* Convert to microframes */ | ||
2981 | if (urb->dev->speed == USB_SPEED_LOW || | ||
2982 | urb->dev->speed == USB_SPEED_FULL) | ||
2983 | ep_interval *= 8; | ||
2984 | /* FIXME change this to a warning and a suggestion to use the new API | ||
2985 | * to set the polling interval (once the API is added). | ||
2986 | */ | ||
2987 | if (xhci_interval != ep_interval) { | ||
2988 | if (!printk_ratelimit()) | ||
2989 | dev_dbg(&urb->dev->dev, "Driver uses different interval" | ||
2990 | " (%d microframe%s) than xHCI " | ||
2991 | "(%d microframe%s)\n", | ||
2992 | ep_interval, | ||
2993 | ep_interval == 1 ? "" : "s", | ||
2994 | xhci_interval, | ||
2995 | xhci_interval == 1 ? "" : "s"); | ||
2996 | urb->interval = xhci_interval; | ||
2997 | /* Convert back to frames for LS/FS devices */ | ||
2998 | if (urb->dev->speed == USB_SPEED_LOW || | ||
2999 | urb->dev->speed == USB_SPEED_FULL) | ||
3000 | urb->interval /= 8; | ||
3001 | } | ||
3002 | return xhci_queue_isoc_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); | ||
3003 | } | ||
3004 | |||
2369 | /**** Command Ring Operations ****/ | 3005 | /**** Command Ring Operations ****/ |
2370 | 3006 | ||
2371 | /* Generic function for queueing a command TRB on the command ring. | 3007 | /* Generic function for queueing a command TRB on the command ring. |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3998f72cd0c4..d5c550ea3e68 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -20,6 +20,7 @@ | |||
20 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 20 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/pci.h> | ||
23 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
24 | #include <linux/log2.h> | 25 | #include <linux/log2.h> |
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
@@ -171,22 +172,84 @@ int xhci_reset(struct xhci_hcd *xhci) | |||
171 | return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); | 172 | return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); |
172 | } | 173 | } |
173 | 174 | ||
175 | /* | ||
176 | * Free IRQs | ||
177 | * free all IRQs request | ||
178 | */ | ||
179 | static void xhci_free_irq(struct xhci_hcd *xhci) | ||
180 | { | ||
181 | int i; | ||
182 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | ||
174 | 183 | ||
175 | #if 0 | 184 | /* return if using legacy interrupt */ |
176 | /* Set up MSI-X table for entry 0 (may claim other entries later) */ | 185 | if (xhci_to_hcd(xhci)->irq >= 0) |
177 | static int xhci_setup_msix(struct xhci_hcd *xhci) | 186 | return; |
187 | |||
188 | if (xhci->msix_entries) { | ||
189 | for (i = 0; i < xhci->msix_count; i++) | ||
190 | if (xhci->msix_entries[i].vector) | ||
191 | free_irq(xhci->msix_entries[i].vector, | ||
192 | xhci_to_hcd(xhci)); | ||
193 | } else if (pdev->irq >= 0) | ||
194 | free_irq(pdev->irq, xhci_to_hcd(xhci)); | ||
195 | |||
196 | return; | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * Set up MSI | ||
201 | */ | ||
202 | static int xhci_setup_msi(struct xhci_hcd *xhci) | ||
178 | { | 203 | { |
179 | int ret; | 204 | int ret; |
205 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | ||
206 | |||
207 | ret = pci_enable_msi(pdev); | ||
208 | if (ret) { | ||
209 | xhci_err(xhci, "failed to allocate MSI entry\n"); | ||
210 | return ret; | ||
211 | } | ||
212 | |||
213 | ret = request_irq(pdev->irq, (irq_handler_t)xhci_msi_irq, | ||
214 | 0, "xhci_hcd", xhci_to_hcd(xhci)); | ||
215 | if (ret) { | ||
216 | xhci_err(xhci, "disable MSI interrupt\n"); | ||
217 | pci_disable_msi(pdev); | ||
218 | } | ||
219 | |||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * Set up MSI-X | ||
225 | */ | ||
226 | static int xhci_setup_msix(struct xhci_hcd *xhci) | ||
227 | { | ||
228 | int i, ret = 0; | ||
180 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | 229 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); |
181 | 230 | ||
182 | xhci->msix_count = 0; | 231 | /* |
183 | /* XXX: did I do this right? ixgbe does kcalloc for more than one */ | 232 | * calculate number of msi-x vectors supported. |
184 | xhci->msix_entries = kmalloc(sizeof(struct msix_entry), GFP_KERNEL); | 233 | * - HCS_MAX_INTRS: the max number of interrupts the host can handle, |
234 | * with max number of interrupters based on the xhci HCSPARAMS1. | ||
235 | * - num_online_cpus: maximum msi-x vectors per CPUs core. | ||
236 | * Add additional 1 vector to ensure always available interrupt. | ||
237 | */ | ||
238 | xhci->msix_count = min(num_online_cpus() + 1, | ||
239 | HCS_MAX_INTRS(xhci->hcs_params1)); | ||
240 | |||
241 | xhci->msix_entries = | ||
242 | kmalloc((sizeof(struct msix_entry))*xhci->msix_count, | ||
243 | GFP_KERNEL); | ||
185 | if (!xhci->msix_entries) { | 244 | if (!xhci->msix_entries) { |
186 | xhci_err(xhci, "Failed to allocate MSI-X entries\n"); | 245 | xhci_err(xhci, "Failed to allocate MSI-X entries\n"); |
187 | return -ENOMEM; | 246 | return -ENOMEM; |
188 | } | 247 | } |
189 | xhci->msix_entries[0].entry = 0; | 248 | |
249 | for (i = 0; i < xhci->msix_count; i++) { | ||
250 | xhci->msix_entries[i].entry = i; | ||
251 | xhci->msix_entries[i].vector = 0; | ||
252 | } | ||
190 | 253 | ||
191 | ret = pci_enable_msix(pdev, xhci->msix_entries, xhci->msix_count); | 254 | ret = pci_enable_msix(pdev, xhci->msix_entries, xhci->msix_count); |
192 | if (ret) { | 255 | if (ret) { |
@@ -194,20 +257,19 @@ static int xhci_setup_msix(struct xhci_hcd *xhci) | |||
194 | goto free_entries; | 257 | goto free_entries; |
195 | } | 258 | } |
196 | 259 | ||
197 | /* | 260 | for (i = 0; i < xhci->msix_count; i++) { |
198 | * Pass the xhci pointer value as the request_irq "cookie". | 261 | ret = request_irq(xhci->msix_entries[i].vector, |
199 | * If more irqs are added, this will need to be unique for each one. | 262 | (irq_handler_t)xhci_msi_irq, |
200 | */ | 263 | 0, "xhci_hcd", xhci_to_hcd(xhci)); |
201 | ret = request_irq(xhci->msix_entries[0].vector, &xhci_irq, 0, | 264 | if (ret) |
202 | "xHCI", xhci_to_hcd(xhci)); | 265 | goto disable_msix; |
203 | if (ret) { | ||
204 | xhci_err(xhci, "Failed to allocate MSI-X interrupt\n"); | ||
205 | goto disable_msix; | ||
206 | } | 266 | } |
207 | xhci_dbg(xhci, "Finished setting up MSI-X\n"); | 267 | |
208 | return 0; | 268 | return ret; |
209 | 269 | ||
210 | disable_msix: | 270 | disable_msix: |
271 | xhci_err(xhci, "disable MSI-X interrupt\n"); | ||
272 | xhci_free_irq(xhci); | ||
211 | pci_disable_msix(pdev); | 273 | pci_disable_msix(pdev); |
212 | free_entries: | 274 | free_entries: |
213 | kfree(xhci->msix_entries); | 275 | kfree(xhci->msix_entries); |
@@ -215,21 +277,23 @@ free_entries: | |||
215 | return ret; | 277 | return ret; |
216 | } | 278 | } |
217 | 279 | ||
218 | /* XXX: code duplication; can xhci_setup_msix call this? */ | ||
219 | /* Free any IRQs and disable MSI-X */ | 280 | /* Free any IRQs and disable MSI-X */ |
220 | static void xhci_cleanup_msix(struct xhci_hcd *xhci) | 281 | static void xhci_cleanup_msix(struct xhci_hcd *xhci) |
221 | { | 282 | { |
222 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | 283 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); |
223 | if (!xhci->msix_entries) | ||
224 | return; | ||
225 | 284 | ||
226 | free_irq(xhci->msix_entries[0].vector, xhci); | 285 | xhci_free_irq(xhci); |
227 | pci_disable_msix(pdev); | 286 | |
228 | kfree(xhci->msix_entries); | 287 | if (xhci->msix_entries) { |
229 | xhci->msix_entries = NULL; | 288 | pci_disable_msix(pdev); |
230 | xhci_dbg(xhci, "Finished cleaning up MSI-X\n"); | 289 | kfree(xhci->msix_entries); |
290 | xhci->msix_entries = NULL; | ||
291 | } else { | ||
292 | pci_disable_msi(pdev); | ||
293 | } | ||
294 | |||
295 | return; | ||
231 | } | 296 | } |
232 | #endif | ||
233 | 297 | ||
234 | /* | 298 | /* |
235 | * Initialize memory for HCD and xHC (one-time init). | 299 | * Initialize memory for HCD and xHC (one-time init). |
@@ -257,100 +321,8 @@ int xhci_init(struct usb_hcd *hcd) | |||
257 | return retval; | 321 | return retval; |
258 | } | 322 | } |
259 | 323 | ||
260 | /* | ||
261 | * Called in interrupt context when there might be work | ||
262 | * queued on the event ring | ||
263 | * | ||
264 | * xhci->lock must be held by caller. | ||
265 | */ | ||
266 | static void xhci_work(struct xhci_hcd *xhci) | ||
267 | { | ||
268 | u32 temp; | ||
269 | u64 temp_64; | ||
270 | |||
271 | /* | ||
272 | * Clear the op reg interrupt status first, | ||
273 | * so we can receive interrupts from other MSI-X interrupters. | ||
274 | * Write 1 to clear the interrupt status. | ||
275 | */ | ||
276 | temp = xhci_readl(xhci, &xhci->op_regs->status); | ||
277 | temp |= STS_EINT; | ||
278 | xhci_writel(xhci, temp, &xhci->op_regs->status); | ||
279 | /* FIXME when MSI-X is supported and there are multiple vectors */ | ||
280 | /* Clear the MSI-X event interrupt status */ | ||
281 | |||
282 | /* Acknowledge the interrupt */ | ||
283 | temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); | ||
284 | temp |= 0x3; | ||
285 | xhci_writel(xhci, temp, &xhci->ir_set->irq_pending); | ||
286 | /* Flush posted writes */ | ||
287 | xhci_readl(xhci, &xhci->ir_set->irq_pending); | ||
288 | |||
289 | if (xhci->xhc_state & XHCI_STATE_DYING) | ||
290 | xhci_dbg(xhci, "xHCI dying, ignoring interrupt. " | ||
291 | "Shouldn't IRQs be disabled?\n"); | ||
292 | else | ||
293 | /* FIXME this should be a delayed service routine | ||
294 | * that clears the EHB. | ||
295 | */ | ||
296 | xhci_handle_event(xhci); | ||
297 | |||
298 | /* Clear the event handler busy flag (RW1C); the event ring should be empty. */ | ||
299 | temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); | ||
300 | xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); | ||
301 | /* Flush posted writes -- FIXME is this necessary? */ | ||
302 | xhci_readl(xhci, &xhci->ir_set->irq_pending); | ||
303 | } | ||
304 | |||
305 | /*-------------------------------------------------------------------------*/ | 324 | /*-------------------------------------------------------------------------*/ |
306 | 325 | ||
307 | /* | ||
308 | * xHCI spec says we can get an interrupt, and if the HC has an error condition, | ||
309 | * we might get bad data out of the event ring. Section 4.10.2.7 has a list of | ||
310 | * indicators of an event TRB error, but we check the status *first* to be safe. | ||
311 | */ | ||
312 | irqreturn_t xhci_irq(struct usb_hcd *hcd) | ||
313 | { | ||
314 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
315 | u32 temp, temp2; | ||
316 | union xhci_trb *trb; | ||
317 | |||
318 | spin_lock(&xhci->lock); | ||
319 | trb = xhci->event_ring->dequeue; | ||
320 | /* Check if the xHC generated the interrupt, or the irq is shared */ | ||
321 | temp = xhci_readl(xhci, &xhci->op_regs->status); | ||
322 | temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending); | ||
323 | if (temp == 0xffffffff && temp2 == 0xffffffff) | ||
324 | goto hw_died; | ||
325 | |||
326 | if (!(temp & STS_EINT) && !ER_IRQ_PENDING(temp2)) { | ||
327 | spin_unlock(&xhci->lock); | ||
328 | return IRQ_NONE; | ||
329 | } | ||
330 | xhci_dbg(xhci, "op reg status = %08x\n", temp); | ||
331 | xhci_dbg(xhci, "ir set irq_pending = %08x\n", temp2); | ||
332 | xhci_dbg(xhci, "Event ring dequeue ptr:\n"); | ||
333 | xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n", | ||
334 | (unsigned long long)xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb), | ||
335 | lower_32_bits(trb->link.segment_ptr), | ||
336 | upper_32_bits(trb->link.segment_ptr), | ||
337 | (unsigned int) trb->link.intr_target, | ||
338 | (unsigned int) trb->link.control); | ||
339 | |||
340 | if (temp & STS_FATAL) { | ||
341 | xhci_warn(xhci, "WARNING: Host System Error\n"); | ||
342 | xhci_halt(xhci); | ||
343 | hw_died: | ||
344 | xhci_to_hcd(xhci)->state = HC_STATE_HALT; | ||
345 | spin_unlock(&xhci->lock); | ||
346 | return -ESHUTDOWN; | ||
347 | } | ||
348 | |||
349 | xhci_work(xhci); | ||
350 | spin_unlock(&xhci->lock); | ||
351 | |||
352 | return IRQ_HANDLED; | ||
353 | } | ||
354 | 326 | ||
355 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING | 327 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING |
356 | void xhci_event_ring_work(unsigned long arg) | 328 | void xhci_event_ring_work(unsigned long arg) |
@@ -423,21 +395,36 @@ int xhci_run(struct usb_hcd *hcd) | |||
423 | { | 395 | { |
424 | u32 temp; | 396 | u32 temp; |
425 | u64 temp_64; | 397 | u64 temp_64; |
398 | u32 ret; | ||
426 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 399 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
400 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | ||
427 | void (*doorbell)(struct xhci_hcd *) = NULL; | 401 | void (*doorbell)(struct xhci_hcd *) = NULL; |
428 | 402 | ||
429 | hcd->uses_new_polling = 1; | 403 | hcd->uses_new_polling = 1; |
430 | hcd->poll_rh = 0; | ||
431 | 404 | ||
432 | xhci_dbg(xhci, "xhci_run\n"); | 405 | xhci_dbg(xhci, "xhci_run\n"); |
433 | #if 0 /* FIXME: MSI not setup yet */ | 406 | /* unregister the legacy interrupt */ |
434 | /* Do this at the very last minute */ | 407 | if (hcd->irq) |
408 | free_irq(hcd->irq, hcd); | ||
409 | hcd->irq = -1; | ||
410 | |||
435 | ret = xhci_setup_msix(xhci); | 411 | ret = xhci_setup_msix(xhci); |
436 | if (!ret) | 412 | if (ret) |
437 | return ret; | 413 | /* fall back to msi*/ |
414 | ret = xhci_setup_msi(xhci); | ||
415 | |||
416 | if (ret) { | ||
417 | /* fall back to legacy interrupt*/ | ||
418 | ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, | ||
419 | hcd->irq_descr, hcd); | ||
420 | if (ret) { | ||
421 | xhci_err(xhci, "request interrupt %d failed\n", | ||
422 | pdev->irq); | ||
423 | return ret; | ||
424 | } | ||
425 | hcd->irq = pdev->irq; | ||
426 | } | ||
438 | 427 | ||
439 | return -ENOSYS; | ||
440 | #endif | ||
441 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING | 428 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING |
442 | init_timer(&xhci->event_ring_timer); | 429 | init_timer(&xhci->event_ring_timer); |
443 | xhci->event_ring_timer.data = (unsigned long) xhci; | 430 | xhci->event_ring_timer.data = (unsigned long) xhci; |
@@ -495,7 +482,6 @@ int xhci_run(struct usb_hcd *hcd) | |||
495 | return -ENODEV; | 482 | return -ENODEV; |
496 | } | 483 | } |
497 | 484 | ||
498 | xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp); | ||
499 | if (doorbell) | 485 | if (doorbell) |
500 | (*doorbell)(xhci); | 486 | (*doorbell)(xhci); |
501 | if (xhci->quirks & XHCI_NEC_HOST) | 487 | if (xhci->quirks & XHCI_NEC_HOST) |
@@ -522,11 +508,9 @@ void xhci_stop(struct usb_hcd *hcd) | |||
522 | spin_lock_irq(&xhci->lock); | 508 | spin_lock_irq(&xhci->lock); |
523 | xhci_halt(xhci); | 509 | xhci_halt(xhci); |
524 | xhci_reset(xhci); | 510 | xhci_reset(xhci); |
511 | xhci_cleanup_msix(xhci); | ||
525 | spin_unlock_irq(&xhci->lock); | 512 | spin_unlock_irq(&xhci->lock); |
526 | 513 | ||
527 | #if 0 /* No MSI yet */ | ||
528 | xhci_cleanup_msix(xhci); | ||
529 | #endif | ||
530 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING | 514 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING |
531 | /* Tell the event ring poll function not to reschedule */ | 515 | /* Tell the event ring poll function not to reschedule */ |
532 | xhci->zombie = 1; | 516 | xhci->zombie = 1; |
@@ -560,11 +544,8 @@ void xhci_shutdown(struct usb_hcd *hcd) | |||
560 | 544 | ||
561 | spin_lock_irq(&xhci->lock); | 545 | spin_lock_irq(&xhci->lock); |
562 | xhci_halt(xhci); | 546 | xhci_halt(xhci); |
563 | spin_unlock_irq(&xhci->lock); | ||
564 | |||
565 | #if 0 | ||
566 | xhci_cleanup_msix(xhci); | 547 | xhci_cleanup_msix(xhci); |
567 | #endif | 548 | spin_unlock_irq(&xhci->lock); |
568 | 549 | ||
569 | xhci_dbg(xhci, "xhci_shutdown completed - status = %x\n", | 550 | xhci_dbg(xhci, "xhci_shutdown completed - status = %x\n", |
570 | xhci_readl(xhci, &xhci->op_regs->status)); | 551 | xhci_readl(xhci, &xhci->op_regs->status)); |
@@ -720,7 +701,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) | |||
720 | unsigned long flags; | 701 | unsigned long flags; |
721 | int ret = 0; | 702 | int ret = 0; |
722 | unsigned int slot_id, ep_index; | 703 | unsigned int slot_id, ep_index; |
723 | 704 | struct urb_priv *urb_priv; | |
705 | int size, i; | ||
724 | 706 | ||
725 | if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0) | 707 | if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0) |
726 | return -EINVAL; | 708 | return -EINVAL; |
@@ -734,12 +716,36 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) | |||
734 | ret = -EINVAL; | 716 | ret = -EINVAL; |
735 | goto exit; | 717 | goto exit; |
736 | } | 718 | } |
737 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | 719 | if (!HCD_HW_ACCESSIBLE(hcd)) { |
738 | if (!in_interrupt()) | 720 | if (!in_interrupt()) |
739 | xhci_dbg(xhci, "urb submitted during PCI suspend\n"); | 721 | xhci_dbg(xhci, "urb submitted during PCI suspend\n"); |
740 | ret = -ESHUTDOWN; | 722 | ret = -ESHUTDOWN; |
741 | goto exit; | 723 | goto exit; |
742 | } | 724 | } |
725 | |||
726 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) | ||
727 | size = urb->number_of_packets; | ||
728 | else | ||
729 | size = 1; | ||
730 | |||
731 | urb_priv = kzalloc(sizeof(struct urb_priv) + | ||
732 | size * sizeof(struct xhci_td *), mem_flags); | ||
733 | if (!urb_priv) | ||
734 | return -ENOMEM; | ||
735 | |||
736 | for (i = 0; i < size; i++) { | ||
737 | urb_priv->td[i] = kzalloc(sizeof(struct xhci_td), mem_flags); | ||
738 | if (!urb_priv->td[i]) { | ||
739 | urb_priv->length = i; | ||
740 | xhci_urb_free_priv(xhci, urb_priv); | ||
741 | return -ENOMEM; | ||
742 | } | ||
743 | } | ||
744 | |||
745 | urb_priv->length = size; | ||
746 | urb_priv->td_cnt = 0; | ||
747 | urb->hcpriv = urb_priv; | ||
748 | |||
743 | if (usb_endpoint_xfer_control(&urb->ep->desc)) { | 749 | if (usb_endpoint_xfer_control(&urb->ep->desc)) { |
744 | /* Check to see if the max packet size for the default control | 750 | /* Check to see if the max packet size for the default control |
745 | * endpoint changed during FS device enumeration | 751 | * endpoint changed during FS device enumeration |
@@ -788,11 +794,18 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) | |||
788 | slot_id, ep_index); | 794 | slot_id, ep_index); |
789 | spin_unlock_irqrestore(&xhci->lock, flags); | 795 | spin_unlock_irqrestore(&xhci->lock, flags); |
790 | } else { | 796 | } else { |
791 | ret = -EINVAL; | 797 | spin_lock_irqsave(&xhci->lock, flags); |
798 | if (xhci->xhc_state & XHCI_STATE_DYING) | ||
799 | goto dying; | ||
800 | ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb, | ||
801 | slot_id, ep_index); | ||
802 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
792 | } | 803 | } |
793 | exit: | 804 | exit: |
794 | return ret; | 805 | return ret; |
795 | dying: | 806 | dying: |
807 | xhci_urb_free_priv(xhci, urb_priv); | ||
808 | urb->hcpriv = NULL; | ||
796 | xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for " | 809 | xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for " |
797 | "non-responsive xHCI host.\n", | 810 | "non-responsive xHCI host.\n", |
798 | urb->ep->desc.bEndpointAddress, urb); | 811 | urb->ep->desc.bEndpointAddress, urb); |
@@ -800,6 +813,47 @@ dying: | |||
800 | return -ESHUTDOWN; | 813 | return -ESHUTDOWN; |
801 | } | 814 | } |
802 | 815 | ||
816 | /* Get the right ring for the given URB. | ||
817 | * If the endpoint supports streams, boundary check the URB's stream ID. | ||
818 | * If the endpoint doesn't support streams, return the singular endpoint ring. | ||
819 | */ | ||
820 | static struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, | ||
821 | struct urb *urb) | ||
822 | { | ||
823 | unsigned int slot_id; | ||
824 | unsigned int ep_index; | ||
825 | unsigned int stream_id; | ||
826 | struct xhci_virt_ep *ep; | ||
827 | |||
828 | slot_id = urb->dev->slot_id; | ||
829 | ep_index = xhci_get_endpoint_index(&urb->ep->desc); | ||
830 | stream_id = urb->stream_id; | ||
831 | ep = &xhci->devs[slot_id]->eps[ep_index]; | ||
832 | /* Common case: no streams */ | ||
833 | if (!(ep->ep_state & EP_HAS_STREAMS)) | ||
834 | return ep->ring; | ||
835 | |||
836 | if (stream_id == 0) { | ||
837 | xhci_warn(xhci, | ||
838 | "WARN: Slot ID %u, ep index %u has streams, " | ||
839 | "but URB has no stream ID.\n", | ||
840 | slot_id, ep_index); | ||
841 | return NULL; | ||
842 | } | ||
843 | |||
844 | if (stream_id < ep->stream_info->num_streams) | ||
845 | return ep->stream_info->stream_rings[stream_id]; | ||
846 | |||
847 | xhci_warn(xhci, | ||
848 | "WARN: Slot ID %u, ep index %u has " | ||
849 | "stream IDs 1 to %u allocated, " | ||
850 | "but stream ID %u is requested.\n", | ||
851 | slot_id, ep_index, | ||
852 | ep->stream_info->num_streams - 1, | ||
853 | stream_id); | ||
854 | return NULL; | ||
855 | } | ||
856 | |||
803 | /* | 857 | /* |
804 | * Remove the URB's TD from the endpoint ring. This may cause the HC to stop | 858 | * Remove the URB's TD from the endpoint ring. This may cause the HC to stop |
805 | * USB transfers, potentially stopping in the middle of a TRB buffer. The HC | 859 | * USB transfers, potentially stopping in the middle of a TRB buffer. The HC |
@@ -834,9 +888,10 @@ dying: | |||
834 | int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | 888 | int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) |
835 | { | 889 | { |
836 | unsigned long flags; | 890 | unsigned long flags; |
837 | int ret; | 891 | int ret, i; |
838 | u32 temp; | 892 | u32 temp; |
839 | struct xhci_hcd *xhci; | 893 | struct xhci_hcd *xhci; |
894 | struct urb_priv *urb_priv; | ||
840 | struct xhci_td *td; | 895 | struct xhci_td *td; |
841 | unsigned int ep_index; | 896 | unsigned int ep_index; |
842 | struct xhci_ring *ep_ring; | 897 | struct xhci_ring *ep_ring; |
@@ -851,12 +906,12 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
851 | temp = xhci_readl(xhci, &xhci->op_regs->status); | 906 | temp = xhci_readl(xhci, &xhci->op_regs->status); |
852 | if (temp == 0xffffffff) { | 907 | if (temp == 0xffffffff) { |
853 | xhci_dbg(xhci, "HW died, freeing TD.\n"); | 908 | xhci_dbg(xhci, "HW died, freeing TD.\n"); |
854 | td = (struct xhci_td *) urb->hcpriv; | 909 | urb_priv = urb->hcpriv; |
855 | 910 | ||
856 | usb_hcd_unlink_urb_from_ep(hcd, urb); | 911 | usb_hcd_unlink_urb_from_ep(hcd, urb); |
857 | spin_unlock_irqrestore(&xhci->lock, flags); | 912 | spin_unlock_irqrestore(&xhci->lock, flags); |
858 | usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, -ESHUTDOWN); | 913 | usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, -ESHUTDOWN); |
859 | kfree(td); | 914 | xhci_urb_free_priv(xhci, urb_priv); |
860 | return ret; | 915 | return ret; |
861 | } | 916 | } |
862 | if (xhci->xhc_state & XHCI_STATE_DYING) { | 917 | if (xhci->xhc_state & XHCI_STATE_DYING) { |
@@ -884,9 +939,14 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
884 | 939 | ||
885 | xhci_dbg(xhci, "Endpoint ring:\n"); | 940 | xhci_dbg(xhci, "Endpoint ring:\n"); |
886 | xhci_debug_ring(xhci, ep_ring); | 941 | xhci_debug_ring(xhci, ep_ring); |
887 | td = (struct xhci_td *) urb->hcpriv; | ||
888 | 942 | ||
889 | list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list); | 943 | urb_priv = urb->hcpriv; |
944 | |||
945 | for (i = urb_priv->td_cnt; i < urb_priv->length; i++) { | ||
946 | td = urb_priv->td[i]; | ||
947 | list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list); | ||
948 | } | ||
949 | |||
890 | /* Queue a stop endpoint command, but only if this is | 950 | /* Queue a stop endpoint command, but only if this is |
891 | * the first cancellation to be handled. | 951 | * the first cancellation to be handled. |
892 | */ | 952 | */ |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 6c7e3430ec93..34a60d9f056a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -720,6 +720,14 @@ struct xhci_virt_ep { | |||
720 | struct timer_list stop_cmd_timer; | 720 | struct timer_list stop_cmd_timer; |
721 | int stop_cmds_pending; | 721 | int stop_cmds_pending; |
722 | struct xhci_hcd *xhci; | 722 | struct xhci_hcd *xhci; |
723 | /* | ||
724 | * Sometimes the xHC can not process isochronous endpoint ring quickly | ||
725 | * enough, and it will miss some isoc tds on the ring and generate | ||
726 | * a Missed Service Error Event. | ||
727 | * Set skip flag when receive a Missed Service Error Event and | ||
728 | * process the missed tds on the endpoint ring. | ||
729 | */ | ||
730 | bool skip; | ||
723 | }; | 731 | }; |
724 | 732 | ||
725 | struct xhci_virt_device { | 733 | struct xhci_virt_device { |
@@ -911,6 +919,9 @@ struct xhci_event_cmd { | |||
911 | /* Control transfer TRB specific fields */ | 919 | /* Control transfer TRB specific fields */ |
912 | #define TRB_DIR_IN (1<<16) | 920 | #define TRB_DIR_IN (1<<16) |
913 | 921 | ||
922 | /* Isochronous TRB specific fields */ | ||
923 | #define TRB_SIA (1<<31) | ||
924 | |||
914 | struct xhci_generic_trb { | 925 | struct xhci_generic_trb { |
915 | u32 field[4]; | 926 | u32 field[4]; |
916 | }; | 927 | }; |
@@ -1082,6 +1093,12 @@ struct xhci_scratchpad { | |||
1082 | dma_addr_t *sp_dma_buffers; | 1093 | dma_addr_t *sp_dma_buffers; |
1083 | }; | 1094 | }; |
1084 | 1095 | ||
1096 | struct urb_priv { | ||
1097 | int length; | ||
1098 | int td_cnt; | ||
1099 | struct xhci_td *td[0]; | ||
1100 | }; | ||
1101 | |||
1085 | /* | 1102 | /* |
1086 | * Each segment table entry is 4*32bits long. 1K seems like an ok size: | 1103 | * Each segment table entry is 4*32bits long. 1K seems like an ok size: |
1087 | * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, | 1104 | * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, |
@@ -1130,7 +1147,7 @@ struct xhci_hcd { | |||
1130 | int page_size; | 1147 | int page_size; |
1131 | /* Valid values are 12 to 20, inclusive */ | 1148 | /* Valid values are 12 to 20, inclusive */ |
1132 | int page_shift; | 1149 | int page_shift; |
1133 | /* only one MSI vector for now, but might need more later */ | 1150 | /* msi-x vectors */ |
1134 | int msix_count; | 1151 | int msix_count; |
1135 | struct msix_entry *msix_entries; | 1152 | struct msix_entry *msix_entries; |
1136 | /* data structures */ | 1153 | /* data structures */ |
@@ -1327,11 +1344,6 @@ void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci, | |||
1327 | struct xhci_ring *xhci_dma_to_transfer_ring( | 1344 | struct xhci_ring *xhci_dma_to_transfer_ring( |
1328 | struct xhci_virt_ep *ep, | 1345 | struct xhci_virt_ep *ep, |
1329 | u64 address); | 1346 | u64 address); |
1330 | struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, | ||
1331 | struct urb *urb); | ||
1332 | struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, | ||
1333 | unsigned int slot_id, unsigned int ep_index, | ||
1334 | unsigned int stream_id); | ||
1335 | struct xhci_ring *xhci_stream_id_to_ring( | 1347 | struct xhci_ring *xhci_stream_id_to_ring( |
1336 | struct xhci_virt_device *dev, | 1348 | struct xhci_virt_device *dev, |
1337 | unsigned int ep_index, | 1349 | unsigned int ep_index, |
@@ -1339,6 +1351,7 @@ struct xhci_ring *xhci_stream_id_to_ring( | |||
1339 | struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, | 1351 | struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, |
1340 | bool allocate_in_ctx, bool allocate_completion, | 1352 | bool allocate_in_ctx, bool allocate_completion, |
1341 | gfp_t mem_flags); | 1353 | gfp_t mem_flags); |
1354 | void xhci_urb_free_priv(struct xhci_hcd *xhci, struct urb_priv *urb_priv); | ||
1342 | void xhci_free_command(struct xhci_hcd *xhci, | 1355 | void xhci_free_command(struct xhci_hcd *xhci, |
1343 | struct xhci_command *command); | 1356 | struct xhci_command *command); |
1344 | 1357 | ||
@@ -1358,6 +1371,7 @@ void xhci_stop(struct usb_hcd *hcd); | |||
1358 | void xhci_shutdown(struct usb_hcd *hcd); | 1371 | void xhci_shutdown(struct usb_hcd *hcd); |
1359 | int xhci_get_frame(struct usb_hcd *hcd); | 1372 | int xhci_get_frame(struct usb_hcd *hcd); |
1360 | irqreturn_t xhci_irq(struct usb_hcd *hcd); | 1373 | irqreturn_t xhci_irq(struct usb_hcd *hcd); |
1374 | irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd); | ||
1361 | int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); | 1375 | int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); |
1362 | void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev); | 1376 | void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev); |
1363 | int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, | 1377 | int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, |
@@ -1386,8 +1400,6 @@ struct xhci_segment *trb_in_td(struct xhci_segment *start_seg, | |||
1386 | int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code); | 1400 | int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code); |
1387 | void xhci_ring_cmd_db(struct xhci_hcd *xhci); | 1401 | void xhci_ring_cmd_db(struct xhci_hcd *xhci); |
1388 | void *xhci_setup_one_noop(struct xhci_hcd *xhci); | 1402 | void *xhci_setup_one_noop(struct xhci_hcd *xhci); |
1389 | void xhci_handle_event(struct xhci_hcd *xhci); | ||
1390 | void xhci_set_hc_event_deq(struct xhci_hcd *xhci); | ||
1391 | int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id); | 1403 | int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id); |
1392 | int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, | 1404 | int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, |
1393 | u32 slot_id); | 1405 | u32 slot_id); |
@@ -1401,6 +1413,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, | |||
1401 | int slot_id, unsigned int ep_index); | 1413 | int slot_id, unsigned int ep_index); |
1402 | int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, | 1414 | int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, |
1403 | int slot_id, unsigned int ep_index); | 1415 | int slot_id, unsigned int ep_index); |
1416 | int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, | ||
1417 | struct urb *urb, int slot_id, unsigned int ep_index); | ||
1404 | int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, | 1418 | int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, |
1405 | u32 slot_id, bool command_must_succeed); | 1419 | u32 slot_id, bool command_must_succeed); |
1406 | int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, | 1420 | int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, |
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 82e16630a78b..aecf380f6ecc 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c | |||
@@ -650,7 +650,7 @@ static int ftdi_elan_open(struct inode *inode, struct file *file) | |||
650 | 650 | ||
651 | static int ftdi_elan_release(struct inode *inode, struct file *file) | 651 | static int ftdi_elan_release(struct inode *inode, struct file *file) |
652 | { | 652 | { |
653 | struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data; | 653 | struct usb_ftdi *ftdi = file->private_data; |
654 | if (ftdi == NULL) | 654 | if (ftdi == NULL) |
655 | return -ENODEV; | 655 | return -ENODEV; |
656 | up(&ftdi->sw_lock); /* decrement the count on our device */ | 656 | up(&ftdi->sw_lock); /* decrement the count on our device */ |
@@ -673,7 +673,7 @@ static ssize_t ftdi_elan_read(struct file *file, char __user *buffer, | |||
673 | int bytes_read = 0; | 673 | int bytes_read = 0; |
674 | int retry_on_empty = 10; | 674 | int retry_on_empty = 10; |
675 | int retry_on_timeout = 5; | 675 | int retry_on_timeout = 5; |
676 | struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data; | 676 | struct usb_ftdi *ftdi = file->private_data; |
677 | if (ftdi->disconnected > 0) { | 677 | if (ftdi->disconnected > 0) { |
678 | return -ENODEV; | 678 | return -ENODEV; |
679 | } | 679 | } |
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 7dc9d3c69984..2de49c8887c5 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/smp_lock.h> | 21 | #include <linux/mutex.h> |
22 | #include <linux/poll.h> | 22 | #include <linux/poll.h> |
23 | #include <linux/usb/iowarrior.h> | 23 | #include <linux/usb/iowarrior.h> |
24 | 24 | ||
@@ -61,6 +61,7 @@ MODULE_DESCRIPTION(DRIVER_DESC); | |||
61 | MODULE_LICENSE("GPL"); | 61 | MODULE_LICENSE("GPL"); |
62 | 62 | ||
63 | /* Module parameters */ | 63 | /* Module parameters */ |
64 | static DEFINE_MUTEX(iowarrior_mutex); | ||
64 | static int debug = 0; | 65 | static int debug = 0; |
65 | module_param(debug, bool, 0644); | 66 | module_param(debug, bool, 0644); |
66 | MODULE_PARM_DESC(debug, "debug=1 enables debugging messages"); | 67 | MODULE_PARM_DESC(debug, "debug=1 enables debugging messages"); |
@@ -282,7 +283,7 @@ static ssize_t iowarrior_read(struct file *file, char __user *buffer, | |||
282 | int read_idx; | 283 | int read_idx; |
283 | int offset; | 284 | int offset; |
284 | 285 | ||
285 | dev = (struct iowarrior *)file->private_data; | 286 | dev = file->private_data; |
286 | 287 | ||
287 | /* verify that the device wasn't unplugged */ | 288 | /* verify that the device wasn't unplugged */ |
288 | if (dev == NULL || !dev->present) | 289 | if (dev == NULL || !dev->present) |
@@ -348,7 +349,7 @@ static ssize_t iowarrior_write(struct file *file, | |||
348 | char *buf = NULL; /* for IOW24 and IOW56 we need a buffer */ | 349 | char *buf = NULL; /* for IOW24 and IOW56 we need a buffer */ |
349 | struct urb *int_out_urb = NULL; | 350 | struct urb *int_out_urb = NULL; |
350 | 351 | ||
351 | dev = (struct iowarrior *)file->private_data; | 352 | dev = file->private_data; |
352 | 353 | ||
353 | mutex_lock(&dev->mutex); | 354 | mutex_lock(&dev->mutex); |
354 | /* verify that the device wasn't unplugged */ | 355 | /* verify that the device wasn't unplugged */ |
@@ -483,7 +484,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, | |||
483 | int retval; | 484 | int retval; |
484 | int io_res; /* checks for bytes read/written and copy_to/from_user results */ | 485 | int io_res; /* checks for bytes read/written and copy_to/from_user results */ |
485 | 486 | ||
486 | dev = (struct iowarrior *)file->private_data; | 487 | dev = file->private_data; |
487 | if (dev == NULL) { | 488 | if (dev == NULL) { |
488 | return -ENODEV; | 489 | return -ENODEV; |
489 | } | 490 | } |
@@ -493,7 +494,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, | |||
493 | return -ENOMEM; | 494 | return -ENOMEM; |
494 | 495 | ||
495 | /* lock this object */ | 496 | /* lock this object */ |
496 | lock_kernel(); | 497 | mutex_lock(&iowarrior_mutex); |
497 | mutex_lock(&dev->mutex); | 498 | mutex_lock(&dev->mutex); |
498 | 499 | ||
499 | /* verify that the device wasn't unplugged */ | 500 | /* verify that the device wasn't unplugged */ |
@@ -585,7 +586,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, | |||
585 | error_out: | 586 | error_out: |
586 | /* unlock the device */ | 587 | /* unlock the device */ |
587 | mutex_unlock(&dev->mutex); | 588 | mutex_unlock(&dev->mutex); |
588 | unlock_kernel(); | 589 | mutex_unlock(&iowarrior_mutex); |
589 | kfree(buffer); | 590 | kfree(buffer); |
590 | return retval; | 591 | return retval; |
591 | } | 592 | } |
@@ -602,12 +603,12 @@ static int iowarrior_open(struct inode *inode, struct file *file) | |||
602 | 603 | ||
603 | dbg("%s", __func__); | 604 | dbg("%s", __func__); |
604 | 605 | ||
605 | lock_kernel(); | 606 | mutex_lock(&iowarrior_mutex); |
606 | subminor = iminor(inode); | 607 | subminor = iminor(inode); |
607 | 608 | ||
608 | interface = usb_find_interface(&iowarrior_driver, subminor); | 609 | interface = usb_find_interface(&iowarrior_driver, subminor); |
609 | if (!interface) { | 610 | if (!interface) { |
610 | unlock_kernel(); | 611 | mutex_unlock(&iowarrior_mutex); |
611 | err("%s - error, can't find device for minor %d", __func__, | 612 | err("%s - error, can't find device for minor %d", __func__, |
612 | subminor); | 613 | subminor); |
613 | return -ENODEV; | 614 | return -ENODEV; |
@@ -617,7 +618,7 @@ static int iowarrior_open(struct inode *inode, struct file *file) | |||
617 | dev = usb_get_intfdata(interface); | 618 | dev = usb_get_intfdata(interface); |
618 | if (!dev) { | 619 | if (!dev) { |
619 | mutex_unlock(&iowarrior_open_disc_lock); | 620 | mutex_unlock(&iowarrior_open_disc_lock); |
620 | unlock_kernel(); | 621 | mutex_unlock(&iowarrior_mutex); |
621 | return -ENODEV; | 622 | return -ENODEV; |
622 | } | 623 | } |
623 | 624 | ||
@@ -644,7 +645,7 @@ static int iowarrior_open(struct inode *inode, struct file *file) | |||
644 | 645 | ||
645 | out: | 646 | out: |
646 | mutex_unlock(&dev->mutex); | 647 | mutex_unlock(&dev->mutex); |
647 | unlock_kernel(); | 648 | mutex_unlock(&iowarrior_mutex); |
648 | return retval; | 649 | return retval; |
649 | } | 650 | } |
650 | 651 | ||
@@ -656,7 +657,7 @@ static int iowarrior_release(struct inode *inode, struct file *file) | |||
656 | struct iowarrior *dev; | 657 | struct iowarrior *dev; |
657 | int retval = 0; | 658 | int retval = 0; |
658 | 659 | ||
659 | dev = (struct iowarrior *)file->private_data; | 660 | dev = file->private_data; |
660 | if (dev == NULL) { | 661 | if (dev == NULL) { |
661 | return -ENODEV; | 662 | return -ENODEV; |
662 | } | 663 | } |
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 8547bf9e3175..6482c6e2e6bd 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c | |||
@@ -448,7 +448,7 @@ static int tower_release (struct inode *inode, struct file *file) | |||
448 | 448 | ||
449 | dbg(2, "%s: enter", __func__); | 449 | dbg(2, "%s: enter", __func__); |
450 | 450 | ||
451 | dev = (struct lego_usb_tower *)file->private_data; | 451 | dev = file->private_data; |
452 | 452 | ||
453 | if (dev == NULL) { | 453 | if (dev == NULL) { |
454 | dbg(1, "%s: object is NULL", __func__); | 454 | dbg(1, "%s: object is NULL", __func__); |
@@ -597,7 +597,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, | |||
597 | 597 | ||
598 | dbg(2, "%s: enter, count = %Zd", __func__, count); | 598 | dbg(2, "%s: enter, count = %Zd", __func__, count); |
599 | 599 | ||
600 | dev = (struct lego_usb_tower *)file->private_data; | 600 | dev = file->private_data; |
601 | 601 | ||
602 | /* lock this object */ | 602 | /* lock this object */ |
603 | if (mutex_lock_interruptible(&dev->lock)) { | 603 | if (mutex_lock_interruptible(&dev->lock)) { |
@@ -686,7 +686,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t | |||
686 | 686 | ||
687 | dbg(2, "%s: enter, count = %Zd", __func__, count); | 687 | dbg(2, "%s: enter, count = %Zd", __func__, count); |
688 | 688 | ||
689 | dev = (struct lego_usb_tower *)file->private_data; | 689 | dev = file->private_data; |
690 | 690 | ||
691 | /* lock this object */ | 691 | /* lock this object */ |
692 | if (mutex_lock_interruptible(&dev->lock)) { | 692 | if (mutex_lock_interruptible(&dev->lock)) { |
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index a85771b1563d..cc13ae61712a 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
33 | #include <linux/signal.h> | 33 | #include <linux/signal.h> |
34 | #include <linux/sched.h> | 34 | #include <linux/sched.h> |
35 | #include <linux/smp_lock.h> | 35 | #include <linux/mutex.h> |
36 | #include <linux/errno.h> | 36 | #include <linux/errno.h> |
37 | #include <linux/random.h> | 37 | #include <linux/random.h> |
38 | #include <linux/poll.h> | 38 | #include <linux/poll.h> |
@@ -72,6 +72,7 @@ struct rio_usb_data { | |||
72 | struct mutex lock; /* general race avoidance */ | 72 | struct mutex lock; /* general race avoidance */ |
73 | }; | 73 | }; |
74 | 74 | ||
75 | static DEFINE_MUTEX(rio500_mutex); | ||
75 | static struct rio_usb_data rio_instance; | 76 | static struct rio_usb_data rio_instance; |
76 | 77 | ||
77 | static int open_rio(struct inode *inode, struct file *file) | 78 | static int open_rio(struct inode *inode, struct file *file) |
@@ -79,12 +80,12 @@ static int open_rio(struct inode *inode, struct file *file) | |||
79 | struct rio_usb_data *rio = &rio_instance; | 80 | struct rio_usb_data *rio = &rio_instance; |
80 | 81 | ||
81 | /* against disconnect() */ | 82 | /* against disconnect() */ |
82 | lock_kernel(); | 83 | mutex_lock(&rio500_mutex); |
83 | mutex_lock(&(rio->lock)); | 84 | mutex_lock(&(rio->lock)); |
84 | 85 | ||
85 | if (rio->isopen || !rio->present) { | 86 | if (rio->isopen || !rio->present) { |
86 | mutex_unlock(&(rio->lock)); | 87 | mutex_unlock(&(rio->lock)); |
87 | unlock_kernel(); | 88 | mutex_unlock(&rio500_mutex); |
88 | return -EBUSY; | 89 | return -EBUSY; |
89 | } | 90 | } |
90 | rio->isopen = 1; | 91 | rio->isopen = 1; |
@@ -94,7 +95,7 @@ static int open_rio(struct inode *inode, struct file *file) | |||
94 | mutex_unlock(&(rio->lock)); | 95 | mutex_unlock(&(rio->lock)); |
95 | 96 | ||
96 | dev_info(&rio->rio_dev->dev, "Rio opened.\n"); | 97 | dev_info(&rio->rio_dev->dev, "Rio opened.\n"); |
97 | unlock_kernel(); | 98 | mutex_unlock(&rio500_mutex); |
98 | 99 | ||
99 | return 0; | 100 | return 0; |
100 | } | 101 | } |
@@ -491,7 +492,7 @@ static void disconnect_rio(struct usb_interface *intf) | |||
491 | struct rio_usb_data *rio = usb_get_intfdata (intf); | 492 | struct rio_usb_data *rio = usb_get_intfdata (intf); |
492 | 493 | ||
493 | usb_set_intfdata (intf, NULL); | 494 | usb_set_intfdata (intf, NULL); |
494 | lock_kernel(); | 495 | mutex_lock(&rio500_mutex); |
495 | if (rio) { | 496 | if (rio) { |
496 | usb_deregister_dev(intf, &usb_rio_class); | 497 | usb_deregister_dev(intf, &usb_rio_class); |
497 | 498 | ||
@@ -501,7 +502,7 @@ static void disconnect_rio(struct usb_interface *intf) | |||
501 | /* better let it finish - the release will do whats needed */ | 502 | /* better let it finish - the release will do whats needed */ |
502 | rio->rio_dev = NULL; | 503 | rio->rio_dev = NULL; |
503 | mutex_unlock(&(rio->lock)); | 504 | mutex_unlock(&(rio->lock)); |
504 | unlock_kernel(); | 505 | mutex_unlock(&rio500_mutex); |
505 | return; | 506 | return; |
506 | } | 507 | } |
507 | kfree(rio->ibuf); | 508 | kfree(rio->ibuf); |
@@ -512,7 +513,7 @@ static void disconnect_rio(struct usb_interface *intf) | |||
512 | rio->present = 0; | 513 | rio->present = 0; |
513 | mutex_unlock(&(rio->lock)); | 514 | mutex_unlock(&(rio->lock)); |
514 | } | 515 | } |
515 | unlock_kernel(); | 516 | mutex_unlock(&rio500_mutex); |
516 | } | 517 | } |
517 | 518 | ||
518 | static const struct usb_device_id rio_table[] = { | 519 | static const struct usb_device_id rio_table[] = { |
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index d25814c172b2..70d00e99a4b4 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c | |||
@@ -2487,7 +2487,7 @@ sisusb_release(struct inode *inode, struct file *file) | |||
2487 | { | 2487 | { |
2488 | struct sisusb_usb_data *sisusb; | 2488 | struct sisusb_usb_data *sisusb; |
2489 | 2489 | ||
2490 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) | 2490 | if (!(sisusb = file->private_data)) |
2491 | return -ENODEV; | 2491 | return -ENODEV; |
2492 | 2492 | ||
2493 | mutex_lock(&sisusb->lock); | 2493 | mutex_lock(&sisusb->lock); |
@@ -2519,7 +2519,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | |||
2519 | u16 buf16; | 2519 | u16 buf16; |
2520 | u32 buf32, address; | 2520 | u32 buf32, address; |
2521 | 2521 | ||
2522 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) | 2522 | if (!(sisusb = file->private_data)) |
2523 | return -ENODEV; | 2523 | return -ENODEV; |
2524 | 2524 | ||
2525 | mutex_lock(&sisusb->lock); | 2525 | mutex_lock(&sisusb->lock); |
@@ -2661,7 +2661,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, | |||
2661 | u16 buf16; | 2661 | u16 buf16; |
2662 | u32 buf32, address; | 2662 | u32 buf32, address; |
2663 | 2663 | ||
2664 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) | 2664 | if (!(sisusb = file->private_data)) |
2665 | return -ENODEV; | 2665 | return -ENODEV; |
2666 | 2666 | ||
2667 | mutex_lock(&sisusb->lock); | 2667 | mutex_lock(&sisusb->lock); |
@@ -2804,7 +2804,7 @@ sisusb_lseek(struct file *file, loff_t offset, int orig) | |||
2804 | struct sisusb_usb_data *sisusb; | 2804 | struct sisusb_usb_data *sisusb; |
2805 | loff_t ret; | 2805 | loff_t ret; |
2806 | 2806 | ||
2807 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) | 2807 | if (!(sisusb = file->private_data)) |
2808 | return -ENODEV; | 2808 | return -ENODEV; |
2809 | 2809 | ||
2810 | mutex_lock(&sisusb->lock); | 2810 | mutex_lock(&sisusb->lock); |
@@ -2969,7 +2969,7 @@ sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2969 | long retval = 0; | 2969 | long retval = 0; |
2970 | u32 __user *argp = (u32 __user *)arg; | 2970 | u32 __user *argp = (u32 __user *)arg; |
2971 | 2971 | ||
2972 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) | 2972 | if (!(sisusb = file->private_data)) |
2973 | return -ENODEV; | 2973 | return -ENODEV; |
2974 | 2974 | ||
2975 | mutex_lock(&sisusb->lock); | 2975 | mutex_lock(&sisusb->lock); |
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 7828c764b323..d00dde19194c 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/smp_lock.h> | ||
20 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
21 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
22 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
@@ -30,6 +29,7 @@ | |||
30 | #define IOCTL_GET_DRV_VERSION 2 | 29 | #define IOCTL_GET_DRV_VERSION 2 |
31 | 30 | ||
32 | 31 | ||
32 | static DEFINE_MUTEX(lcd_mutex); | ||
33 | static const struct usb_device_id id_table[] = { | 33 | static const struct usb_device_id id_table[] = { |
34 | { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, }, | 34 | { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, }, |
35 | { }, | 35 | { }, |
@@ -74,12 +74,12 @@ static int lcd_open(struct inode *inode, struct file *file) | |||
74 | struct usb_interface *interface; | 74 | struct usb_interface *interface; |
75 | int subminor, r; | 75 | int subminor, r; |
76 | 76 | ||
77 | lock_kernel(); | 77 | mutex_lock(&lcd_mutex); |
78 | subminor = iminor(inode); | 78 | subminor = iminor(inode); |
79 | 79 | ||
80 | interface = usb_find_interface(&lcd_driver, subminor); | 80 | interface = usb_find_interface(&lcd_driver, subminor); |
81 | if (!interface) { | 81 | if (!interface) { |
82 | unlock_kernel(); | 82 | mutex_unlock(&lcd_mutex); |
83 | err ("USBLCD: %s - error, can't find device for minor %d", | 83 | err ("USBLCD: %s - error, can't find device for minor %d", |
84 | __func__, subminor); | 84 | __func__, subminor); |
85 | return -ENODEV; | 85 | return -ENODEV; |
@@ -89,7 +89,7 @@ static int lcd_open(struct inode *inode, struct file *file) | |||
89 | dev = usb_get_intfdata(interface); | 89 | dev = usb_get_intfdata(interface); |
90 | if (!dev) { | 90 | if (!dev) { |
91 | mutex_unlock(&open_disc_mutex); | 91 | mutex_unlock(&open_disc_mutex); |
92 | unlock_kernel(); | 92 | mutex_unlock(&lcd_mutex); |
93 | return -ENODEV; | 93 | return -ENODEV; |
94 | } | 94 | } |
95 | 95 | ||
@@ -101,13 +101,13 @@ static int lcd_open(struct inode *inode, struct file *file) | |||
101 | r = usb_autopm_get_interface(interface); | 101 | r = usb_autopm_get_interface(interface); |
102 | if (r < 0) { | 102 | if (r < 0) { |
103 | kref_put(&dev->kref, lcd_delete); | 103 | kref_put(&dev->kref, lcd_delete); |
104 | unlock_kernel(); | 104 | mutex_unlock(&lcd_mutex); |
105 | return r; | 105 | return r; |
106 | } | 106 | } |
107 | 107 | ||
108 | /* save our object in the file's private structure */ | 108 | /* save our object in the file's private structure */ |
109 | file->private_data = dev; | 109 | file->private_data = dev; |
110 | unlock_kernel(); | 110 | mutex_unlock(&lcd_mutex); |
111 | 111 | ||
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
@@ -116,7 +116,7 @@ static int lcd_release(struct inode *inode, struct file *file) | |||
116 | { | 116 | { |
117 | struct usb_lcd *dev; | 117 | struct usb_lcd *dev; |
118 | 118 | ||
119 | dev = (struct usb_lcd *)file->private_data; | 119 | dev = file->private_data; |
120 | if (dev == NULL) | 120 | if (dev == NULL) |
121 | return -ENODEV; | 121 | return -ENODEV; |
122 | 122 | ||
@@ -132,7 +132,7 @@ static ssize_t lcd_read(struct file *file, char __user * buffer, size_t count, l | |||
132 | int retval = 0; | 132 | int retval = 0; |
133 | int bytes_read; | 133 | int bytes_read; |
134 | 134 | ||
135 | dev = (struct usb_lcd *)file->private_data; | 135 | dev = file->private_data; |
136 | 136 | ||
137 | /* do a blocking bulk read to get data from the device */ | 137 | /* do a blocking bulk read to get data from the device */ |
138 | retval = usb_bulk_msg(dev->udev, | 138 | retval = usb_bulk_msg(dev->udev, |
@@ -158,20 +158,20 @@ static long lcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
158 | u16 bcdDevice; | 158 | u16 bcdDevice; |
159 | char buf[30]; | 159 | char buf[30]; |
160 | 160 | ||
161 | dev = (struct usb_lcd *)file->private_data; | 161 | dev = file->private_data; |
162 | if (dev == NULL) | 162 | if (dev == NULL) |
163 | return -ENODEV; | 163 | return -ENODEV; |
164 | 164 | ||
165 | switch (cmd) { | 165 | switch (cmd) { |
166 | case IOCTL_GET_HARD_VERSION: | 166 | case IOCTL_GET_HARD_VERSION: |
167 | lock_kernel(); | 167 | mutex_lock(&lcd_mutex); |
168 | bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice); | 168 | bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice); |
169 | sprintf(buf,"%1d%1d.%1d%1d", | 169 | sprintf(buf,"%1d%1d.%1d%1d", |
170 | (bcdDevice & 0xF000)>>12, | 170 | (bcdDevice & 0xF000)>>12, |
171 | (bcdDevice & 0xF00)>>8, | 171 | (bcdDevice & 0xF00)>>8, |
172 | (bcdDevice & 0xF0)>>4, | 172 | (bcdDevice & 0xF0)>>4, |
173 | (bcdDevice & 0xF)); | 173 | (bcdDevice & 0xF)); |
174 | unlock_kernel(); | 174 | mutex_unlock(&lcd_mutex); |
175 | if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0) | 175 | if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0) |
176 | return -EFAULT; | 176 | return -EFAULT; |
177 | break; | 177 | break; |
@@ -217,7 +217,7 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz | |||
217 | struct urb *urb = NULL; | 217 | struct urb *urb = NULL; |
218 | char *buf = NULL; | 218 | char *buf = NULL; |
219 | 219 | ||
220 | dev = (struct usb_lcd *)file->private_data; | 220 | dev = file->private_data; |
221 | 221 | ||
222 | /* verify that we actually have some data to write */ | 222 | /* verify that we actually have some data to write */ |
223 | if (count == 0) | 223 | if (count == 0) |
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 16dffe99d9f1..eef370eb7a54 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -136,7 +136,7 @@ try_iso: | |||
136 | iso_out = e; | 136 | iso_out = e; |
137 | } | 137 | } |
138 | } | 138 | } |
139 | if ((in && out) || (iso_in && iso_out)) | 139 | if ((in && out) || iso_in || iso_out) |
140 | goto found; | 140 | goto found; |
141 | } | 141 | } |
142 | return -EINVAL; | 142 | return -EINVAL; |
@@ -162,6 +162,9 @@ found: | |||
162 | dev->in_iso_pipe = usb_rcvisocpipe (udev, | 162 | dev->in_iso_pipe = usb_rcvisocpipe (udev, |
163 | iso_in->desc.bEndpointAddress | 163 | iso_in->desc.bEndpointAddress |
164 | & USB_ENDPOINT_NUMBER_MASK); | 164 | & USB_ENDPOINT_NUMBER_MASK); |
165 | } | ||
166 | |||
167 | if (iso_out) { | ||
165 | dev->iso_out = &iso_out->desc; | 168 | dev->iso_out = &iso_out->desc; |
166 | dev->out_iso_pipe = usb_sndisocpipe (udev, | 169 | dev->out_iso_pipe = usb_sndisocpipe (udev, |
167 | iso_out->desc.bEndpointAddress | 170 | iso_out->desc.bEndpointAddress |
@@ -1378,7 +1381,6 @@ static void iso_callback (struct urb *urb) | |||
1378 | break; | 1381 | break; |
1379 | } | 1382 | } |
1380 | } | 1383 | } |
1381 | simple_free_urb (urb); | ||
1382 | 1384 | ||
1383 | ctx->pending--; | 1385 | ctx->pending--; |
1384 | if (ctx->pending == 0) { | 1386 | if (ctx->pending == 0) { |
@@ -1495,6 +1497,7 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, | |||
1495 | } | 1497 | } |
1496 | 1498 | ||
1497 | simple_free_urb (urbs [i]); | 1499 | simple_free_urb (urbs [i]); |
1500 | urbs[i] = NULL; | ||
1498 | context.pending--; | 1501 | context.pending--; |
1499 | context.submit_error = 1; | 1502 | context.submit_error = 1; |
1500 | break; | 1503 | break; |
@@ -1504,6 +1507,10 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, | |||
1504 | 1507 | ||
1505 | wait_for_completion (&context.done); | 1508 | wait_for_completion (&context.done); |
1506 | 1509 | ||
1510 | for (i = 0; i < param->sglen; i++) { | ||
1511 | if (urbs[i]) | ||
1512 | simple_free_urb(urbs[i]); | ||
1513 | } | ||
1507 | /* | 1514 | /* |
1508 | * Isochronous transfers are expected to fail sometimes. As an | 1515 | * Isochronous transfers are expected to fail sometimes. As an |
1509 | * arbitrary limit, we will report an error if any submissions | 1516 | * arbitrary limit, we will report an error if any submissions |
@@ -1548,6 +1555,7 @@ fail: | |||
1548 | * off just killing the userspace task and waiting for it to exit. | 1555 | * off just killing the userspace task and waiting for it to exit. |
1549 | */ | 1556 | */ |
1550 | 1557 | ||
1558 | /* No BKL needed */ | ||
1551 | static int | 1559 | static int |
1552 | usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) | 1560 | usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) |
1553 | { | 1561 | { |
@@ -2170,7 +2178,7 @@ static struct usb_driver usbtest_driver = { | |||
2170 | .name = "usbtest", | 2178 | .name = "usbtest", |
2171 | .id_table = id_table, | 2179 | .id_table = id_table, |
2172 | .probe = usbtest_probe, | 2180 | .probe = usbtest_probe, |
2173 | .ioctl = usbtest_ioctl, | 2181 | .unlocked_ioctl = usbtest_ioctl, |
2174 | .disconnect = usbtest_disconnect, | 2182 | .disconnect = usbtest_disconnect, |
2175 | .suspend = usbtest_suspend, | 2183 | .suspend = usbtest_suspend, |
2176 | .resume = usbtest_resume, | 2184 | .resume = usbtest_resume, |
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 61c76b13f0f1..44cb37b5a4dc 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c | |||
@@ -646,17 +646,14 @@ static int mon_bin_open(struct inode *inode, struct file *file) | |||
646 | size_t size; | 646 | size_t size; |
647 | int rc; | 647 | int rc; |
648 | 648 | ||
649 | lock_kernel(); | ||
650 | mutex_lock(&mon_lock); | 649 | mutex_lock(&mon_lock); |
651 | if ((mbus = mon_bus_lookup(iminor(inode))) == NULL) { | 650 | if ((mbus = mon_bus_lookup(iminor(inode))) == NULL) { |
652 | mutex_unlock(&mon_lock); | 651 | mutex_unlock(&mon_lock); |
653 | unlock_kernel(); | ||
654 | return -ENODEV; | 652 | return -ENODEV; |
655 | } | 653 | } |
656 | if (mbus != &mon_bus0 && mbus->u_bus == NULL) { | 654 | if (mbus != &mon_bus0 && mbus->u_bus == NULL) { |
657 | printk(KERN_ERR TAG ": consistency error on open\n"); | 655 | printk(KERN_ERR TAG ": consistency error on open\n"); |
658 | mutex_unlock(&mon_lock); | 656 | mutex_unlock(&mon_lock); |
659 | unlock_kernel(); | ||
660 | return -ENODEV; | 657 | return -ENODEV; |
661 | } | 658 | } |
662 | 659 | ||
@@ -689,7 +686,6 @@ static int mon_bin_open(struct inode *inode, struct file *file) | |||
689 | 686 | ||
690 | file->private_data = rp; | 687 | file->private_data = rp; |
691 | mutex_unlock(&mon_lock); | 688 | mutex_unlock(&mon_lock); |
692 | unlock_kernel(); | ||
693 | return 0; | 689 | return 0; |
694 | 690 | ||
695 | err_allocbuff: | 691 | err_allocbuff: |
@@ -698,7 +694,6 @@ err_allocvec: | |||
698 | kfree(rp); | 694 | kfree(rp); |
699 | err_alloc: | 695 | err_alloc: |
700 | mutex_unlock(&mon_lock); | 696 | mutex_unlock(&mon_lock); |
701 | unlock_kernel(); | ||
702 | return rc; | 697 | return rc; |
703 | } | 698 | } |
704 | 699 | ||
@@ -954,7 +949,7 @@ static int mon_bin_queued(struct mon_reader_bin *rp) | |||
954 | 949 | ||
955 | /* | 950 | /* |
956 | */ | 951 | */ |
957 | static int mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 952 | static long mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
958 | { | 953 | { |
959 | struct mon_reader_bin *rp = file->private_data; | 954 | struct mon_reader_bin *rp = file->private_data; |
960 | // struct mon_bus* mbus = rp->r.m_bus; | 955 | // struct mon_bus* mbus = rp->r.m_bus; |
@@ -1009,7 +1004,7 @@ static int mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
1009 | 1004 | ||
1010 | mutex_lock(&rp->fetch_lock); | 1005 | mutex_lock(&rp->fetch_lock); |
1011 | spin_lock_irqsave(&rp->b_lock, flags); | 1006 | spin_lock_irqsave(&rp->b_lock, flags); |
1012 | mon_free_buff(rp->b_vec, size/CHUNK_SIZE); | 1007 | mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE); |
1013 | kfree(rp->b_vec); | 1008 | kfree(rp->b_vec); |
1014 | rp->b_vec = vec; | 1009 | rp->b_vec = vec; |
1015 | rp->b_size = size; | 1010 | rp->b_size = size; |
@@ -1094,19 +1089,6 @@ static int mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
1094 | return ret; | 1089 | return ret; |
1095 | } | 1090 | } |
1096 | 1091 | ||
1097 | static long mon_bin_unlocked_ioctl(struct file *file, unsigned int cmd, | ||
1098 | unsigned long arg) | ||
1099 | { | ||
1100 | int ret; | ||
1101 | |||
1102 | lock_kernel(); | ||
1103 | ret = mon_bin_ioctl(file, cmd, arg); | ||
1104 | unlock_kernel(); | ||
1105 | |||
1106 | return ret; | ||
1107 | } | ||
1108 | |||
1109 | |||
1110 | #ifdef CONFIG_COMPAT | 1092 | #ifdef CONFIG_COMPAT |
1111 | static long mon_bin_compat_ioctl(struct file *file, | 1093 | static long mon_bin_compat_ioctl(struct file *file, |
1112 | unsigned int cmd, unsigned long arg) | 1094 | unsigned int cmd, unsigned long arg) |
@@ -1250,7 +1232,7 @@ static const struct file_operations mon_fops_binary = { | |||
1250 | .read = mon_bin_read, | 1232 | .read = mon_bin_read, |
1251 | /* .write = mon_text_write, */ | 1233 | /* .write = mon_text_write, */ |
1252 | .poll = mon_bin_poll, | 1234 | .poll = mon_bin_poll, |
1253 | .unlocked_ioctl = mon_bin_unlocked_ioctl, | 1235 | .unlocked_ioctl = mon_bin_ioctl, |
1254 | #ifdef CONFIG_COMPAT | 1236 | #ifdef CONFIG_COMPAT |
1255 | .compat_ioctl = mon_bin_compat_ioctl, | 1237 | .compat_ioctl = mon_bin_compat_ioctl, |
1256 | #endif | 1238 | #endif |
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 3b795c56221f..540c766c4f86 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -704,7 +704,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
704 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | 704 | #ifdef CONFIG_USB_MUSB_HDRC_HCD |
705 | if (int_usb & MUSB_INTR_CONNECT) { | 705 | if (int_usb & MUSB_INTR_CONNECT) { |
706 | struct usb_hcd *hcd = musb_to_hcd(musb); | 706 | struct usb_hcd *hcd = musb_to_hcd(musb); |
707 | void __iomem *mbase = musb->mregs; | ||
708 | 707 | ||
709 | handled = IRQ_HANDLED; | 708 | handled = IRQ_HANDLED; |
710 | musb->is_active = 1; | 709 | musb->is_active = 1; |
@@ -717,9 +716,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
717 | if (is_peripheral_active(musb)) { | 716 | if (is_peripheral_active(musb)) { |
718 | /* REVISIT HNP; just force disconnect */ | 717 | /* REVISIT HNP; just force disconnect */ |
719 | } | 718 | } |
720 | musb_writew(mbase, MUSB_INTRTXE, musb->epmask); | 719 | musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask); |
721 | musb_writew(mbase, MUSB_INTRRXE, musb->epmask & 0xfffe); | 720 | musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe); |
722 | musb_writeb(mbase, MUSB_INTRUSBE, 0xf7); | 721 | musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7); |
723 | #endif | 722 | #endif |
724 | musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED | 723 | musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED |
725 | |USB_PORT_STAT_HIGH_SPEED | 724 | |USB_PORT_STAT_HIGH_SPEED |
diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index bba76af0c0c6..c79a5e30d437 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c | |||
@@ -92,29 +92,29 @@ static const struct musb_register_map musb_regmap[] = { | |||
92 | { "LS_EOF1", 0x7E, 8 }, | 92 | { "LS_EOF1", 0x7E, 8 }, |
93 | { "SOFT_RST", 0x7F, 8 }, | 93 | { "SOFT_RST", 0x7F, 8 }, |
94 | { "DMA_CNTLch0", 0x204, 16 }, | 94 | { "DMA_CNTLch0", 0x204, 16 }, |
95 | { "DMA_ADDRch0", 0x208, 16 }, | 95 | { "DMA_ADDRch0", 0x208, 32 }, |
96 | { "DMA_COUNTch0", 0x20C, 16 }, | 96 | { "DMA_COUNTch0", 0x20C, 32 }, |
97 | { "DMA_CNTLch1", 0x214, 16 }, | 97 | { "DMA_CNTLch1", 0x214, 16 }, |
98 | { "DMA_ADDRch1", 0x218, 16 }, | 98 | { "DMA_ADDRch1", 0x218, 32 }, |
99 | { "DMA_COUNTch1", 0x21C, 16 }, | 99 | { "DMA_COUNTch1", 0x21C, 32 }, |
100 | { "DMA_CNTLch2", 0x224, 16 }, | 100 | { "DMA_CNTLch2", 0x224, 16 }, |
101 | { "DMA_ADDRch2", 0x228, 16 }, | 101 | { "DMA_ADDRch2", 0x228, 32 }, |
102 | { "DMA_COUNTch2", 0x22C, 16 }, | 102 | { "DMA_COUNTch2", 0x22C, 32 }, |
103 | { "DMA_CNTLch3", 0x234, 16 }, | 103 | { "DMA_CNTLch3", 0x234, 16 }, |
104 | { "DMA_ADDRch3", 0x238, 16 }, | 104 | { "DMA_ADDRch3", 0x238, 32 }, |
105 | { "DMA_COUNTch3", 0x23C, 16 }, | 105 | { "DMA_COUNTch3", 0x23C, 32 }, |
106 | { "DMA_CNTLch4", 0x244, 16 }, | 106 | { "DMA_CNTLch4", 0x244, 16 }, |
107 | { "DMA_ADDRch4", 0x248, 16 }, | 107 | { "DMA_ADDRch4", 0x248, 32 }, |
108 | { "DMA_COUNTch4", 0x24C, 16 }, | 108 | { "DMA_COUNTch4", 0x24C, 32 }, |
109 | { "DMA_CNTLch5", 0x254, 16 }, | 109 | { "DMA_CNTLch5", 0x254, 16 }, |
110 | { "DMA_ADDRch5", 0x258, 16 }, | 110 | { "DMA_ADDRch5", 0x258, 32 }, |
111 | { "DMA_COUNTch5", 0x25C, 16 }, | 111 | { "DMA_COUNTch5", 0x25C, 32 }, |
112 | { "DMA_CNTLch6", 0x264, 16 }, | 112 | { "DMA_CNTLch6", 0x264, 16 }, |
113 | { "DMA_ADDRch6", 0x268, 16 }, | 113 | { "DMA_ADDRch6", 0x268, 32 }, |
114 | { "DMA_COUNTch6", 0x26C, 16 }, | 114 | { "DMA_COUNTch6", 0x26C, 32 }, |
115 | { "DMA_CNTLch7", 0x274, 16 }, | 115 | { "DMA_CNTLch7", 0x274, 16 }, |
116 | { "DMA_ADDRch7", 0x278, 16 }, | 116 | { "DMA_ADDRch7", 0x278, 32 }, |
117 | { "DMA_COUNTch7", 0x27C, 16 }, | 117 | { "DMA_COUNTch7", 0x27C, 32 }, |
118 | { } /* Terminating Entry */ | 118 | { } /* Terminating Entry */ |
119 | }; | 119 | }; |
120 | 120 | ||
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 21b9788d0243..59bef8f3a358 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c | |||
@@ -402,6 +402,9 @@ __acquires(musb->lock) | |||
402 | musb->g.a_alt_hnp_support = 1; | 402 | musb->g.a_alt_hnp_support = 1; |
403 | break; | 403 | break; |
404 | #endif | 404 | #endif |
405 | case USB_DEVICE_DEBUG_MODE: | ||
406 | handled = 0; | ||
407 | break; | ||
405 | stall: | 408 | stall: |
406 | default: | 409 | default: |
407 | handled = -EINVAL; | 410 | handled = -EINVAL; |
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 92e85e027cfb..43233c397b6e 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c | |||
@@ -244,7 +244,7 @@ int musb_hub_control( | |||
244 | 244 | ||
245 | spin_lock_irqsave(&musb->lock, flags); | 245 | spin_lock_irqsave(&musb->lock, flags); |
246 | 246 | ||
247 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { | 247 | if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) { |
248 | spin_unlock_irqrestore(&musb->lock, flags); | 248 | spin_unlock_irqrestore(&musb->lock, flags); |
249 | return -ESHUTDOWN; | 249 | return -ESHUTDOWN; |
250 | } | 250 | } |
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index dc66e4376d49..6dc107f25245 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c | |||
@@ -173,10 +173,7 @@ static int dma_channel_program(struct dma_channel *channel, | |||
173 | musb_channel->max_packet_sz = packet_sz; | 173 | musb_channel->max_packet_sz = packet_sz; |
174 | channel->status = MUSB_DMA_STATUS_BUSY; | 174 | channel->status = MUSB_DMA_STATUS_BUSY; |
175 | 175 | ||
176 | if ((mode == 1) && (len >= packet_sz)) | 176 | configure_channel(channel, packet_sz, mode, dma_addr, len); |
177 | configure_channel(channel, packet_sz, 1, dma_addr, len); | ||
178 | else | ||
179 | configure_channel(channel, packet_sz, 0, dma_addr, len); | ||
180 | 177 | ||
181 | return true; | 178 | return true; |
182 | } | 179 | } |
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index e06d65e36bf7..2111a241dd03 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c | |||
@@ -32,8 +32,6 @@ | |||
32 | #include <linux/clk.h> | 32 | #include <linux/clk.h> |
33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
34 | 34 | ||
35 | #include <plat/mux.h> | ||
36 | |||
37 | #include "musb_core.h" | 35 | #include "musb_core.h" |
38 | #include "omap2430.h" | 36 | #include "omap2430.h" |
39 | 37 | ||
@@ -194,10 +192,6 @@ int __init musb_platform_init(struct musb *musb, void *board_data) | |||
194 | u32 l; | 192 | u32 l; |
195 | struct omap_musb_board_data *data = board_data; | 193 | struct omap_musb_board_data *data = board_data; |
196 | 194 | ||
197 | #if defined(CONFIG_ARCH_OMAP2430) | ||
198 | omap_cfg_reg(AE5_2430_USB0HS_STP); | ||
199 | #endif | ||
200 | |||
201 | /* We require some kind of external transceiver, hooked | 195 | /* We require some kind of external transceiver, hooked |
202 | * up through ULPI. TWL4030-family PMICs include one, | 196 | * up through ULPI. TWL4030-family PMICs include one, |
203 | * which needs a driver, drivers aren't always needed. | 197 | * which needs a driver, drivers aren't always needed. |
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 3d2d3e549bd1..3b1289572d72 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
@@ -49,8 +49,6 @@ config USB_ULPI | |||
49 | Enable this to support ULPI connected USB OTG transceivers which | 49 | Enable this to support ULPI connected USB OTG transceivers which |
50 | are likely found on embedded boards. | 50 | are likely found on embedded boards. |
51 | 51 | ||
52 | The only chip currently supported is NXP's ISP1504 | ||
53 | |||
54 | config TWL4030_USB | 52 | config TWL4030_USB |
55 | tristate "TWL4030 USB Transceiver Driver" | 53 | tristate "TWL4030 USB Transceiver Driver" |
56 | depends on TWL4030_CORE && REGULATOR_TWL4030 | 54 | depends on TWL4030_CORE && REGULATOR_TWL4030 |
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index d331b222ad21..ccc81950822b 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c | |||
@@ -31,30 +31,110 @@ | |||
31 | 31 | ||
32 | #define ULPI_ID(vendor, product) (((vendor) << 16) | (product)) | 32 | #define ULPI_ID(vendor, product) (((vendor) << 16) | (product)) |
33 | 33 | ||
34 | #define TR_FLAG(flags, a, b) (((flags) & a) ? b : 0) | ||
35 | |||
36 | /* ULPI hardcoded IDs, used for probing */ | 34 | /* ULPI hardcoded IDs, used for probing */ |
37 | static unsigned int ulpi_ids[] = { | 35 | static unsigned int ulpi_ids[] = { |
38 | ULPI_ID(0x04cc, 0x1504), /* NXP ISP1504 */ | 36 | ULPI_ID(0x04cc, 0x1504), /* NXP ISP1504 */ |
37 | ULPI_ID(0x0424, 0x0006), /* SMSC USB3319 */ | ||
39 | }; | 38 | }; |
40 | 39 | ||
41 | static int ulpi_set_flags(struct otg_transceiver *otg) | 40 | static int ulpi_set_otg_flags(struct otg_transceiver *otg) |
42 | { | 41 | { |
43 | unsigned int flags = 0; | 42 | unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN | |
43 | ULPI_OTG_CTRL_DM_PULLDOWN; | ||
44 | 44 | ||
45 | if (otg->flags & USB_OTG_PULLUP_ID) | 45 | if (otg->flags & ULPI_OTG_ID_PULLUP) |
46 | flags |= ULPI_OTG_CTRL_ID_PULLUP; | 46 | flags |= ULPI_OTG_CTRL_ID_PULLUP; |
47 | 47 | ||
48 | if (otg->flags & USB_OTG_PULLDOWN_DM) | 48 | /* |
49 | flags |= ULPI_OTG_CTRL_DM_PULLDOWN; | 49 | * ULPI Specification rev.1.1 default |
50 | * for Dp/DmPulldown is enabled. | ||
51 | */ | ||
52 | if (otg->flags & ULPI_OTG_DP_PULLDOWN_DIS) | ||
53 | flags &= ~ULPI_OTG_CTRL_DP_PULLDOWN; | ||
50 | 54 | ||
51 | if (otg->flags & USB_OTG_PULLDOWN_DP) | 55 | if (otg->flags & ULPI_OTG_DM_PULLDOWN_DIS) |
52 | flags |= ULPI_OTG_CTRL_DP_PULLDOWN; | 56 | flags &= ~ULPI_OTG_CTRL_DM_PULLDOWN; |
53 | 57 | ||
54 | if (otg->flags & USB_OTG_EXT_VBUS_INDICATOR) | 58 | if (otg->flags & ULPI_OTG_EXTVBUSIND) |
55 | flags |= ULPI_OTG_CTRL_EXTVBUSIND; | 59 | flags |= ULPI_OTG_CTRL_EXTVBUSIND; |
56 | 60 | ||
57 | return otg_io_write(otg, flags, ULPI_SET(ULPI_OTG_CTRL)); | 61 | return otg_io_write(otg, flags, ULPI_OTG_CTRL); |
62 | } | ||
63 | |||
64 | static int ulpi_set_fc_flags(struct otg_transceiver *otg) | ||
65 | { | ||
66 | unsigned int flags = 0; | ||
67 | |||
68 | /* | ||
69 | * ULPI Specification rev.1.1 default | ||
70 | * for XcvrSelect is Full Speed. | ||
71 | */ | ||
72 | if (otg->flags & ULPI_FC_HS) | ||
73 | flags |= ULPI_FUNC_CTRL_HIGH_SPEED; | ||
74 | else if (otg->flags & ULPI_FC_LS) | ||
75 | flags |= ULPI_FUNC_CTRL_LOW_SPEED; | ||
76 | else if (otg->flags & ULPI_FC_FS4LS) | ||
77 | flags |= ULPI_FUNC_CTRL_FS4LS; | ||
78 | else | ||
79 | flags |= ULPI_FUNC_CTRL_FULL_SPEED; | ||
80 | |||
81 | if (otg->flags & ULPI_FC_TERMSEL) | ||
82 | flags |= ULPI_FUNC_CTRL_TERMSELECT; | ||
83 | |||
84 | /* | ||
85 | * ULPI Specification rev.1.1 default | ||
86 | * for OpMode is Normal Operation. | ||
87 | */ | ||
88 | if (otg->flags & ULPI_FC_OP_NODRV) | ||
89 | flags |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; | ||
90 | else if (otg->flags & ULPI_FC_OP_DIS_NRZI) | ||
91 | flags |= ULPI_FUNC_CTRL_OPMODE_DISABLE_NRZI; | ||
92 | else if (otg->flags & ULPI_FC_OP_NSYNC_NEOP) | ||
93 | flags |= ULPI_FUNC_CTRL_OPMODE_NOSYNC_NOEOP; | ||
94 | else | ||
95 | flags |= ULPI_FUNC_CTRL_OPMODE_NORMAL; | ||
96 | |||
97 | /* | ||
98 | * ULPI Specification rev.1.1 default | ||
99 | * for SuspendM is Powered. | ||
100 | */ | ||
101 | flags |= ULPI_FUNC_CTRL_SUSPENDM; | ||
102 | |||
103 | return otg_io_write(otg, flags, ULPI_FUNC_CTRL); | ||
104 | } | ||
105 | |||
106 | static int ulpi_set_ic_flags(struct otg_transceiver *otg) | ||
107 | { | ||
108 | unsigned int flags = 0; | ||
109 | |||
110 | if (otg->flags & ULPI_IC_AUTORESUME) | ||
111 | flags |= ULPI_IFC_CTRL_AUTORESUME; | ||
112 | |||
113 | if (otg->flags & ULPI_IC_EXTVBUS_INDINV) | ||
114 | flags |= ULPI_IFC_CTRL_EXTERNAL_VBUS; | ||
115 | |||
116 | if (otg->flags & ULPI_IC_IND_PASSTHRU) | ||
117 | flags |= ULPI_IFC_CTRL_PASSTHRU; | ||
118 | |||
119 | if (otg->flags & ULPI_IC_PROTECT_DIS) | ||
120 | flags |= ULPI_IFC_CTRL_PROTECT_IFC_DISABLE; | ||
121 | |||
122 | return otg_io_write(otg, flags, ULPI_IFC_CTRL); | ||
123 | } | ||
124 | |||
125 | static int ulpi_set_flags(struct otg_transceiver *otg) | ||
126 | { | ||
127 | int ret; | ||
128 | |||
129 | ret = ulpi_set_otg_flags(otg); | ||
130 | if (ret) | ||
131 | return ret; | ||
132 | |||
133 | ret = ulpi_set_ic_flags(otg); | ||
134 | if (ret) | ||
135 | return ret; | ||
136 | |||
137 | return ulpi_set_fc_flags(otg); | ||
58 | } | 138 | } |
59 | 139 | ||
60 | static int ulpi_init(struct otg_transceiver *otg) | 140 | static int ulpi_init(struct otg_transceiver *otg) |
@@ -81,6 +161,31 @@ static int ulpi_init(struct otg_transceiver *otg) | |||
81 | return -ENODEV; | 161 | return -ENODEV; |
82 | } | 162 | } |
83 | 163 | ||
164 | static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host) | ||
165 | { | ||
166 | unsigned int flags = otg_io_read(otg, ULPI_IFC_CTRL); | ||
167 | |||
168 | if (!host) { | ||
169 | otg->host = NULL; | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | otg->host = host; | ||
174 | |||
175 | flags &= ~(ULPI_IFC_CTRL_6_PIN_SERIAL_MODE | | ||
176 | ULPI_IFC_CTRL_3_PIN_SERIAL_MODE | | ||
177 | ULPI_IFC_CTRL_CARKITMODE); | ||
178 | |||
179 | if (otg->flags & ULPI_IC_6PIN_SERIAL) | ||
180 | flags |= ULPI_IFC_CTRL_6_PIN_SERIAL_MODE; | ||
181 | else if (otg->flags & ULPI_IC_3PIN_SERIAL) | ||
182 | flags |= ULPI_IFC_CTRL_3_PIN_SERIAL_MODE; | ||
183 | else if (otg->flags & ULPI_IC_CARKIT) | ||
184 | flags |= ULPI_IFC_CTRL_CARKITMODE; | ||
185 | |||
186 | return otg_io_write(otg, flags, ULPI_IFC_CTRL); | ||
187 | } | ||
188 | |||
84 | static int ulpi_set_vbus(struct otg_transceiver *otg, bool on) | 189 | static int ulpi_set_vbus(struct otg_transceiver *otg, bool on) |
85 | { | 190 | { |
86 | unsigned int flags = otg_io_read(otg, ULPI_OTG_CTRL); | 191 | unsigned int flags = otg_io_read(otg, ULPI_OTG_CTRL); |
@@ -88,14 +193,14 @@ static int ulpi_set_vbus(struct otg_transceiver *otg, bool on) | |||
88 | flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT); | 193 | flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT); |
89 | 194 | ||
90 | if (on) { | 195 | if (on) { |
91 | if (otg->flags & USB_OTG_DRV_VBUS) | 196 | if (otg->flags & ULPI_OTG_DRVVBUS) |
92 | flags |= ULPI_OTG_CTRL_DRVVBUS; | 197 | flags |= ULPI_OTG_CTRL_DRVVBUS; |
93 | 198 | ||
94 | if (otg->flags & USB_OTG_DRV_VBUS_EXT) | 199 | if (otg->flags & ULPI_OTG_DRVVBUS_EXT) |
95 | flags |= ULPI_OTG_CTRL_DRVVBUS_EXT; | 200 | flags |= ULPI_OTG_CTRL_DRVVBUS_EXT; |
96 | } | 201 | } |
97 | 202 | ||
98 | return otg_io_write(otg, flags, ULPI_SET(ULPI_OTG_CTRL)); | 203 | return otg_io_write(otg, flags, ULPI_OTG_CTRL); |
99 | } | 204 | } |
100 | 205 | ||
101 | struct otg_transceiver * | 206 | struct otg_transceiver * |
@@ -112,6 +217,7 @@ otg_ulpi_create(struct otg_io_access_ops *ops, | |||
112 | otg->flags = flags; | 217 | otg->flags = flags; |
113 | otg->io_ops = ops; | 218 | otg->io_ops = ops; |
114 | otg->init = ulpi_init; | 219 | otg->init = ulpi_init; |
220 | otg->set_host = ulpi_set_host; | ||
115 | otg->set_vbus = ulpi_set_vbus; | 221 | otg->set_vbus = ulpi_set_vbus; |
116 | 222 | ||
117 | return otg; | 223 | return otg; |
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index bd8aab0ef1cf..916b2b6d765f 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -642,6 +642,15 @@ config USB_SERIAL_ZIO | |||
642 | To compile this driver as a module, choose M here: the | 642 | To compile this driver as a module, choose M here: the |
643 | module will be called zio. | 643 | module will be called zio. |
644 | 644 | ||
645 | config USB_SERIAL_SSU100 | ||
646 | tristate "USB Quatech SSU-100 Single Port Serial Driver" | ||
647 | help | ||
648 | Say Y here if you want to use the Quatech SSU-100 single | ||
649 | port usb to serial adapter. | ||
650 | |||
651 | To compile this driver as a module, choose M here: the | ||
652 | module will be called ssu100. | ||
653 | |||
645 | config USB_SERIAL_DEBUG | 654 | config USB_SERIAL_DEBUG |
646 | tristate "USB Debugging Device" | 655 | tristate "USB Debugging Device" |
647 | help | 656 | help |
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index e54c728c016e..40ebe17b6ea8 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile | |||
@@ -51,6 +51,7 @@ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o | |||
51 | obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o | 51 | obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o |
52 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o | 52 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o |
53 | obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o | 53 | obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o |
54 | obj-$(CONFIG_USB_SERIAL_SSU100) += ssu100.o | ||
54 | obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o | 55 | obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o |
55 | obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o | 56 | obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o |
56 | obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o | 57 | obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o |
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 8b8c7976b4c0..2bef4415c19c 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c | |||
@@ -126,6 +126,10 @@ static const struct usb_device_id id_table[] = { | |||
126 | { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ | 126 | { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ |
127 | { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ | 127 | { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ |
128 | { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ | 128 | { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ |
129 | { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ | ||
130 | { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ | ||
131 | { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ | ||
132 | { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ | ||
129 | { } /* Terminating Entry */ | 133 | { } /* Terminating Entry */ |
130 | }; | 134 | }; |
131 | 135 | ||
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index fd35f73b5721..b92070c103cd 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c | |||
@@ -609,8 +609,10 @@ static void digi_wakeup_write_lock(struct work_struct *work) | |||
609 | static void digi_wakeup_write(struct usb_serial_port *port) | 609 | static void digi_wakeup_write(struct usb_serial_port *port) |
610 | { | 610 | { |
611 | struct tty_struct *tty = tty_port_tty_get(&port->port); | 611 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
612 | tty_wakeup(tty); | 612 | if (tty) { |
613 | tty_kref_put(tty); | 613 | tty_wakeup(tty); |
614 | tty_kref_put(tty); | ||
615 | } | ||
614 | } | 616 | } |
615 | 617 | ||
616 | 618 | ||
@@ -1682,7 +1684,7 @@ static int digi_read_inb_callback(struct urb *urb) | |||
1682 | priv->dp_throttle_restart = 1; | 1684 | priv->dp_throttle_restart = 1; |
1683 | 1685 | ||
1684 | /* receive data */ | 1686 | /* receive data */ |
1685 | if (opcode == DIGI_CMD_RECEIVE_DATA) { | 1687 | if (tty && opcode == DIGI_CMD_RECEIVE_DATA) { |
1686 | /* get flag from port_status */ | 1688 | /* get flag from port_status */ |
1687 | flag = 0; | 1689 | flag = 0; |
1688 | 1690 | ||
@@ -1763,10 +1765,12 @@ static int digi_read_oob_callback(struct urb *urb) | |||
1763 | return -1; | 1765 | return -1; |
1764 | 1766 | ||
1765 | tty = tty_port_tty_get(&port->port); | 1767 | tty = tty_port_tty_get(&port->port); |
1768 | |||
1766 | rts = 0; | 1769 | rts = 0; |
1767 | rts = tty->termios->c_cflag & CRTSCTS; | 1770 | if (tty) |
1771 | rts = tty->termios->c_cflag & CRTSCTS; | ||
1768 | 1772 | ||
1769 | if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) { | 1773 | if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) { |
1770 | spin_lock(&priv->dp_port_lock); | 1774 | spin_lock(&priv->dp_port_lock); |
1771 | /* convert from digi flags to termiox flags */ | 1775 | /* convert from digi flags to termiox flags */ |
1772 | if (val & DIGI_READ_INPUT_SIGNALS_CTS) { | 1776 | if (val & DIGI_READ_INPUT_SIGNALS_CTS) { |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e298dc4baed7..eb12d9b096b4 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -157,6 +157,9 @@ static struct usb_device_id id_table_combined [] = { | |||
157 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) }, | 157 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) }, |
158 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) }, | 158 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) }, |
159 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) }, | 159 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) }, |
160 | { USB_DEVICE(FTDI_VID, FTDI_USINT_CAT_PID) }, | ||
161 | { USB_DEVICE(FTDI_VID, FTDI_USINT_WKEY_PID) }, | ||
162 | { USB_DEVICE(FTDI_VID, FTDI_USINT_RS232_PID) }, | ||
160 | { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, | 163 | { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, |
161 | { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, | 164 | { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, |
162 | { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, | 165 | { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, |
@@ -746,6 +749,7 @@ static struct usb_device_id id_table_combined [] = { | |||
746 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 749 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
747 | { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID), | 750 | { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID), |
748 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 751 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
752 | { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) }, | ||
749 | { }, /* Optional parameter entry */ | 753 | { }, /* Optional parameter entry */ |
750 | { } /* Terminating entry */ | 754 | { } /* Terminating entry */ |
751 | }; | 755 | }; |
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index d01946db8fac..6e612c52e763 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h | |||
@@ -40,6 +40,11 @@ | |||
40 | 40 | ||
41 | #define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ | 41 | #define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ |
42 | 42 | ||
43 | /* US Interface Navigator (http://www.usinterface.com/) */ | ||
44 | #define FTDI_USINT_CAT_PID 0xb810 /* Navigator CAT and 2nd PTT lines */ | ||
45 | #define FTDI_USINT_WKEY_PID 0xb811 /* Navigator WKEY and FSK lines */ | ||
46 | #define FTDI_USINT_RS232_PID 0xb812 /* Navigator RS232 and CONFIG lines */ | ||
47 | |||
43 | /* OOCDlink by Joern Kaipf <joernk@web.de> | 48 | /* OOCDlink by Joern Kaipf <joernk@web.de> |
44 | * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */ | 49 | * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */ |
45 | #define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */ | 50 | #define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */ |
@@ -1032,3 +1037,8 @@ | |||
1032 | #define XVERVE_SIGNALYZER_SH2_PID 0xBCA2 | 1037 | #define XVERVE_SIGNALYZER_SH2_PID 0xBCA2 |
1033 | #define XVERVE_SIGNALYZER_SH4_PID 0xBCA4 | 1038 | #define XVERVE_SIGNALYZER_SH4_PID 0xBCA4 |
1034 | 1039 | ||
1040 | /* | ||
1041 | * Segway Robotic Mobility Platform USB interface (using VID 0x0403) | ||
1042 | * Submitted by John G. Rogers | ||
1043 | */ | ||
1044 | #define SEGWAY_RMP200_PID 0xe729 | ||
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index a817ced82835..ca92f67747cc 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -208,18 +208,23 @@ retry: | |||
208 | urb->transfer_buffer_length = count; | 208 | urb->transfer_buffer_length = count; |
209 | usb_serial_debug_data(debug, &port->dev, __func__, count, | 209 | usb_serial_debug_data(debug, &port->dev, __func__, count, |
210 | urb->transfer_buffer); | 210 | urb->transfer_buffer); |
211 | spin_lock_irqsave(&port->lock, flags); | ||
212 | port->tx_bytes += count; | ||
213 | spin_unlock_irqrestore(&port->lock, flags); | ||
214 | |||
215 | clear_bit(i, &port->write_urbs_free); | ||
211 | result = usb_submit_urb(urb, GFP_ATOMIC); | 216 | result = usb_submit_urb(urb, GFP_ATOMIC); |
212 | if (result) { | 217 | if (result) { |
213 | dev_err(&port->dev, "%s - error submitting urb: %d\n", | 218 | dev_err(&port->dev, "%s - error submitting urb: %d\n", |
214 | __func__, result); | 219 | __func__, result); |
220 | set_bit(i, &port->write_urbs_free); | ||
221 | spin_lock_irqsave(&port->lock, flags); | ||
222 | port->tx_bytes -= count; | ||
223 | spin_unlock_irqrestore(&port->lock, flags); | ||
224 | |||
215 | clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); | 225 | clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); |
216 | return result; | 226 | return result; |
217 | } | 227 | } |
218 | clear_bit(i, &port->write_urbs_free); | ||
219 | |||
220 | spin_lock_irqsave(&port->lock, flags); | ||
221 | port->tx_bytes += count; | ||
222 | spin_unlock_irqrestore(&port->lock, flags); | ||
223 | 228 | ||
224 | /* Try sending off another urb, unless in irq context (in which case | 229 | /* Try sending off another urb, unless in irq context (in which case |
225 | * there will be no free urb). */ | 230 | * there will be no free urb). */ |
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 0fca2659206f..dc47f986df57 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
@@ -1298,7 +1298,7 @@ static int download_fw(struct edgeport_serial *serial) | |||
1298 | kfree(header); | 1298 | kfree(header); |
1299 | kfree(rom_desc); | 1299 | kfree(rom_desc); |
1300 | kfree(ti_manuf_desc); | 1300 | kfree(ti_manuf_desc); |
1301 | return status; | 1301 | return -EINVAL; |
1302 | } | 1302 | } |
1303 | 1303 | ||
1304 | /* verify the write -- must do this in order for | 1304 | /* verify the write -- must do this in order for |
@@ -1321,7 +1321,7 @@ static int download_fw(struct edgeport_serial *serial) | |||
1321 | kfree(header); | 1321 | kfree(header); |
1322 | kfree(rom_desc); | 1322 | kfree(rom_desc); |
1323 | kfree(ti_manuf_desc); | 1323 | kfree(ti_manuf_desc); |
1324 | return status; | 1324 | return -EINVAL; |
1325 | } | 1325 | } |
1326 | 1326 | ||
1327 | kfree(vheader); | 1327 | kfree(vheader); |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 28913fa95fb7..4735931b4c7b 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -534,7 +534,6 @@ static struct usb_device_id ipaq_id_table [] = { | |||
534 | { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */ | 534 | { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */ |
535 | { USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */ | 535 | { USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */ |
536 | { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */ | 536 | { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */ |
537 | { USB_DEVICE(0x0BB4, 0x00CF) }, /* HTC smartphone modems */ | ||
538 | { } /* Terminating entry */ | 537 | { } /* Terminating entry */ |
539 | }; | 538 | }; |
540 | 539 | ||
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 74551cb2e8ee..efc72113216b 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c | |||
@@ -1,6 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Infinity Unlimited USB Phoenix driver | 2 | * Infinity Unlimited USB Phoenix driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010 James Courtier-Dutton (James@superbug.co.uk) | ||
5 | |||
4 | * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com) | 6 | * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com) |
5 | * | 7 | * |
6 | * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás) | 8 | * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás) |
@@ -40,7 +42,7 @@ static int debug; | |||
40 | /* | 42 | /* |
41 | * Version Information | 43 | * Version Information |
42 | */ | 44 | */ |
43 | #define DRIVER_VERSION "v0.11" | 45 | #define DRIVER_VERSION "v0.12" |
44 | #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" | 46 | #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" |
45 | 47 | ||
46 | static const struct usb_device_id id_table[] = { | 48 | static const struct usb_device_id id_table[] = { |
@@ -81,6 +83,9 @@ struct iuu_private { | |||
81 | u8 *dbgbuf; /* debug buffer */ | 83 | u8 *dbgbuf; /* debug buffer */ |
82 | u8 len; | 84 | u8 len; |
83 | int vcc; /* vcc (either 3 or 5 V) */ | 85 | int vcc; /* vcc (either 3 or 5 V) */ |
86 | u32 baud; | ||
87 | u32 boost; | ||
88 | u32 clk; | ||
84 | }; | 89 | }; |
85 | 90 | ||
86 | 91 | ||
@@ -157,13 +162,14 @@ static int iuu_tiocmset(struct tty_struct *tty, struct file *file, | |||
157 | port->number, set, clear); | 162 | port->number, set, clear); |
158 | 163 | ||
159 | spin_lock_irqsave(&priv->lock, flags); | 164 | spin_lock_irqsave(&priv->lock, flags); |
160 | if (set & TIOCM_RTS) | ||
161 | priv->tiostatus = TIOCM_RTS; | ||
162 | 165 | ||
163 | if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) { | 166 | if ((set & TIOCM_RTS) && !(priv->tiostatus == TIOCM_RTS)) { |
164 | dbg("%s TIOCMSET RESET called !!!", __func__); | 167 | dbg("%s TIOCMSET RESET called !!!", __func__); |
165 | priv->reset = 1; | 168 | priv->reset = 1; |
166 | } | 169 | } |
170 | if (set & TIOCM_RTS) | ||
171 | priv->tiostatus = TIOCM_RTS; | ||
172 | |||
167 | spin_unlock_irqrestore(&priv->lock, flags); | 173 | spin_unlock_irqrestore(&priv->lock, flags); |
168 | return 0; | 174 | return 0; |
169 | } | 175 | } |
@@ -851,20 +857,24 @@ static int iuu_uart_off(struct usb_serial_port *port) | |||
851 | return status; | 857 | return status; |
852 | } | 858 | } |
853 | 859 | ||
854 | static int iuu_uart_baud(struct usb_serial_port *port, u32 baud, | 860 | static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base, |
855 | u32 *actual, u8 parity) | 861 | u32 *actual, u8 parity) |
856 | { | 862 | { |
857 | int status; | 863 | int status; |
864 | u32 baud; | ||
858 | u8 *dataout; | 865 | u8 *dataout; |
859 | u8 DataCount = 0; | 866 | u8 DataCount = 0; |
860 | u8 T1Frekvens = 0; | 867 | u8 T1Frekvens = 0; |
861 | u8 T1reload = 0; | 868 | u8 T1reload = 0; |
862 | unsigned int T1FrekvensHZ = 0; | 869 | unsigned int T1FrekvensHZ = 0; |
863 | 870 | ||
871 | dbg("%s - enter baud_base=%d", __func__, baud_base); | ||
864 | dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL); | 872 | dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL); |
865 | 873 | ||
866 | if (!dataout) | 874 | if (!dataout) |
867 | return -ENOMEM; | 875 | return -ENOMEM; |
876 | /*baud = (((priv->clk / 35) * baud_base) / 100000); */ | ||
877 | baud = baud_base; | ||
868 | 878 | ||
869 | if (baud < 1200 || baud > 230400) { | 879 | if (baud < 1200 || baud > 230400) { |
870 | kfree(dataout); | 880 | kfree(dataout); |
@@ -948,15 +958,20 @@ static void iuu_set_termios(struct tty_struct *tty, | |||
948 | struct usb_serial_port *port, struct ktermios *old_termios) | 958 | struct usb_serial_port *port, struct ktermios *old_termios) |
949 | { | 959 | { |
950 | const u32 supported_mask = CMSPAR|PARENB|PARODD; | 960 | const u32 supported_mask = CMSPAR|PARENB|PARODD; |
951 | 961 | struct iuu_private *priv = usb_get_serial_port_data(port); | |
952 | unsigned int cflag = tty->termios->c_cflag; | 962 | unsigned int cflag = tty->termios->c_cflag; |
953 | int status; | 963 | int status; |
954 | u32 actual; | 964 | u32 actual; |
955 | u32 parity; | 965 | u32 parity; |
956 | int csize = CS7; | 966 | int csize = CS7; |
957 | int baud = 9600; /* Fixed for the moment */ | 967 | int baud; |
958 | u32 newval = cflag & supported_mask; | 968 | u32 newval = cflag & supported_mask; |
959 | 969 | ||
970 | /* Just use the ospeed. ispeed should be the same. */ | ||
971 | baud = tty->termios->c_ospeed; | ||
972 | |||
973 | dbg("%s - enter c_ospeed or baud=%d", __func__, baud); | ||
974 | |||
960 | /* compute the parity parameter */ | 975 | /* compute the parity parameter */ |
961 | parity = 0; | 976 | parity = 0; |
962 | if (cflag & CMSPAR) { /* Using mark space */ | 977 | if (cflag & CMSPAR) { /* Using mark space */ |
@@ -976,15 +991,15 @@ static void iuu_set_termios(struct tty_struct *tty, | |||
976 | 991 | ||
977 | /* set it */ | 992 | /* set it */ |
978 | status = iuu_uart_baud(port, | 993 | status = iuu_uart_baud(port, |
979 | (clockmode == 2) ? 16457 : 9600 * boost / 100, | 994 | baud * priv->boost / 100, |
980 | &actual, parity); | 995 | &actual, parity); |
981 | 996 | ||
982 | /* set the termios value to the real one, so the user now what has | 997 | /* set the termios value to the real one, so the user now what has |
983 | * changed. We support few fields so its easies to copy the old hw | 998 | * changed. We support few fields so its easies to copy the old hw |
984 | * settings back over and then adjust them | 999 | * settings back over and then adjust them |
985 | */ | 1000 | */ |
986 | if (old_termios) | 1001 | if (old_termios) |
987 | tty_termios_copy_hw(tty->termios, old_termios); | 1002 | tty_termios_copy_hw(tty->termios, old_termios); |
988 | if (status != 0) /* Set failed - return old bits */ | 1003 | if (status != 0) /* Set failed - return old bits */ |
989 | return; | 1004 | return; |
990 | /* Re-encode speed, parity and csize */ | 1005 | /* Re-encode speed, parity and csize */ |
@@ -1018,6 +1033,7 @@ static void iuu_close(struct usb_serial_port *port) | |||
1018 | 1033 | ||
1019 | static void iuu_init_termios(struct tty_struct *tty) | 1034 | static void iuu_init_termios(struct tty_struct *tty) |
1020 | { | 1035 | { |
1036 | dbg("%s - enter", __func__); | ||
1021 | *(tty->termios) = tty_std_termios; | 1037 | *(tty->termios) = tty_std_termios; |
1022 | tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 | 1038 | tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 |
1023 | | TIOCM_CTS | CSTOPB | PARENB; | 1039 | | TIOCM_CTS | CSTOPB | PARENB; |
@@ -1033,10 +1049,16 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1033 | struct usb_serial *serial = port->serial; | 1049 | struct usb_serial *serial = port->serial; |
1034 | u8 *buf; | 1050 | u8 *buf; |
1035 | int result; | 1051 | int result; |
1052 | int baud; | ||
1036 | u32 actual; | 1053 | u32 actual; |
1037 | struct iuu_private *priv = usb_get_serial_port_data(port); | 1054 | struct iuu_private *priv = usb_get_serial_port_data(port); |
1038 | 1055 | ||
1039 | dbg("%s - port %d", __func__, port->number); | 1056 | baud = tty->termios->c_ospeed; |
1057 | tty->termios->c_ispeed = baud; | ||
1058 | /* Re-encode speed */ | ||
1059 | tty_encode_baud_rate(tty, baud, baud); | ||
1060 | |||
1061 | dbg("%s - port %d, baud %d", __func__, port->number, baud); | ||
1040 | usb_clear_halt(serial->dev, port->write_urb->pipe); | 1062 | usb_clear_halt(serial->dev, port->write_urb->pipe); |
1041 | usb_clear_halt(serial->dev, port->read_urb->pipe); | 1063 | usb_clear_halt(serial->dev, port->read_urb->pipe); |
1042 | 1064 | ||
@@ -1071,23 +1093,29 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1071 | iuu_uart_on(port); | 1093 | iuu_uart_on(port); |
1072 | if (boost < 100) | 1094 | if (boost < 100) |
1073 | boost = 100; | 1095 | boost = 100; |
1096 | priv->boost = boost; | ||
1097 | priv->baud = baud; | ||
1074 | switch (clockmode) { | 1098 | switch (clockmode) { |
1075 | case 2: /* 3.680 Mhz */ | 1099 | case 2: /* 3.680 Mhz */ |
1100 | priv->clk = IUU_CLK_3680000; | ||
1076 | iuu_clk(port, IUU_CLK_3680000 * boost / 100); | 1101 | iuu_clk(port, IUU_CLK_3680000 * boost / 100); |
1077 | result = | 1102 | result = |
1078 | iuu_uart_baud(port, 9600 * boost / 100, &actual, | 1103 | iuu_uart_baud(port, baud * boost / 100, &actual, |
1079 | IUU_PARITY_EVEN); | 1104 | IUU_PARITY_EVEN); |
1080 | break; | 1105 | break; |
1081 | case 3: /* 6.00 Mhz */ | 1106 | case 3: /* 6.00 Mhz */ |
1082 | iuu_clk(port, IUU_CLK_6000000 * boost / 100); | 1107 | iuu_clk(port, IUU_CLK_6000000 * boost / 100); |
1108 | priv->clk = IUU_CLK_6000000; | ||
1109 | /* Ratio of 6000000 to 3500000 for baud 9600 */ | ||
1083 | result = | 1110 | result = |
1084 | iuu_uart_baud(port, 16457 * boost / 100, &actual, | 1111 | iuu_uart_baud(port, 16457 * boost / 100, &actual, |
1085 | IUU_PARITY_EVEN); | 1112 | IUU_PARITY_EVEN); |
1086 | break; | 1113 | break; |
1087 | default: /* 3.579 Mhz */ | 1114 | default: /* 3.579 Mhz */ |
1088 | iuu_clk(port, IUU_CLK_3579000 * boost / 100); | 1115 | iuu_clk(port, IUU_CLK_3579000 * boost / 100); |
1116 | priv->clk = IUU_CLK_3579000; | ||
1089 | result = | 1117 | result = |
1090 | iuu_uart_baud(port, 9600 * boost / 100, &actual, | 1118 | iuu_uart_baud(port, baud * boost / 100, &actual, |
1091 | IUU_PARITY_EVEN); | 1119 | IUU_PARITY_EVEN); |
1092 | } | 1120 | } |
1093 | 1121 | ||
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5cd30e4345c6..9fc6ea2c681f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -145,7 +145,10 @@ static void option_instat_callback(struct urb *urb); | |||
145 | #define HUAWEI_PRODUCT_E143D 0x143D | 145 | #define HUAWEI_PRODUCT_E143D 0x143D |
146 | #define HUAWEI_PRODUCT_E143E 0x143E | 146 | #define HUAWEI_PRODUCT_E143E 0x143E |
147 | #define HUAWEI_PRODUCT_E143F 0x143F | 147 | #define HUAWEI_PRODUCT_E143F 0x143F |
148 | #define HUAWEI_PRODUCT_K4505 0x1464 | ||
149 | #define HUAWEI_PRODUCT_K3765 0x1465 | ||
148 | #define HUAWEI_PRODUCT_E14AC 0x14AC | 150 | #define HUAWEI_PRODUCT_E14AC 0x14AC |
151 | #define HUAWEI_PRODUCT_ETS1220 0x1803 | ||
149 | 152 | ||
150 | #define QUANTA_VENDOR_ID 0x0408 | 153 | #define QUANTA_VENDOR_ID 0x0408 |
151 | #define QUANTA_PRODUCT_Q101 0xEA02 | 154 | #define QUANTA_PRODUCT_Q101 0xEA02 |
@@ -264,9 +267,6 @@ static void option_instat_callback(struct urb *urb); | |||
264 | #define BANDRICH_PRODUCT_1011 0x1011 | 267 | #define BANDRICH_PRODUCT_1011 0x1011 |
265 | #define BANDRICH_PRODUCT_1012 0x1012 | 268 | #define BANDRICH_PRODUCT_1012 0x1012 |
266 | 269 | ||
267 | #define AMOI_VENDOR_ID 0x1614 | ||
268 | #define AMOI_PRODUCT_9508 0x0800 | ||
269 | |||
270 | #define QUALCOMM_VENDOR_ID 0x05C6 | 270 | #define QUALCOMM_VENDOR_ID 0x05C6 |
271 | 271 | ||
272 | #define CMOTECH_VENDOR_ID 0x16d8 | 272 | #define CMOTECH_VENDOR_ID 0x16d8 |
@@ -482,8 +482,10 @@ static const struct usb_device_id option_ids[] = { | |||
482 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, | 482 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, |
483 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, | 483 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, |
484 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, | 484 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, |
485 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff) }, | ||
486 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) }, | ||
487 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, | ||
485 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) }, | 488 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) }, |
486 | { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) }, | ||
487 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ | 489 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ |
488 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */ | 490 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */ |
489 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */ | 491 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */ |
@@ -1017,6 +1019,13 @@ static int option_probe(struct usb_serial *serial, | |||
1017 | serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff) | 1019 | serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff) |
1018 | return -ENODEV; | 1020 | return -ENODEV; |
1019 | 1021 | ||
1022 | /* Don't bind network interfaces on Huawei K3765 & K4505 */ | ||
1023 | if (serial->dev->descriptor.idVendor == HUAWEI_VENDOR_ID && | ||
1024 | (serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K3765 || | ||
1025 | serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505) && | ||
1026 | serial->interface->cur_altsetting->desc.bInterfaceNumber == 1) | ||
1027 | return -ENODEV; | ||
1028 | |||
1020 | data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); | 1029 | data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); |
1021 | 1030 | ||
1022 | if (!data) | 1031 | if (!data) |
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c new file mode 100644 index 000000000000..6e82d4f54bc8 --- /dev/null +++ b/drivers/usb/serial/ssu100.c | |||
@@ -0,0 +1,698 @@ | |||
1 | /* | ||
2 | * usb-serial driver for Quatech SSU-100 | ||
3 | * | ||
4 | * based on ftdi_sio.c and the original serqt_usb.c from Quatech | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #include <linux/errno.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/tty.h> | ||
12 | #include <linux/tty_driver.h> | ||
13 | #include <linux/tty_flip.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/serial.h> | ||
16 | #include <linux/usb.h> | ||
17 | #include <linux/usb/serial.h> | ||
18 | #include <linux/uaccess.h> | ||
19 | |||
20 | #define QT_OPEN_CLOSE_CHANNEL 0xca | ||
21 | #define QT_SET_GET_DEVICE 0xc2 | ||
22 | #define QT_SET_GET_REGISTER 0xc0 | ||
23 | #define QT_GET_SET_PREBUF_TRIG_LVL 0xcc | ||
24 | #define QT_SET_ATF 0xcd | ||
25 | #define QT_GET_SET_UART 0xc1 | ||
26 | #define QT_TRANSFER_IN 0xc0 | ||
27 | #define QT_HW_FLOW_CONTROL_MASK 0xc5 | ||
28 | #define QT_SW_FLOW_CONTROL_MASK 0xc6 | ||
29 | |||
30 | #define MODEM_CTL_REGISTER 0x04 | ||
31 | #define MODEM_STATUS_REGISTER 0x06 | ||
32 | |||
33 | |||
34 | #define SERIAL_LSR_OE 0x02 | ||
35 | #define SERIAL_LSR_PE 0x04 | ||
36 | #define SERIAL_LSR_FE 0x08 | ||
37 | #define SERIAL_LSR_BI 0x10 | ||
38 | |||
39 | #define SERIAL_LSR_TEMT 0x40 | ||
40 | |||
41 | #define SERIAL_MCR_DTR 0x01 | ||
42 | #define SERIAL_MCR_RTS 0x02 | ||
43 | #define SERIAL_MCR_LOOP 0x10 | ||
44 | |||
45 | #define SERIAL_MSR_CTS 0x10 | ||
46 | #define SERIAL_MSR_CD 0x80 | ||
47 | #define SERIAL_MSR_RI 0x40 | ||
48 | #define SERIAL_MSR_DSR 0x20 | ||
49 | #define SERIAL_MSR_MASK 0xf0 | ||
50 | |||
51 | #define SERIAL_CRTSCTS ((SERIAL_MCR_RTS << 8) | SERIAL_MSR_CTS) | ||
52 | |||
53 | #define SERIAL_8_DATA 0x03 | ||
54 | #define SERIAL_7_DATA 0x02 | ||
55 | #define SERIAL_6_DATA 0x01 | ||
56 | #define SERIAL_5_DATA 0x00 | ||
57 | |||
58 | #define SERIAL_ODD_PARITY 0X08 | ||
59 | #define SERIAL_EVEN_PARITY 0X18 | ||
60 | |||
61 | #define MAX_BAUD_RATE 460800 | ||
62 | |||
63 | #define ATC_DISABLED 0x00 | ||
64 | #define DUPMODE_BITS 0xc0 | ||
65 | #define RR_BITS 0x03 | ||
66 | #define LOOPMODE_BITS 0x41 | ||
67 | #define RS232_MODE 0x00 | ||
68 | #define RTSCTS_TO_CONNECTOR 0x40 | ||
69 | #define CLKS_X4 0x02 | ||
70 | #define FULLPWRBIT 0x00000080 | ||
71 | #define NEXT_BOARD_POWER_BIT 0x00000004 | ||
72 | |||
73 | static int debug = 1; | ||
74 | |||
75 | /* Version Information */ | ||
76 | #define DRIVER_VERSION "v0.1" | ||
77 | #define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver" | ||
78 | |||
79 | #define USB_VENDOR_ID_QUATECH 0x061d /* Quatech VID */ | ||
80 | #define QUATECH_SSU100 0xC020 /* SSU100 */ | ||
81 | |||
82 | static const struct usb_device_id id_table[] = { | ||
83 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)}, | ||
84 | {} /* Terminating entry */ | ||
85 | }; | ||
86 | |||
87 | MODULE_DEVICE_TABLE(usb, id_table); | ||
88 | |||
89 | |||
90 | static struct usb_driver ssu100_driver = { | ||
91 | .name = "ssu100", | ||
92 | .probe = usb_serial_probe, | ||
93 | .disconnect = usb_serial_disconnect, | ||
94 | .id_table = id_table, | ||
95 | .suspend = usb_serial_suspend, | ||
96 | .resume = usb_serial_resume, | ||
97 | .no_dynamic_id = 1, | ||
98 | .supports_autosuspend = 1, | ||
99 | }; | ||
100 | |||
101 | struct ssu100_port_private { | ||
102 | u8 shadowLSR; | ||
103 | u8 shadowMSR; | ||
104 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | ||
105 | unsigned short max_packet_size; | ||
106 | }; | ||
107 | |||
108 | static void ssu100_release(struct usb_serial *serial) | ||
109 | { | ||
110 | struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port); | ||
111 | |||
112 | dbg("%s", __func__); | ||
113 | kfree(priv); | ||
114 | } | ||
115 | |||
116 | static inline int ssu100_control_msg(struct usb_device *dev, | ||
117 | u8 request, u16 data, u16 index) | ||
118 | { | ||
119 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
120 | request, 0x40, data, index, | ||
121 | NULL, 0, 300); | ||
122 | } | ||
123 | |||
124 | static inline int ssu100_setdevice(struct usb_device *dev, u8 *data) | ||
125 | { | ||
126 | u16 x = ((u16)(data[1] << 8) | (u16)(data[0])); | ||
127 | |||
128 | return ssu100_control_msg(dev, QT_SET_GET_DEVICE, x, 0); | ||
129 | } | ||
130 | |||
131 | |||
132 | static inline int ssu100_getdevice(struct usb_device *dev, u8 *data) | ||
133 | { | ||
134 | return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
135 | QT_SET_GET_DEVICE, 0xc0, 0, 0, | ||
136 | data, 3, 300); | ||
137 | } | ||
138 | |||
139 | static inline int ssu100_getregister(struct usb_device *dev, | ||
140 | unsigned short uart, | ||
141 | unsigned short reg, | ||
142 | u8 *data) | ||
143 | { | ||
144 | return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
145 | QT_SET_GET_REGISTER, 0xc0, reg, | ||
146 | uart, data, sizeof(*data), 300); | ||
147 | |||
148 | } | ||
149 | |||
150 | |||
151 | static inline int ssu100_setregister(struct usb_device *dev, | ||
152 | unsigned short uart, | ||
153 | u16 data) | ||
154 | { | ||
155 | u16 value = (data << 8) | MODEM_CTL_REGISTER; | ||
156 | |||
157 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
158 | QT_SET_GET_REGISTER, 0x40, value, uart, | ||
159 | NULL, 0, 300); | ||
160 | |||
161 | } | ||
162 | |||
163 | #define set_mctrl(dev, set) update_mctrl((dev), (set), 0) | ||
164 | #define clear_mctrl(dev, clear) update_mctrl((dev), 0, (clear)) | ||
165 | |||
166 | /* these do not deal with device that have more than 1 port */ | ||
167 | static inline int update_mctrl(struct usb_device *dev, unsigned int set, | ||
168 | unsigned int clear) | ||
169 | { | ||
170 | unsigned urb_value; | ||
171 | int result; | ||
172 | |||
173 | if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) { | ||
174 | dbg("%s - DTR|RTS not being set|cleared", __func__); | ||
175 | return 0; /* no change */ | ||
176 | } | ||
177 | |||
178 | clear &= ~set; /* 'set' takes precedence over 'clear' */ | ||
179 | urb_value = 0; | ||
180 | if (set & TIOCM_DTR) | ||
181 | urb_value |= SERIAL_MCR_DTR; | ||
182 | if (set & TIOCM_RTS) | ||
183 | urb_value |= SERIAL_MCR_RTS; | ||
184 | |||
185 | result = ssu100_setregister(dev, 0, urb_value); | ||
186 | if (result < 0) | ||
187 | dbg("%s Error from MODEM_CTRL urb", __func__); | ||
188 | |||
189 | return result; | ||
190 | } | ||
191 | |||
192 | static int ssu100_initdevice(struct usb_device *dev) | ||
193 | { | ||
194 | u8 *data; | ||
195 | int result = 0; | ||
196 | |||
197 | dbg("%s", __func__); | ||
198 | |||
199 | data = kzalloc(3, GFP_KERNEL); | ||
200 | if (!data) | ||
201 | return -ENOMEM; | ||
202 | |||
203 | result = ssu100_getdevice(dev, data); | ||
204 | if (result < 0) { | ||
205 | dbg("%s - get_device failed %i", __func__, result); | ||
206 | goto out; | ||
207 | } | ||
208 | |||
209 | data[1] &= ~FULLPWRBIT; | ||
210 | |||
211 | result = ssu100_setdevice(dev, data); | ||
212 | if (result < 0) { | ||
213 | dbg("%s - setdevice failed %i", __func__, result); | ||
214 | goto out; | ||
215 | } | ||
216 | |||
217 | result = ssu100_control_msg(dev, QT_GET_SET_PREBUF_TRIG_LVL, 128, 0); | ||
218 | if (result < 0) { | ||
219 | dbg("%s - set prebuffer level failed %i", __func__, result); | ||
220 | goto out; | ||
221 | } | ||
222 | |||
223 | result = ssu100_control_msg(dev, QT_SET_ATF, ATC_DISABLED, 0); | ||
224 | if (result < 0) { | ||
225 | dbg("%s - set ATFprebuffer level failed %i", __func__, result); | ||
226 | goto out; | ||
227 | } | ||
228 | |||
229 | result = ssu100_getdevice(dev, data); | ||
230 | if (result < 0) { | ||
231 | dbg("%s - get_device failed %i", __func__, result); | ||
232 | goto out; | ||
233 | } | ||
234 | |||
235 | data[0] &= ~(RR_BITS | DUPMODE_BITS); | ||
236 | data[0] |= CLKS_X4; | ||
237 | data[1] &= ~(LOOPMODE_BITS); | ||
238 | data[1] |= RS232_MODE; | ||
239 | |||
240 | result = ssu100_setdevice(dev, data); | ||
241 | if (result < 0) { | ||
242 | dbg("%s - setdevice failed %i", __func__, result); | ||
243 | goto out; | ||
244 | } | ||
245 | |||
246 | out: kfree(data); | ||
247 | return result; | ||
248 | |||
249 | } | ||
250 | |||
251 | |||
252 | static void ssu100_set_termios(struct tty_struct *tty, | ||
253 | struct usb_serial_port *port, | ||
254 | struct ktermios *old_termios) | ||
255 | { | ||
256 | struct usb_device *dev = port->serial->dev; | ||
257 | struct ktermios *termios = tty->termios; | ||
258 | u16 baud, divisor, remainder; | ||
259 | unsigned int cflag = termios->c_cflag; | ||
260 | u16 urb_value = 0; /* will hold the new flags */ | ||
261 | int result; | ||
262 | |||
263 | dbg("%s", __func__); | ||
264 | |||
265 | if (cflag & PARENB) { | ||
266 | if (cflag & PARODD) | ||
267 | urb_value |= SERIAL_ODD_PARITY; | ||
268 | else | ||
269 | urb_value |= SERIAL_EVEN_PARITY; | ||
270 | } | ||
271 | |||
272 | switch (cflag & CSIZE) { | ||
273 | case CS5: | ||
274 | urb_value |= SERIAL_5_DATA; | ||
275 | break; | ||
276 | case CS6: | ||
277 | urb_value |= SERIAL_6_DATA; | ||
278 | break; | ||
279 | case CS7: | ||
280 | urb_value |= SERIAL_7_DATA; | ||
281 | break; | ||
282 | default: | ||
283 | case CS8: | ||
284 | urb_value |= SERIAL_8_DATA; | ||
285 | break; | ||
286 | } | ||
287 | |||
288 | baud = tty_get_baud_rate(tty); | ||
289 | if (!baud) | ||
290 | baud = 9600; | ||
291 | |||
292 | dbg("%s - got baud = %d\n", __func__, baud); | ||
293 | |||
294 | |||
295 | divisor = MAX_BAUD_RATE / baud; | ||
296 | remainder = MAX_BAUD_RATE % baud; | ||
297 | if (((remainder * 2) >= baud) && (baud != 110)) | ||
298 | divisor++; | ||
299 | |||
300 | urb_value = urb_value << 8; | ||
301 | |||
302 | result = ssu100_control_msg(dev, QT_GET_SET_UART, divisor, urb_value); | ||
303 | if (result < 0) | ||
304 | dbg("%s - set uart failed", __func__); | ||
305 | |||
306 | if (cflag & CRTSCTS) | ||
307 | result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK, | ||
308 | SERIAL_CRTSCTS, 0); | ||
309 | else | ||
310 | result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK, | ||
311 | 0, 0); | ||
312 | if (result < 0) | ||
313 | dbg("%s - set HW flow control failed", __func__); | ||
314 | |||
315 | if (I_IXOFF(tty) || I_IXON(tty)) { | ||
316 | u16 x = ((u16)(START_CHAR(tty) << 8) | (u16)(STOP_CHAR(tty))); | ||
317 | |||
318 | result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK, | ||
319 | x, 0); | ||
320 | } else | ||
321 | result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK, | ||
322 | 0, 0); | ||
323 | |||
324 | if (result < 0) | ||
325 | dbg("%s - set SW flow control failed", __func__); | ||
326 | |||
327 | } | ||
328 | |||
329 | |||
330 | static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) | ||
331 | { | ||
332 | struct usb_device *dev = port->serial->dev; | ||
333 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | ||
334 | u8 *data; | ||
335 | int result; | ||
336 | |||
337 | dbg("%s - port %d", __func__, port->number); | ||
338 | |||
339 | data = kzalloc(2, GFP_KERNEL); | ||
340 | if (!data) | ||
341 | return -ENOMEM; | ||
342 | |||
343 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
344 | QT_OPEN_CLOSE_CHANNEL, | ||
345 | QT_TRANSFER_IN, 0x01, | ||
346 | 0, data, 2, 300); | ||
347 | if (result < 0) { | ||
348 | dbg("%s - open failed %i", __func__, result); | ||
349 | kfree(data); | ||
350 | return result; | ||
351 | } | ||
352 | |||
353 | priv->shadowLSR = data[0] & (SERIAL_LSR_OE | SERIAL_LSR_PE | | ||
354 | SERIAL_LSR_FE | SERIAL_LSR_BI); | ||
355 | |||
356 | priv->shadowMSR = data[1] & (SERIAL_MSR_CTS | SERIAL_MSR_DSR | | ||
357 | SERIAL_MSR_RI | SERIAL_MSR_CD); | ||
358 | |||
359 | kfree(data); | ||
360 | |||
361 | /* set to 9600 */ | ||
362 | result = ssu100_control_msg(dev, QT_GET_SET_UART, 0x30, 0x0300); | ||
363 | if (result < 0) | ||
364 | dbg("%s - set uart failed", __func__); | ||
365 | |||
366 | if (tty) | ||
367 | ssu100_set_termios(tty, port, tty->termios); | ||
368 | |||
369 | return usb_serial_generic_open(tty, port); | ||
370 | } | ||
371 | |||
372 | static void ssu100_close(struct usb_serial_port *port) | ||
373 | { | ||
374 | dbg("%s", __func__); | ||
375 | usb_serial_generic_close(port); | ||
376 | } | ||
377 | |||
378 | static int get_serial_info(struct usb_serial_port *port, | ||
379 | struct serial_struct __user *retinfo) | ||
380 | { | ||
381 | struct serial_struct tmp; | ||
382 | |||
383 | if (!retinfo) | ||
384 | return -EFAULT; | ||
385 | |||
386 | memset(&tmp, 0, sizeof(tmp)); | ||
387 | tmp.line = port->serial->minor; | ||
388 | tmp.port = 0; | ||
389 | tmp.irq = 0; | ||
390 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | ||
391 | tmp.xmit_fifo_size = port->bulk_out_size; | ||
392 | tmp.baud_base = 9600; | ||
393 | tmp.close_delay = 5*HZ; | ||
394 | tmp.closing_wait = 30*HZ; | ||
395 | |||
396 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | ||
397 | return -EFAULT; | ||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static int ssu100_ioctl(struct tty_struct *tty, struct file *file, | ||
402 | unsigned int cmd, unsigned long arg) | ||
403 | { | ||
404 | struct usb_serial_port *port = tty->driver_data; | ||
405 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | ||
406 | |||
407 | dbg("%s cmd 0x%04x", __func__, cmd); | ||
408 | |||
409 | switch (cmd) { | ||
410 | case TIOCGSERIAL: | ||
411 | return get_serial_info(port, | ||
412 | (struct serial_struct __user *) arg); | ||
413 | |||
414 | case TIOCMIWAIT: | ||
415 | while (priv != NULL) { | ||
416 | u8 prevMSR = priv->shadowMSR & SERIAL_MSR_MASK; | ||
417 | interruptible_sleep_on(&priv->delta_msr_wait); | ||
418 | /* see if a signal did it */ | ||
419 | if (signal_pending(current)) | ||
420 | return -ERESTARTSYS; | ||
421 | else { | ||
422 | u8 diff = (priv->shadowMSR & SERIAL_MSR_MASK) ^ prevMSR; | ||
423 | if (!diff) | ||
424 | return -EIO; /* no change => error */ | ||
425 | |||
426 | /* Return 0 if caller wanted to know about | ||
427 | these bits */ | ||
428 | |||
429 | if (((arg & TIOCM_RNG) && (diff & SERIAL_MSR_RI)) || | ||
430 | ((arg & TIOCM_DSR) && (diff & SERIAL_MSR_DSR)) || | ||
431 | ((arg & TIOCM_CD) && (diff & SERIAL_MSR_CD)) || | ||
432 | ((arg & TIOCM_CTS) && (diff & SERIAL_MSR_CTS))) | ||
433 | return 0; | ||
434 | } | ||
435 | } | ||
436 | return 0; | ||
437 | |||
438 | default: | ||
439 | break; | ||
440 | } | ||
441 | |||
442 | dbg("%s arg not supported", __func__); | ||
443 | |||
444 | return -ENOIOCTLCMD; | ||
445 | } | ||
446 | |||
447 | static void ssu100_set_max_packet_size(struct usb_serial_port *port) | ||
448 | { | ||
449 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | ||
450 | struct usb_serial *serial = port->serial; | ||
451 | struct usb_device *udev = serial->dev; | ||
452 | |||
453 | struct usb_interface *interface = serial->interface; | ||
454 | struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc; | ||
455 | |||
456 | unsigned num_endpoints; | ||
457 | int i; | ||
458 | |||
459 | num_endpoints = interface->cur_altsetting->desc.bNumEndpoints; | ||
460 | dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints); | ||
461 | |||
462 | for (i = 0; i < num_endpoints; i++) { | ||
463 | dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1, | ||
464 | interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize); | ||
465 | ep_desc = &interface->cur_altsetting->endpoint[i].desc; | ||
466 | } | ||
467 | |||
468 | /* set max packet size based on descriptor */ | ||
469 | priv->max_packet_size = ep_desc->wMaxPacketSize; | ||
470 | |||
471 | dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size); | ||
472 | } | ||
473 | |||
474 | static int ssu100_attach(struct usb_serial *serial) | ||
475 | { | ||
476 | struct ssu100_port_private *priv; | ||
477 | struct usb_serial_port *port = *serial->port; | ||
478 | |||
479 | dbg("%s", __func__); | ||
480 | |||
481 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
482 | if (!priv) { | ||
483 | dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, | ||
484 | sizeof(*priv)); | ||
485 | return -ENOMEM; | ||
486 | } | ||
487 | |||
488 | init_waitqueue_head(&priv->delta_msr_wait); | ||
489 | usb_set_serial_port_data(port, priv); | ||
490 | |||
491 | ssu100_set_max_packet_size(port); | ||
492 | |||
493 | return ssu100_initdevice(serial->dev); | ||
494 | } | ||
495 | |||
496 | static int ssu100_tiocmget(struct tty_struct *tty, struct file *file) | ||
497 | { | ||
498 | struct usb_serial_port *port = tty->driver_data; | ||
499 | struct usb_device *dev = port->serial->dev; | ||
500 | u8 *d; | ||
501 | int r; | ||
502 | |||
503 | dbg("%s\n", __func__); | ||
504 | |||
505 | d = kzalloc(2, GFP_KERNEL); | ||
506 | if (!d) | ||
507 | return -ENOMEM; | ||
508 | |||
509 | r = ssu100_getregister(dev, 0, MODEM_CTL_REGISTER, d); | ||
510 | if (r < 0) | ||
511 | goto mget_out; | ||
512 | |||
513 | r = ssu100_getregister(dev, 0, MODEM_STATUS_REGISTER, d+1); | ||
514 | if (r < 0) | ||
515 | goto mget_out; | ||
516 | |||
517 | r = (d[0] & SERIAL_MCR_DTR ? TIOCM_DTR : 0) | | ||
518 | (d[0] & SERIAL_MCR_RTS ? TIOCM_RTS : 0) | | ||
519 | (d[1] & SERIAL_MSR_CTS ? TIOCM_CTS : 0) | | ||
520 | (d[1] & SERIAL_MSR_CD ? TIOCM_CAR : 0) | | ||
521 | (d[1] & SERIAL_MSR_RI ? TIOCM_RI : 0) | | ||
522 | (d[1] & SERIAL_MSR_DSR ? TIOCM_DSR : 0); | ||
523 | |||
524 | mget_out: | ||
525 | kfree(d); | ||
526 | return r; | ||
527 | } | ||
528 | |||
529 | static int ssu100_tiocmset(struct tty_struct *tty, struct file *file, | ||
530 | unsigned int set, unsigned int clear) | ||
531 | { | ||
532 | struct usb_serial_port *port = tty->driver_data; | ||
533 | struct usb_device *dev = port->serial->dev; | ||
534 | |||
535 | dbg("%s\n", __func__); | ||
536 | return update_mctrl(dev, set, clear); | ||
537 | } | ||
538 | |||
539 | static void ssu100_dtr_rts(struct usb_serial_port *port, int on) | ||
540 | { | ||
541 | struct usb_device *dev = port->serial->dev; | ||
542 | |||
543 | dbg("%s\n", __func__); | ||
544 | |||
545 | mutex_lock(&port->serial->disc_mutex); | ||
546 | if (!port->serial->disconnected) { | ||
547 | /* Disable flow control */ | ||
548 | if (!on && | ||
549 | ssu100_setregister(dev, 0, 0) < 0) | ||
550 | dev_err(&port->dev, "error from flowcontrol urb\n"); | ||
551 | /* drop RTS and DTR */ | ||
552 | if (on) | ||
553 | set_mctrl(dev, TIOCM_DTR | TIOCM_RTS); | ||
554 | else | ||
555 | clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS); | ||
556 | } | ||
557 | mutex_unlock(&port->serial->disc_mutex); | ||
558 | } | ||
559 | |||
560 | static int ssu100_process_packet(struct tty_struct *tty, | ||
561 | struct usb_serial_port *port, | ||
562 | struct ssu100_port_private *priv, | ||
563 | char *packet, int len) | ||
564 | { | ||
565 | int i; | ||
566 | char flag; | ||
567 | char *ch; | ||
568 | |||
569 | dbg("%s - port %d", __func__, port->number); | ||
570 | |||
571 | if (len < 4) { | ||
572 | dbg("%s - malformed packet", __func__); | ||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | if ((packet[0] == 0x1b) && (packet[1] == 0x1b) && | ||
577 | ((packet[2] == 0x00) || (packet[2] == 0x01))) { | ||
578 | if (packet[2] == 0x00) | ||
579 | priv->shadowLSR = packet[3] & (SERIAL_LSR_OE | | ||
580 | SERIAL_LSR_PE | | ||
581 | SERIAL_LSR_FE | | ||
582 | SERIAL_LSR_BI); | ||
583 | |||
584 | if (packet[2] == 0x01) { | ||
585 | priv->shadowMSR = packet[3]; | ||
586 | wake_up_interruptible(&priv->delta_msr_wait); | ||
587 | } | ||
588 | |||
589 | len -= 4; | ||
590 | ch = packet + 4; | ||
591 | } else | ||
592 | ch = packet; | ||
593 | |||
594 | if (!len) | ||
595 | return 0; /* status only */ | ||
596 | |||
597 | if (port->port.console && port->sysrq) { | ||
598 | for (i = 0; i < len; i++, ch++) { | ||
599 | if (!usb_serial_handle_sysrq_char(tty, port, *ch)) | ||
600 | tty_insert_flip_char(tty, *ch, flag); | ||
601 | } | ||
602 | } else | ||
603 | tty_insert_flip_string_fixed_flag(tty, ch, flag, len); | ||
604 | |||
605 | return len; | ||
606 | } | ||
607 | |||
608 | static void ssu100_process_read_urb(struct urb *urb) | ||
609 | { | ||
610 | struct usb_serial_port *port = urb->context; | ||
611 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | ||
612 | char *data = (char *)urb->transfer_buffer; | ||
613 | struct tty_struct *tty; | ||
614 | int count = 0; | ||
615 | int i; | ||
616 | int len; | ||
617 | |||
618 | dbg("%s", __func__); | ||
619 | |||
620 | tty = tty_port_tty_get(&port->port); | ||
621 | if (!tty) | ||
622 | return; | ||
623 | |||
624 | for (i = 0; i < urb->actual_length; i += priv->max_packet_size) { | ||
625 | len = min_t(int, urb->actual_length - i, priv->max_packet_size); | ||
626 | count += ssu100_process_packet(tty, port, priv, &data[i], len); | ||
627 | } | ||
628 | |||
629 | if (count) | ||
630 | tty_flip_buffer_push(tty); | ||
631 | tty_kref_put(tty); | ||
632 | } | ||
633 | |||
634 | |||
635 | static struct usb_serial_driver ssu100_device = { | ||
636 | .driver = { | ||
637 | .owner = THIS_MODULE, | ||
638 | .name = "ssu100", | ||
639 | }, | ||
640 | .description = DRIVER_DESC, | ||
641 | .id_table = id_table, | ||
642 | .usb_driver = &ssu100_driver, | ||
643 | .num_ports = 1, | ||
644 | .bulk_in_size = 256, | ||
645 | .bulk_out_size = 256, | ||
646 | .open = ssu100_open, | ||
647 | .close = ssu100_close, | ||
648 | .attach = ssu100_attach, | ||
649 | .release = ssu100_release, | ||
650 | .dtr_rts = ssu100_dtr_rts, | ||
651 | .process_read_urb = ssu100_process_read_urb, | ||
652 | .tiocmget = ssu100_tiocmget, | ||
653 | .tiocmset = ssu100_tiocmset, | ||
654 | .ioctl = ssu100_ioctl, | ||
655 | .set_termios = ssu100_set_termios, | ||
656 | }; | ||
657 | |||
658 | static int __init ssu100_init(void) | ||
659 | { | ||
660 | int retval; | ||
661 | |||
662 | dbg("%s", __func__); | ||
663 | |||
664 | /* register with usb-serial */ | ||
665 | retval = usb_serial_register(&ssu100_device); | ||
666 | |||
667 | if (retval) | ||
668 | goto failed_usb_sio_register; | ||
669 | |||
670 | retval = usb_register(&ssu100_driver); | ||
671 | if (retval) | ||
672 | goto failed_usb_register; | ||
673 | |||
674 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
675 | DRIVER_DESC "\n"); | ||
676 | |||
677 | return 0; | ||
678 | |||
679 | failed_usb_register: | ||
680 | usb_serial_deregister(&ssu100_device); | ||
681 | failed_usb_sio_register: | ||
682 | return retval; | ||
683 | } | ||
684 | |||
685 | static void __exit ssu100_exit(void) | ||
686 | { | ||
687 | usb_deregister(&ssu100_driver); | ||
688 | usb_serial_deregister(&ssu100_device); | ||
689 | } | ||
690 | |||
691 | module_init(ssu100_init); | ||
692 | module_exit(ssu100_exit); | ||
693 | |||
694 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
695 | MODULE_LICENSE("GPL"); | ||
696 | |||
697 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
698 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 941c2d409f85..2a982e62963b 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -653,6 +653,7 @@ exit: | |||
653 | return id; | 653 | return id; |
654 | } | 654 | } |
655 | 655 | ||
656 | /* Caller must hold table_lock */ | ||
656 | static struct usb_serial_driver *search_serial_device( | 657 | static struct usb_serial_driver *search_serial_device( |
657 | struct usb_interface *iface) | 658 | struct usb_interface *iface) |
658 | { | 659 | { |
@@ -718,17 +719,23 @@ int usb_serial_probe(struct usb_interface *interface, | |||
718 | int num_ports = 0; | 719 | int num_ports = 0; |
719 | int max_endpoints; | 720 | int max_endpoints; |
720 | 721 | ||
721 | lock_kernel(); /* guard against unloading a serial driver module */ | 722 | mutex_lock(&table_lock); |
722 | type = search_serial_device(interface); | 723 | type = search_serial_device(interface); |
723 | if (!type) { | 724 | if (!type) { |
724 | unlock_kernel(); | 725 | mutex_unlock(&table_lock); |
725 | dbg("none matched"); | 726 | dbg("none matched"); |
726 | return -ENODEV; | 727 | return -ENODEV; |
727 | } | 728 | } |
728 | 729 | ||
730 | if (!try_module_get(type->driver.owner)) { | ||
731 | mutex_unlock(&table_lock); | ||
732 | dev_err(&interface->dev, "module get failed, exiting\n"); | ||
733 | return -EIO; | ||
734 | } | ||
735 | mutex_unlock(&table_lock); | ||
736 | |||
729 | serial = create_serial(dev, interface, type); | 737 | serial = create_serial(dev, interface, type); |
730 | if (!serial) { | 738 | if (!serial) { |
731 | unlock_kernel(); | ||
732 | dev_err(&interface->dev, "%s - out of memory\n", __func__); | 739 | dev_err(&interface->dev, "%s - out of memory\n", __func__); |
733 | return -ENOMEM; | 740 | return -ENOMEM; |
734 | } | 741 | } |
@@ -737,20 +744,11 @@ int usb_serial_probe(struct usb_interface *interface, | |||
737 | if (type->probe) { | 744 | if (type->probe) { |
738 | const struct usb_device_id *id; | 745 | const struct usb_device_id *id; |
739 | 746 | ||
740 | if (!try_module_get(type->driver.owner)) { | ||
741 | unlock_kernel(); | ||
742 | dev_err(&interface->dev, | ||
743 | "module get failed, exiting\n"); | ||
744 | kfree(serial); | ||
745 | return -EIO; | ||
746 | } | ||
747 | |||
748 | id = get_iface_id(type, interface); | 747 | id = get_iface_id(type, interface); |
749 | retval = type->probe(serial, id); | 748 | retval = type->probe(serial, id); |
750 | module_put(type->driver.owner); | 749 | module_put(type->driver.owner); |
751 | 750 | ||
752 | if (retval) { | 751 | if (retval) { |
753 | unlock_kernel(); | ||
754 | dbg("sub driver rejected device"); | 752 | dbg("sub driver rejected device"); |
755 | kfree(serial); | 753 | kfree(serial); |
756 | return retval; | 754 | return retval; |
@@ -822,7 +820,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
822 | * properly during a later invocation of usb_serial_probe | 820 | * properly during a later invocation of usb_serial_probe |
823 | */ | 821 | */ |
824 | if (num_bulk_in == 0 || num_bulk_out == 0) { | 822 | if (num_bulk_in == 0 || num_bulk_out == 0) { |
825 | unlock_kernel(); | ||
826 | dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); | 823 | dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); |
827 | kfree(serial); | 824 | kfree(serial); |
828 | return -ENODEV; | 825 | return -ENODEV; |
@@ -835,7 +832,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
835 | if (type == &usb_serial_generic_device) { | 832 | if (type == &usb_serial_generic_device) { |
836 | num_ports = num_bulk_out; | 833 | num_ports = num_bulk_out; |
837 | if (num_ports == 0) { | 834 | if (num_ports == 0) { |
838 | unlock_kernel(); | ||
839 | dev_err(&interface->dev, | 835 | dev_err(&interface->dev, |
840 | "Generic device with no bulk out, not allowed.\n"); | 836 | "Generic device with no bulk out, not allowed.\n"); |
841 | kfree(serial); | 837 | kfree(serial); |
@@ -847,7 +843,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
847 | /* if this device type has a calc_num_ports function, call it */ | 843 | /* if this device type has a calc_num_ports function, call it */ |
848 | if (type->calc_num_ports) { | 844 | if (type->calc_num_ports) { |
849 | if (!try_module_get(type->driver.owner)) { | 845 | if (!try_module_get(type->driver.owner)) { |
850 | unlock_kernel(); | ||
851 | dev_err(&interface->dev, | 846 | dev_err(&interface->dev, |
852 | "module get failed, exiting\n"); | 847 | "module get failed, exiting\n"); |
853 | kfree(serial); | 848 | kfree(serial); |
@@ -878,7 +873,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
878 | max_endpoints = max(max_endpoints, num_interrupt_out); | 873 | max_endpoints = max(max_endpoints, num_interrupt_out); |
879 | max_endpoints = max(max_endpoints, (int)serial->num_ports); | 874 | max_endpoints = max(max_endpoints, (int)serial->num_ports); |
880 | serial->num_port_pointers = max_endpoints; | 875 | serial->num_port_pointers = max_endpoints; |
881 | unlock_kernel(); | ||
882 | 876 | ||
883 | dbg("%s - setting up %d port structures for this device", | 877 | dbg("%s - setting up %d port structures for this device", |
884 | __func__, max_endpoints); | 878 | __func__, max_endpoints); |
@@ -1077,6 +1071,8 @@ int usb_serial_probe(struct usb_interface *interface, | |||
1077 | dev_set_name(&port->dev, "ttyUSB%d", port->number); | 1071 | dev_set_name(&port->dev, "ttyUSB%d", port->number); |
1078 | dbg ("%s - registering %s", __func__, dev_name(&port->dev)); | 1072 | dbg ("%s - registering %s", __func__, dev_name(&port->dev)); |
1079 | port->dev_state = PORT_REGISTERING; | 1073 | port->dev_state = PORT_REGISTERING; |
1074 | device_enable_async_suspend(&port->dev); | ||
1075 | |||
1080 | retval = device_add(&port->dev); | 1076 | retval = device_add(&port->dev); |
1081 | if (retval) { | 1077 | if (retval) { |
1082 | dev_err(&port->dev, "Error registering port device, " | 1078 | dev_err(&port->dev, "Error registering port device, " |
@@ -1349,6 +1345,7 @@ int usb_serial_register(struct usb_serial_driver *driver) | |||
1349 | driver->description = driver->driver.name; | 1345 | driver->description = driver->driver.name; |
1350 | 1346 | ||
1351 | /* Add this device to our list of devices */ | 1347 | /* Add this device to our list of devices */ |
1348 | mutex_lock(&table_lock); | ||
1352 | list_add(&driver->driver_list, &usb_serial_driver_list); | 1349 | list_add(&driver->driver_list, &usb_serial_driver_list); |
1353 | 1350 | ||
1354 | retval = usb_serial_bus_register(driver); | 1351 | retval = usb_serial_bus_register(driver); |
@@ -1360,6 +1357,7 @@ int usb_serial_register(struct usb_serial_driver *driver) | |||
1360 | printk(KERN_INFO "USB Serial support registered for %s\n", | 1357 | printk(KERN_INFO "USB Serial support registered for %s\n", |
1361 | driver->description); | 1358 | driver->description); |
1362 | 1359 | ||
1360 | mutex_unlock(&table_lock); | ||
1363 | return retval; | 1361 | return retval; |
1364 | } | 1362 | } |
1365 | EXPORT_SYMBOL_GPL(usb_serial_register); | 1363 | EXPORT_SYMBOL_GPL(usb_serial_register); |
@@ -1370,8 +1368,10 @@ void usb_serial_deregister(struct usb_serial_driver *device) | |||
1370 | /* must be called with BKL held */ | 1368 | /* must be called with BKL held */ |
1371 | printk(KERN_INFO "USB Serial deregistering driver %s\n", | 1369 | printk(KERN_INFO "USB Serial deregistering driver %s\n", |
1372 | device->description); | 1370 | device->description); |
1371 | mutex_lock(&table_lock); | ||
1373 | list_del(&device->driver_list); | 1372 | list_del(&device->driver_list); |
1374 | usb_serial_bus_deregister(device); | 1373 | usb_serial_bus_deregister(device); |
1374 | mutex_unlock(&table_lock); | ||
1375 | } | 1375 | } |
1376 | EXPORT_SYMBOL_GPL(usb_serial_deregister); | 1376 | EXPORT_SYMBOL_GPL(usb_serial_deregister); |
1377 | 1377 | ||
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 54cc94277acb..6542ca40d505 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c | |||
@@ -269,7 +269,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
269 | /* The firmware will time-out commands after 20 seconds. Some commands | 269 | /* The firmware will time-out commands after 20 seconds. Some commands |
270 | * can legitimately take longer than this, so we use a different | 270 | * can legitimately take longer than this, so we use a different |
271 | * command that only waits for the interrupt and then sends status, | 271 | * command that only waits for the interrupt and then sends status, |
272 | * without having to send a new ATAPI command to the device. | 272 | * without having to send a new ATAPI command to the device. |
273 | * | 273 | * |
274 | * NOTE: There is some indication that a data transfer after a timeout | 274 | * NOTE: There is some indication that a data transfer after a timeout |
275 | * may not work, but that is a condition that should never happen. | 275 | * may not work, but that is a condition that should never happen. |
@@ -324,14 +324,14 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
324 | 324 | ||
325 | /* Find the length we desire to read. */ | 325 | /* Find the length we desire to read. */ |
326 | switch (srb->cmnd[0]) { | 326 | switch (srb->cmnd[0]) { |
327 | case INQUIRY: | 327 | case INQUIRY: |
328 | case REQUEST_SENSE: /* 16 or 18 bytes? spec says 18, lots of devices only have 16 */ | 328 | case REQUEST_SENSE: /* 16 or 18 bytes? spec says 18, lots of devices only have 16 */ |
329 | case MODE_SENSE: | 329 | case MODE_SENSE: |
330 | case MODE_SENSE_10: | 330 | case MODE_SENSE_10: |
331 | length = le16_to_cpu(fst->Count); | 331 | length = le16_to_cpu(fst->Count); |
332 | break; | 332 | break; |
333 | default: | 333 | default: |
334 | length = scsi_bufflen(srb); | 334 | length = scsi_bufflen(srb); |
335 | } | 335 | } |
336 | 336 | ||
337 | /* verify that this amount is legal */ | 337 | /* verify that this amount is legal */ |
@@ -414,7 +414,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
414 | /* should never hit here -- filtered in usb.c */ | 414 | /* should never hit here -- filtered in usb.c */ |
415 | US_DEBUGP ("freecom unimplemented direction: %d\n", | 415 | US_DEBUGP ("freecom unimplemented direction: %d\n", |
416 | us->srb->sc_data_direction); | 416 | us->srb->sc_data_direction); |
417 | // Return fail, SCSI seems to handle this better. | 417 | /* Return fail, SCSI seems to handle this better. */ |
418 | return USB_STOR_TRANSPORT_FAILED; | 418 | return USB_STOR_TRANSPORT_FAILED; |
419 | break; | 419 | break; |
420 | } | 420 | } |
@@ -494,8 +494,7 @@ static void pdump (void *ibuffer, int length) | |||
494 | offset = 0; | 494 | offset = 0; |
495 | } | 495 | } |
496 | offset += sprintf (line+offset, "%08x:", i); | 496 | offset += sprintf (line+offset, "%08x:", i); |
497 | } | 497 | } else if ((i & 7) == 0) { |
498 | else if ((i & 7) == 0) { | ||
499 | offset += sprintf (line+offset, " -"); | 498 | offset += sprintf (line+offset, " -"); |
500 | } | 499 | } |
501 | offset += sprintf (line+offset, " %02x", buffer[i] & 0xff); | 500 | offset += sprintf (line+offset, " %02x", buffer[i] & 0xff); |
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index e9cbc1467f76..6b9982cd5423 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c | |||
@@ -1456,8 +1456,7 @@ static int isd200_init_info(struct us_data *us) | |||
1456 | int retStatus = ISD200_GOOD; | 1456 | int retStatus = ISD200_GOOD; |
1457 | struct isd200_info *info; | 1457 | struct isd200_info *info; |
1458 | 1458 | ||
1459 | info = (struct isd200_info *) | 1459 | info = kzalloc(sizeof(struct isd200_info), GFP_KERNEL); |
1460 | kzalloc(sizeof(struct isd200_info), GFP_KERNEL); | ||
1461 | if (!info) | 1460 | if (!info) |
1462 | retStatus = ISD200_ERROR; | 1461 | retStatus = ISD200_ERROR; |
1463 | else { | 1462 | else { |
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index a7d0bf9d92a7..90bb0175a152 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
@@ -336,6 +336,7 @@ static int usb_stor_control_thread(void * __us) | |||
336 | else { | 336 | else { |
337 | US_DEBUG(usb_stor_show_command(us->srb)); | 337 | US_DEBUG(usb_stor_show_command(us->srb)); |
338 | us->proto_handler(us->srb, us); | 338 | us->proto_handler(us->srb, us); |
339 | usb_mark_last_busy(us->pusb_dev); | ||
339 | } | 340 | } |
340 | 341 | ||
341 | /* lock access to the state */ | 342 | /* lock access to the state */ |
@@ -845,6 +846,7 @@ static int usb_stor_scan_thread(void * __us) | |||
845 | /* Should we unbind if no devices were detected? */ | 846 | /* Should we unbind if no devices were detected? */ |
846 | } | 847 | } |
847 | 848 | ||
849 | usb_autopm_put_interface(us->pusb_intf); | ||
848 | complete_and_exit(&us->scanning_done, 0); | 850 | complete_and_exit(&us->scanning_done, 0); |
849 | } | 851 | } |
850 | 852 | ||
@@ -968,6 +970,7 @@ int usb_stor_probe2(struct us_data *us) | |||
968 | goto BadDevice; | 970 | goto BadDevice; |
969 | } | 971 | } |
970 | 972 | ||
973 | usb_autopm_get_interface_no_resume(us->pusb_intf); | ||
971 | wake_up_process(th); | 974 | wake_up_process(th); |
972 | 975 | ||
973 | return 0; | 976 | return 0; |
@@ -1040,6 +1043,7 @@ static struct usb_driver usb_storage_driver = { | |||
1040 | .pre_reset = usb_stor_pre_reset, | 1043 | .pre_reset = usb_stor_pre_reset, |
1041 | .post_reset = usb_stor_post_reset, | 1044 | .post_reset = usb_stor_post_reset, |
1042 | .id_table = usb_storage_usb_ids, | 1045 | .id_table = usb_storage_usb_ids, |
1046 | .supports_autosuspend = 1, | ||
1043 | .soft_unbind = 1, | 1047 | .soft_unbind = 1, |
1044 | }; | 1048 | }; |
1045 | 1049 | ||
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index d110588b56f1..552679b8dbd1 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c | |||
@@ -142,7 +142,7 @@ static int skel_release(struct inode *inode, struct file *file) | |||
142 | { | 142 | { |
143 | struct usb_skel *dev; | 143 | struct usb_skel *dev; |
144 | 144 | ||
145 | dev = (struct usb_skel *)file->private_data; | 145 | dev = file->private_data; |
146 | if (dev == NULL) | 146 | if (dev == NULL) |
147 | return -ENODEV; | 147 | return -ENODEV; |
148 | 148 | ||
@@ -162,7 +162,7 @@ static int skel_flush(struct file *file, fl_owner_t id) | |||
162 | struct usb_skel *dev; | 162 | struct usb_skel *dev; |
163 | int res; | 163 | int res; |
164 | 164 | ||
165 | dev = (struct usb_skel *)file->private_data; | 165 | dev = file->private_data; |
166 | if (dev == NULL) | 166 | if (dev == NULL) |
167 | return -ENODEV; | 167 | return -ENODEV; |
168 | 168 | ||
@@ -246,7 +246,7 @@ static ssize_t skel_read(struct file *file, char *buffer, size_t count, | |||
246 | int rv; | 246 | int rv; |
247 | bool ongoing_io; | 247 | bool ongoing_io; |
248 | 248 | ||
249 | dev = (struct usb_skel *)file->private_data; | 249 | dev = file->private_data; |
250 | 250 | ||
251 | /* if we cannot read at all, return EOF */ | 251 | /* if we cannot read at all, return EOF */ |
252 | if (!dev->bulk_in_urb || !count) | 252 | if (!dev->bulk_in_urb || !count) |
@@ -401,7 +401,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, | |||
401 | char *buf = NULL; | 401 | char *buf = NULL; |
402 | size_t writesize = min(count, (size_t)MAX_TRANSFER); | 402 | size_t writesize = min(count, (size_t)MAX_TRANSFER); |
403 | 403 | ||
404 | dev = (struct usb_skel *)file->private_data; | 404 | dev = file->private_data; |
405 | 405 | ||
406 | /* verify that we actually have some data to write */ | 406 | /* verify that we actually have some data to write */ |
407 | if (count == 0) | 407 | if (count == 0) |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 3b3f5749af92..26bf7cbfecc2 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -283,7 +283,8 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) | |||
283 | struct fbcon_ops *ops = info->fbcon_par; | 283 | struct fbcon_ops *ops = info->fbcon_par; |
284 | 284 | ||
285 | return (info->state != FBINFO_STATE_RUNNING || | 285 | return (info->state != FBINFO_STATE_RUNNING || |
286 | vc->vc_mode != KD_TEXT || ops->graphics); | 286 | vc->vc_mode != KD_TEXT || ops->graphics) && |
287 | !vt_force_oops_output(vc); | ||
287 | } | 288 | } |
288 | 289 | ||
289 | static inline int get_color(struct vc_data *vc, struct fb_info *info, | 290 | static inline int get_color(struct vc_data *vc, struct fb_info *info, |
@@ -1073,6 +1074,7 @@ static void fbcon_init(struct vc_data *vc, int init) | |||
1073 | if (p->userfont) | 1074 | if (p->userfont) |
1074 | charcnt = FNTCHARCNT(p->fontdata); | 1075 | charcnt = FNTCHARCNT(p->fontdata); |
1075 | 1076 | ||
1077 | vc->vc_panic_force_write = !!(info->flags & FBINFO_CAN_FORCE_OUTPUT); | ||
1076 | vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); | 1078 | vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); |
1077 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; | 1079 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; |
1078 | if (charcnt == 256) { | 1080 | if (charcnt == 256) { |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 182dd6f8aadd..54e32c513610 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
@@ -1108,7 +1108,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) | |||
1108 | charmap += 4 * cmapsz; | 1108 | charmap += 4 * cmapsz; |
1109 | #endif | 1109 | #endif |
1110 | 1110 | ||
1111 | unlock_kernel(); | ||
1112 | spin_lock_irq(&vga_lock); | 1111 | spin_lock_irq(&vga_lock); |
1113 | /* First, the Sequencer */ | 1112 | /* First, the Sequencer */ |
1114 | vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); | 1113 | vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); |
@@ -1192,7 +1191,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) | |||
1192 | vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); | 1191 | vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); |
1193 | } | 1192 | } |
1194 | spin_unlock_irq(&vga_lock); | 1193 | spin_unlock_irq(&vga_lock); |
1195 | lock_kernel(); | ||
1196 | return 0; | 1194 | return 0; |
1197 | } | 1195 | } |
1198 | 1196 | ||
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index e66b8b19ce5d..d8b12c32e3ef 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c | |||
@@ -858,9 +858,9 @@ unsigned long w100fb_gpio_read(int port) | |||
858 | void w100fb_gpio_write(int port, unsigned long value) | 858 | void w100fb_gpio_write(int port, unsigned long value) |
859 | { | 859 | { |
860 | if (port==W100_GPIO_PORT_A) | 860 | if (port==W100_GPIO_PORT_A) |
861 | value = writel(value, remapped_regs + mmGPIO_DATA); | 861 | writel(value, remapped_regs + mmGPIO_DATA); |
862 | else | 862 | else |
863 | value = writel(value, remapped_regs + mmGPIO_DATA2); | 863 | writel(value, remapped_regs + mmGPIO_DATA2); |
864 | } | 864 | } |
865 | EXPORT_SYMBOL(w100fb_gpio_read); | 865 | EXPORT_SYMBOL(w100fb_gpio_read); |
866 | EXPORT_SYMBOL(w100fb_gpio_write); | 866 | EXPORT_SYMBOL(w100fb_gpio_write); |
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b04b18468932..4d2992aadfb7 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -73,6 +73,13 @@ config WM8350_WATCHDOG | |||
73 | 73 | ||
74 | # ARM Architecture | 74 | # ARM Architecture |
75 | 75 | ||
76 | config ARM_SP805_WATCHDOG | ||
77 | tristate "ARM SP805 Watchdog" | ||
78 | depends on ARM_AMBA | ||
79 | help | ||
80 | ARM Primecell SP805 Watchdog timer. This will reboot your system when | ||
81 | the timeout is reached. | ||
82 | |||
76 | config AT91RM9200_WATCHDOG | 83 | config AT91RM9200_WATCHDOG |
77 | tristate "AT91RM9200 watchdog" | 84 | tristate "AT91RM9200 watchdog" |
78 | depends on ARCH_AT91RM9200 | 85 | depends on ARCH_AT91RM9200 |
@@ -401,6 +408,17 @@ config ALIM7101_WDT | |||
401 | 408 | ||
402 | Most people will say N. | 409 | Most people will say N. |
403 | 410 | ||
411 | config F71808E_WDT | ||
412 | tristate "Fintek F71808E and F71882FG Watchdog" | ||
413 | depends on X86 && EXPERIMENTAL | ||
414 | help | ||
415 | This is the driver for the hardware watchdog on the Fintek | ||
416 | F71808E and F71882FG Super I/O controllers. | ||
417 | |||
418 | You can compile this driver directly into the kernel, or use | ||
419 | it as a module. The module will be called f71808e_wdt. | ||
420 | |||
421 | |||
404 | config GEODE_WDT | 422 | config GEODE_WDT |
405 | tristate "AMD Geode CS5535/CS5536 Watchdog" | 423 | tristate "AMD Geode CS5535/CS5536 Watchdog" |
406 | depends on CS5535_MFGPT | 424 | depends on CS5535_MFGPT |
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index e30289a5e367..8374503fcc6a 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
@@ -25,6 +25,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o | |||
25 | # ALPHA Architecture | 25 | # ALPHA Architecture |
26 | 26 | ||
27 | # ARM Architecture | 27 | # ARM Architecture |
28 | obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o | ||
28 | obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o | 29 | obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o |
29 | obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o | 30 | obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o |
30 | obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o | 31 | obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o |
@@ -66,6 +67,7 @@ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o | |||
66 | obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o | 67 | obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o |
67 | obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o | 68 | obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o |
68 | obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o | 69 | obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o |
70 | obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o | ||
69 | obj-$(CONFIG_GEODE_WDT) += geodewdt.o | 71 | obj-$(CONFIG_GEODE_WDT) += geodewdt.o |
70 | obj-$(CONFIG_SC520_WDT) += sc520_wdt.o | 72 | obj-$(CONFIG_SC520_WDT) += sc520_wdt.o |
71 | obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o | 73 | obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o |
diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c new file mode 100644 index 000000000000..7e5c266cda48 --- /dev/null +++ b/drivers/watchdog/f71808e_wdt.c | |||
@@ -0,0 +1,768 @@ | |||
1 | /*************************************************************************** | ||
2 | * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> * | ||
3 | * Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com> * | ||
4 | * Copyright (C) 2010 Giel van Schijndel <me@mortis.eu> * | ||
5 | * * | ||
6 | * This program is free software; you can redistribute it and/or modify * | ||
7 | * it under the terms of the GNU General Public License as published by * | ||
8 | * the Free Software Foundation; either version 2 of the License, or * | ||
9 | * (at your option) any later version. * | ||
10 | * * | ||
11 | * This program is distributed in the hope that it will be useful, * | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
14 | * GNU General Public License for more details. * | ||
15 | * * | ||
16 | * You should have received a copy of the GNU General Public License * | ||
17 | * along with this program; if not, write to the * | ||
18 | * Free Software Foundation, Inc., * | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
20 | ***************************************************************************/ | ||
21 | |||
22 | #include <linux/err.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/ioport.h> | ||
27 | #include <linux/miscdevice.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/mutex.h> | ||
30 | #include <linux/notifier.h> | ||
31 | #include <linux/reboot.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | #include <linux/watchdog.h> | ||
34 | |||
35 | #define DRVNAME "f71808e_wdt" | ||
36 | |||
37 | #define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */ | ||
38 | #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ | ||
39 | #define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ | ||
40 | |||
41 | #define SIO_REG_LDSEL 0x07 /* Logical device select */ | ||
42 | #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ | ||
43 | #define SIO_REG_DEVREV 0x22 /* Device revision */ | ||
44 | #define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ | ||
45 | #define SIO_REG_ENABLE 0x30 /* Logical device enable */ | ||
46 | #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ | ||
47 | |||
48 | #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ | ||
49 | #define SIO_F71808_ID 0x0901 /* Chipset ID */ | ||
50 | #define SIO_F71858_ID 0x0507 /* Chipset ID */ | ||
51 | #define SIO_F71862_ID 0x0601 /* Chipset ID */ | ||
52 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ | ||
53 | #define SIO_F71889_ID 0x0723 /* Chipset ID */ | ||
54 | |||
55 | #define F71882FG_REG_START 0x01 | ||
56 | |||
57 | #define F71808FG_REG_WDO_CONF 0xf0 | ||
58 | #define F71808FG_REG_WDT_CONF 0xf5 | ||
59 | #define F71808FG_REG_WD_TIME 0xf6 | ||
60 | |||
61 | #define F71808FG_FLAG_WDOUT_EN 7 | ||
62 | |||
63 | #define F71808FG_FLAG_WDTMOUT_STS 5 | ||
64 | #define F71808FG_FLAG_WD_EN 5 | ||
65 | #define F71808FG_FLAG_WD_PULSE 4 | ||
66 | #define F71808FG_FLAG_WD_UNIT 3 | ||
67 | |||
68 | /* Default values */ | ||
69 | #define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */ | ||
70 | #define WATCHDOG_MAX_TIMEOUT (60 * 255) | ||
71 | #define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for | ||
72 | watchdog signal */ | ||
73 | |||
74 | static unsigned short force_id; | ||
75 | module_param(force_id, ushort, 0); | ||
76 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); | ||
77 | |||
78 | static const int max_timeout = WATCHDOG_MAX_TIMEOUT; | ||
79 | static int timeout = 60; /* default timeout in seconds */ | ||
80 | module_param(timeout, int, 0); | ||
81 | MODULE_PARM_DESC(timeout, | ||
82 | "Watchdog timeout in seconds. 1<= timeout <=" | ||
83 | __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default=" | ||
84 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
85 | |||
86 | static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH; | ||
87 | module_param(pulse_width, uint, 0); | ||
88 | MODULE_PARM_DESC(pulse_width, | ||
89 | "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" | ||
90 | " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); | ||
91 | |||
92 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
93 | module_param(nowayout, bool, 0444); | ||
94 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); | ||
95 | |||
96 | static unsigned int start_withtimeout; | ||
97 | module_param(start_withtimeout, uint, 0); | ||
98 | MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" | ||
99 | " given initial timeout. Zero (default) disables this feature."); | ||
100 | |||
101 | enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg }; | ||
102 | |||
103 | static const char *f71808e_names[] = { | ||
104 | "f71808fg", | ||
105 | "f71858fg", | ||
106 | "f71862fg", | ||
107 | "f71882fg", | ||
108 | "f71889fg", | ||
109 | }; | ||
110 | |||
111 | /* Super-I/O Function prototypes */ | ||
112 | static inline int superio_inb(int base, int reg); | ||
113 | static inline int superio_inw(int base, int reg); | ||
114 | static inline void superio_outb(int base, int reg, u8 val); | ||
115 | static inline void superio_set_bit(int base, int reg, int bit); | ||
116 | static inline void superio_clear_bit(int base, int reg, int bit); | ||
117 | static inline int superio_enter(int base); | ||
118 | static inline void superio_select(int base, int ld); | ||
119 | static inline void superio_exit(int base); | ||
120 | |||
121 | struct watchdog_data { | ||
122 | unsigned short sioaddr; | ||
123 | enum chips type; | ||
124 | unsigned long opened; | ||
125 | struct mutex lock; | ||
126 | char expect_close; | ||
127 | struct watchdog_info ident; | ||
128 | |||
129 | unsigned short timeout; | ||
130 | u8 timer_val; /* content for the wd_time register */ | ||
131 | char minutes_mode; | ||
132 | u8 pulse_val; /* pulse width flag */ | ||
133 | char pulse_mode; /* enable pulse output mode? */ | ||
134 | char caused_reboot; /* last reboot was by the watchdog */ | ||
135 | }; | ||
136 | |||
137 | static struct watchdog_data watchdog = { | ||
138 | .lock = __MUTEX_INITIALIZER(watchdog.lock), | ||
139 | }; | ||
140 | |||
141 | /* Super I/O functions */ | ||
142 | static inline int superio_inb(int base, int reg) | ||
143 | { | ||
144 | outb(reg, base); | ||
145 | return inb(base + 1); | ||
146 | } | ||
147 | |||
148 | static int superio_inw(int base, int reg) | ||
149 | { | ||
150 | int val; | ||
151 | val = superio_inb(base, reg) << 8; | ||
152 | val |= superio_inb(base, reg + 1); | ||
153 | return val; | ||
154 | } | ||
155 | |||
156 | static inline void superio_outb(int base, int reg, u8 val) | ||
157 | { | ||
158 | outb(reg, base); | ||
159 | outb(val, base + 1); | ||
160 | } | ||
161 | |||
162 | static inline void superio_set_bit(int base, int reg, int bit) | ||
163 | { | ||
164 | unsigned long val = superio_inb(base, reg); | ||
165 | __set_bit(bit, &val); | ||
166 | superio_outb(base, reg, val); | ||
167 | } | ||
168 | |||
169 | static inline void superio_clear_bit(int base, int reg, int bit) | ||
170 | { | ||
171 | unsigned long val = superio_inb(base, reg); | ||
172 | __clear_bit(bit, &val); | ||
173 | superio_outb(base, reg, val); | ||
174 | } | ||
175 | |||
176 | static inline int superio_enter(int base) | ||
177 | { | ||
178 | /* Don't step on other drivers' I/O space by accident */ | ||
179 | if (!request_muxed_region(base, 2, DRVNAME)) { | ||
180 | printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", | ||
181 | (int)base); | ||
182 | return -EBUSY; | ||
183 | } | ||
184 | |||
185 | /* according to the datasheet the key must be send twice! */ | ||
186 | outb(SIO_UNLOCK_KEY, base); | ||
187 | outb(SIO_UNLOCK_KEY, base); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static inline void superio_select(int base, int ld) | ||
193 | { | ||
194 | outb(SIO_REG_LDSEL, base); | ||
195 | outb(ld, base + 1); | ||
196 | } | ||
197 | |||
198 | static inline void superio_exit(int base) | ||
199 | { | ||
200 | outb(SIO_LOCK_KEY, base); | ||
201 | release_region(base, 2); | ||
202 | } | ||
203 | |||
204 | static int watchdog_set_timeout(int timeout) | ||
205 | { | ||
206 | if (timeout <= 0 | ||
207 | || timeout > max_timeout) { | ||
208 | printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n"); | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | |||
212 | mutex_lock(&watchdog.lock); | ||
213 | |||
214 | watchdog.timeout = timeout; | ||
215 | if (timeout > 0xff) { | ||
216 | watchdog.timer_val = DIV_ROUND_UP(timeout, 60); | ||
217 | watchdog.minutes_mode = true; | ||
218 | } else { | ||
219 | watchdog.timer_val = timeout; | ||
220 | watchdog.minutes_mode = false; | ||
221 | } | ||
222 | |||
223 | mutex_unlock(&watchdog.lock); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int watchdog_set_pulse_width(unsigned int pw) | ||
229 | { | ||
230 | int err = 0; | ||
231 | |||
232 | mutex_lock(&watchdog.lock); | ||
233 | |||
234 | if (pw <= 1) { | ||
235 | watchdog.pulse_val = 0; | ||
236 | } else if (pw <= 25) { | ||
237 | watchdog.pulse_val = 1; | ||
238 | } else if (pw <= 125) { | ||
239 | watchdog.pulse_val = 2; | ||
240 | } else if (pw <= 5000) { | ||
241 | watchdog.pulse_val = 3; | ||
242 | } else { | ||
243 | printk(KERN_ERR DRVNAME ": pulse width out of range\n"); | ||
244 | err = -EINVAL; | ||
245 | goto exit_unlock; | ||
246 | } | ||
247 | |||
248 | watchdog.pulse_mode = pw; | ||
249 | |||
250 | exit_unlock: | ||
251 | mutex_unlock(&watchdog.lock); | ||
252 | return err; | ||
253 | } | ||
254 | |||
255 | static int watchdog_keepalive(void) | ||
256 | { | ||
257 | int err = 0; | ||
258 | |||
259 | mutex_lock(&watchdog.lock); | ||
260 | err = superio_enter(watchdog.sioaddr); | ||
261 | if (err) | ||
262 | goto exit_unlock; | ||
263 | superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); | ||
264 | |||
265 | if (watchdog.minutes_mode) | ||
266 | /* select minutes for timer units */ | ||
267 | superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, | ||
268 | F71808FG_FLAG_WD_UNIT); | ||
269 | else | ||
270 | /* select seconds for timer units */ | ||
271 | superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, | ||
272 | F71808FG_FLAG_WD_UNIT); | ||
273 | |||
274 | /* Set timer value */ | ||
275 | superio_outb(watchdog.sioaddr, F71808FG_REG_WD_TIME, | ||
276 | watchdog.timer_val); | ||
277 | |||
278 | superio_exit(watchdog.sioaddr); | ||
279 | |||
280 | exit_unlock: | ||
281 | mutex_unlock(&watchdog.lock); | ||
282 | return err; | ||
283 | } | ||
284 | |||
285 | static int watchdog_start(void) | ||
286 | { | ||
287 | /* Make sure we don't die as soon as the watchdog is enabled below */ | ||
288 | int err = watchdog_keepalive(); | ||
289 | if (err) | ||
290 | return err; | ||
291 | |||
292 | mutex_lock(&watchdog.lock); | ||
293 | err = superio_enter(watchdog.sioaddr); | ||
294 | if (err) | ||
295 | goto exit_unlock; | ||
296 | superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); | ||
297 | |||
298 | /* Watchdog pin configuration */ | ||
299 | switch (watchdog.type) { | ||
300 | case f71808fg: | ||
301 | /* Set pin 21 to GPIO23/WDTRST#, then to WDTRST# */ | ||
302 | superio_clear_bit(watchdog.sioaddr, 0x2a, 3); | ||
303 | superio_clear_bit(watchdog.sioaddr, 0x2b, 3); | ||
304 | break; | ||
305 | |||
306 | case f71882fg: | ||
307 | /* Set pin 56 to WDTRST# */ | ||
308 | superio_set_bit(watchdog.sioaddr, 0x29, 1); | ||
309 | break; | ||
310 | |||
311 | default: | ||
312 | /* | ||
313 | * 'default' label to shut up the compiler and catch | ||
314 | * programmer errors | ||
315 | */ | ||
316 | err = -ENODEV; | ||
317 | goto exit_superio; | ||
318 | } | ||
319 | |||
320 | superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); | ||
321 | superio_set_bit(watchdog.sioaddr, SIO_REG_ENABLE, 0); | ||
322 | superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDO_CONF, | ||
323 | F71808FG_FLAG_WDOUT_EN); | ||
324 | |||
325 | superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, | ||
326 | F71808FG_FLAG_WD_EN); | ||
327 | |||
328 | if (watchdog.pulse_mode) { | ||
329 | /* Select "pulse" output mode with given duration */ | ||
330 | u8 wdt_conf = superio_inb(watchdog.sioaddr, | ||
331 | F71808FG_REG_WDT_CONF); | ||
332 | |||
333 | /* Set WD_PSWIDTH bits (1:0) */ | ||
334 | wdt_conf = (wdt_conf & 0xfc) | (watchdog.pulse_val & 0x03); | ||
335 | /* Set WD_PULSE to "pulse" mode */ | ||
336 | wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE); | ||
337 | |||
338 | superio_outb(watchdog.sioaddr, F71808FG_REG_WDT_CONF, | ||
339 | wdt_conf); | ||
340 | } else { | ||
341 | /* Select "level" output mode */ | ||
342 | superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, | ||
343 | F71808FG_FLAG_WD_PULSE); | ||
344 | } | ||
345 | |||
346 | exit_superio: | ||
347 | superio_exit(watchdog.sioaddr); | ||
348 | exit_unlock: | ||
349 | mutex_unlock(&watchdog.lock); | ||
350 | |||
351 | return err; | ||
352 | } | ||
353 | |||
354 | static int watchdog_stop(void) | ||
355 | { | ||
356 | int err = 0; | ||
357 | |||
358 | mutex_lock(&watchdog.lock); | ||
359 | err = superio_enter(watchdog.sioaddr); | ||
360 | if (err) | ||
361 | goto exit_unlock; | ||
362 | superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); | ||
363 | |||
364 | superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, | ||
365 | F71808FG_FLAG_WD_EN); | ||
366 | |||
367 | superio_exit(watchdog.sioaddr); | ||
368 | |||
369 | exit_unlock: | ||
370 | mutex_unlock(&watchdog.lock); | ||
371 | |||
372 | return err; | ||
373 | } | ||
374 | |||
375 | static int watchdog_get_status(void) | ||
376 | { | ||
377 | int status = 0; | ||
378 | |||
379 | mutex_lock(&watchdog.lock); | ||
380 | status = (watchdog.caused_reboot) ? WDIOF_CARDRESET : 0; | ||
381 | mutex_unlock(&watchdog.lock); | ||
382 | |||
383 | return status; | ||
384 | } | ||
385 | |||
386 | static bool watchdog_is_running(void) | ||
387 | { | ||
388 | /* | ||
389 | * if we fail to determine the watchdog's status assume it to be | ||
390 | * running to be on the safe side | ||
391 | */ | ||
392 | bool is_running = true; | ||
393 | |||
394 | mutex_lock(&watchdog.lock); | ||
395 | if (superio_enter(watchdog.sioaddr)) | ||
396 | goto exit_unlock; | ||
397 | superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); | ||
398 | |||
399 | is_running = (superio_inb(watchdog.sioaddr, SIO_REG_ENABLE) & BIT(0)) | ||
400 | && (superio_inb(watchdog.sioaddr, F71808FG_REG_WDT_CONF) | ||
401 | & F71808FG_FLAG_WD_EN); | ||
402 | |||
403 | superio_exit(watchdog.sioaddr); | ||
404 | |||
405 | exit_unlock: | ||
406 | mutex_unlock(&watchdog.lock); | ||
407 | return is_running; | ||
408 | } | ||
409 | |||
410 | /* /dev/watchdog api */ | ||
411 | |||
412 | static int watchdog_open(struct inode *inode, struct file *file) | ||
413 | { | ||
414 | int err; | ||
415 | |||
416 | /* If the watchdog is alive we don't need to start it again */ | ||
417 | if (test_and_set_bit(0, &watchdog.opened)) | ||
418 | return -EBUSY; | ||
419 | |||
420 | err = watchdog_start(); | ||
421 | if (err) { | ||
422 | clear_bit(0, &watchdog.opened); | ||
423 | return err; | ||
424 | } | ||
425 | |||
426 | if (nowayout) | ||
427 | __module_get(THIS_MODULE); | ||
428 | |||
429 | watchdog.expect_close = 0; | ||
430 | return nonseekable_open(inode, file); | ||
431 | } | ||
432 | |||
433 | static int watchdog_release(struct inode *inode, struct file *file) | ||
434 | { | ||
435 | clear_bit(0, &watchdog.opened); | ||
436 | |||
437 | if (!watchdog.expect_close) { | ||
438 | watchdog_keepalive(); | ||
439 | printk(KERN_CRIT DRVNAME | ||
440 | ": Unexpected close, not stopping watchdog!\n"); | ||
441 | } else if (!nowayout) { | ||
442 | watchdog_stop(); | ||
443 | } | ||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | /* | ||
448 | * watchdog_write: | ||
449 | * @file: file handle to the watchdog | ||
450 | * @buf: buffer to write | ||
451 | * @count: count of bytes | ||
452 | * @ppos: pointer to the position to write. No seeks allowed | ||
453 | * | ||
454 | * A write to a watchdog device is defined as a keepalive signal. Any | ||
455 | * write of data will do, as we we don't define content meaning. | ||
456 | */ | ||
457 | |||
458 | static ssize_t watchdog_write(struct file *file, const char __user *buf, | ||
459 | size_t count, loff_t *ppos) | ||
460 | { | ||
461 | if (count) { | ||
462 | if (!nowayout) { | ||
463 | size_t i; | ||
464 | |||
465 | /* In case it was set long ago */ | ||
466 | bool expect_close = false; | ||
467 | |||
468 | for (i = 0; i != count; i++) { | ||
469 | char c; | ||
470 | if (get_user(c, buf + i)) | ||
471 | return -EFAULT; | ||
472 | expect_close = (c == 'V'); | ||
473 | } | ||
474 | |||
475 | /* Properly order writes across fork()ed processes */ | ||
476 | mutex_lock(&watchdog.lock); | ||
477 | watchdog.expect_close = expect_close; | ||
478 | mutex_unlock(&watchdog.lock); | ||
479 | } | ||
480 | |||
481 | /* someone wrote to us, we should restart timer */ | ||
482 | watchdog_keepalive(); | ||
483 | } | ||
484 | return count; | ||
485 | } | ||
486 | |||
487 | /* | ||
488 | * watchdog_ioctl: | ||
489 | * @inode: inode of the device | ||
490 | * @file: file handle to the device | ||
491 | * @cmd: watchdog command | ||
492 | * @arg: argument pointer | ||
493 | * | ||
494 | * The watchdog API defines a common set of functions for all watchdogs | ||
495 | * according to their available features. | ||
496 | */ | ||
497 | static long watchdog_ioctl(struct file *file, unsigned int cmd, | ||
498 | unsigned long arg) | ||
499 | { | ||
500 | int status; | ||
501 | int new_options; | ||
502 | int new_timeout; | ||
503 | union { | ||
504 | struct watchdog_info __user *ident; | ||
505 | int __user *i; | ||
506 | } uarg; | ||
507 | |||
508 | uarg.i = (int __user *)arg; | ||
509 | |||
510 | switch (cmd) { | ||
511 | case WDIOC_GETSUPPORT: | ||
512 | return copy_to_user(uarg.ident, &watchdog.ident, | ||
513 | sizeof(watchdog.ident)) ? -EFAULT : 0; | ||
514 | |||
515 | case WDIOC_GETSTATUS: | ||
516 | status = watchdog_get_status(); | ||
517 | if (status < 0) | ||
518 | return status; | ||
519 | return put_user(status, uarg.i); | ||
520 | |||
521 | case WDIOC_GETBOOTSTATUS: | ||
522 | return put_user(0, uarg.i); | ||
523 | |||
524 | case WDIOC_SETOPTIONS: | ||
525 | if (get_user(new_options, uarg.i)) | ||
526 | return -EFAULT; | ||
527 | |||
528 | if (new_options & WDIOS_DISABLECARD) | ||
529 | watchdog_stop(); | ||
530 | |||
531 | if (new_options & WDIOS_ENABLECARD) | ||
532 | return watchdog_start(); | ||
533 | |||
534 | |||
535 | case WDIOC_KEEPALIVE: | ||
536 | watchdog_keepalive(); | ||
537 | return 0; | ||
538 | |||
539 | case WDIOC_SETTIMEOUT: | ||
540 | if (get_user(new_timeout, uarg.i)) | ||
541 | return -EFAULT; | ||
542 | |||
543 | if (watchdog_set_timeout(new_timeout)) | ||
544 | return -EINVAL; | ||
545 | |||
546 | watchdog_keepalive(); | ||
547 | /* Fall */ | ||
548 | |||
549 | case WDIOC_GETTIMEOUT: | ||
550 | return put_user(watchdog.timeout, uarg.i); | ||
551 | |||
552 | default: | ||
553 | return -ENOTTY; | ||
554 | |||
555 | } | ||
556 | } | ||
557 | |||
558 | static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, | ||
559 | void *unused) | ||
560 | { | ||
561 | if (code == SYS_DOWN || code == SYS_HALT) | ||
562 | watchdog_stop(); | ||
563 | return NOTIFY_DONE; | ||
564 | } | ||
565 | |||
566 | static const struct file_operations watchdog_fops = { | ||
567 | .owner = THIS_MODULE, | ||
568 | .llseek = no_llseek, | ||
569 | .open = watchdog_open, | ||
570 | .release = watchdog_release, | ||
571 | .write = watchdog_write, | ||
572 | .unlocked_ioctl = watchdog_ioctl, | ||
573 | }; | ||
574 | |||
575 | static struct miscdevice watchdog_miscdev = { | ||
576 | .minor = WATCHDOG_MINOR, | ||
577 | .name = "watchdog", | ||
578 | .fops = &watchdog_fops, | ||
579 | }; | ||
580 | |||
581 | static struct notifier_block watchdog_notifier = { | ||
582 | .notifier_call = watchdog_notify_sys, | ||
583 | }; | ||
584 | |||
585 | static int __init watchdog_init(int sioaddr) | ||
586 | { | ||
587 | int wdt_conf, err = 0; | ||
588 | |||
589 | /* No need to lock watchdog.lock here because no entry points | ||
590 | * into the module have been registered yet. | ||
591 | */ | ||
592 | watchdog.sioaddr = sioaddr; | ||
593 | watchdog.ident.options = WDIOC_SETTIMEOUT | ||
594 | | WDIOF_MAGICCLOSE | ||
595 | | WDIOF_KEEPALIVEPING; | ||
596 | |||
597 | snprintf(watchdog.ident.identity, | ||
598 | sizeof(watchdog.ident.identity), "%s watchdog", | ||
599 | f71808e_names[watchdog.type]); | ||
600 | |||
601 | err = superio_enter(sioaddr); | ||
602 | if (err) | ||
603 | return err; | ||
604 | superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); | ||
605 | |||
606 | wdt_conf = superio_inb(sioaddr, F71808FG_REG_WDT_CONF); | ||
607 | watchdog.caused_reboot = wdt_conf & F71808FG_FLAG_WDTMOUT_STS; | ||
608 | |||
609 | superio_exit(sioaddr); | ||
610 | |||
611 | err = watchdog_set_timeout(timeout); | ||
612 | if (err) | ||
613 | return err; | ||
614 | err = watchdog_set_pulse_width(pulse_width); | ||
615 | if (err) | ||
616 | return err; | ||
617 | |||
618 | err = register_reboot_notifier(&watchdog_notifier); | ||
619 | if (err) | ||
620 | return err; | ||
621 | |||
622 | err = misc_register(&watchdog_miscdev); | ||
623 | if (err) { | ||
624 | printk(KERN_ERR DRVNAME | ||
625 | ": cannot register miscdev on minor=%d\n", | ||
626 | watchdog_miscdev.minor); | ||
627 | goto exit_reboot; | ||
628 | } | ||
629 | |||
630 | if (start_withtimeout) { | ||
631 | if (start_withtimeout <= 0 | ||
632 | || start_withtimeout > max_timeout) { | ||
633 | printk(KERN_ERR DRVNAME | ||
634 | ": starting timeout out of range\n"); | ||
635 | err = -EINVAL; | ||
636 | goto exit_miscdev; | ||
637 | } | ||
638 | |||
639 | err = watchdog_start(); | ||
640 | if (err) { | ||
641 | printk(KERN_ERR DRVNAME | ||
642 | ": cannot start watchdog timer\n"); | ||
643 | goto exit_miscdev; | ||
644 | } | ||
645 | |||
646 | mutex_lock(&watchdog.lock); | ||
647 | err = superio_enter(sioaddr); | ||
648 | if (err) | ||
649 | goto exit_unlock; | ||
650 | superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); | ||
651 | |||
652 | if (start_withtimeout > 0xff) { | ||
653 | /* select minutes for timer units */ | ||
654 | superio_set_bit(sioaddr, F71808FG_REG_WDT_CONF, | ||
655 | F71808FG_FLAG_WD_UNIT); | ||
656 | superio_outb(sioaddr, F71808FG_REG_WD_TIME, | ||
657 | DIV_ROUND_UP(start_withtimeout, 60)); | ||
658 | } else { | ||
659 | /* select seconds for timer units */ | ||
660 | superio_clear_bit(sioaddr, F71808FG_REG_WDT_CONF, | ||
661 | F71808FG_FLAG_WD_UNIT); | ||
662 | superio_outb(sioaddr, F71808FG_REG_WD_TIME, | ||
663 | start_withtimeout); | ||
664 | } | ||
665 | |||
666 | superio_exit(sioaddr); | ||
667 | mutex_unlock(&watchdog.lock); | ||
668 | |||
669 | if (nowayout) | ||
670 | __module_get(THIS_MODULE); | ||
671 | |||
672 | printk(KERN_INFO DRVNAME | ||
673 | ": watchdog started with initial timeout of %u sec\n", | ||
674 | start_withtimeout); | ||
675 | } | ||
676 | |||
677 | return 0; | ||
678 | |||
679 | exit_unlock: | ||
680 | mutex_unlock(&watchdog.lock); | ||
681 | exit_miscdev: | ||
682 | misc_deregister(&watchdog_miscdev); | ||
683 | exit_reboot: | ||
684 | unregister_reboot_notifier(&watchdog_notifier); | ||
685 | |||
686 | return err; | ||
687 | } | ||
688 | |||
689 | static int __init f71808e_find(int sioaddr) | ||
690 | { | ||
691 | u16 devid; | ||
692 | int err = superio_enter(sioaddr); | ||
693 | if (err) | ||
694 | return err; | ||
695 | |||
696 | devid = superio_inw(sioaddr, SIO_REG_MANID); | ||
697 | if (devid != SIO_FINTEK_ID) { | ||
698 | pr_debug(DRVNAME ": Not a Fintek device\n"); | ||
699 | err = -ENODEV; | ||
700 | goto exit; | ||
701 | } | ||
702 | |||
703 | devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); | ||
704 | switch (devid) { | ||
705 | case SIO_F71808_ID: | ||
706 | watchdog.type = f71808fg; | ||
707 | break; | ||
708 | case SIO_F71882_ID: | ||
709 | watchdog.type = f71882fg; | ||
710 | break; | ||
711 | case SIO_F71862_ID: | ||
712 | case SIO_F71889_ID: | ||
713 | /* These have a watchdog, though it isn't implemented (yet). */ | ||
714 | err = -ENOSYS; | ||
715 | goto exit; | ||
716 | case SIO_F71858_ID: | ||
717 | /* Confirmed (by datasheet) not to have a watchdog. */ | ||
718 | err = -ENODEV; | ||
719 | goto exit; | ||
720 | default: | ||
721 | printk(KERN_INFO DRVNAME ": Unrecognized Fintek device: %04x\n", | ||
722 | (unsigned int)devid); | ||
723 | err = -ENODEV; | ||
724 | goto exit; | ||
725 | } | ||
726 | |||
727 | printk(KERN_INFO DRVNAME ": Found %s watchdog chip, revision %d\n", | ||
728 | f71808e_names[watchdog.type], | ||
729 | (int)superio_inb(sioaddr, SIO_REG_DEVREV)); | ||
730 | exit: | ||
731 | superio_exit(sioaddr); | ||
732 | return err; | ||
733 | } | ||
734 | |||
735 | static int __init f71808e_init(void) | ||
736 | { | ||
737 | static const unsigned short addrs[] = { 0x2e, 0x4e }; | ||
738 | int err = -ENODEV; | ||
739 | int i; | ||
740 | |||
741 | for (i = 0; i < ARRAY_SIZE(addrs); i++) { | ||
742 | err = f71808e_find(addrs[i]); | ||
743 | if (err == 0) | ||
744 | break; | ||
745 | } | ||
746 | if (i == ARRAY_SIZE(addrs)) | ||
747 | return err; | ||
748 | |||
749 | return watchdog_init(addrs[i]); | ||
750 | } | ||
751 | |||
752 | static void __exit f71808e_exit(void) | ||
753 | { | ||
754 | if (watchdog_is_running()) { | ||
755 | printk(KERN_WARNING DRVNAME | ||
756 | ": Watchdog timer still running, stopping it\n"); | ||
757 | watchdog_stop(); | ||
758 | } | ||
759 | misc_deregister(&watchdog_miscdev); | ||
760 | unregister_reboot_notifier(&watchdog_notifier); | ||
761 | } | ||
762 | |||
763 | MODULE_DESCRIPTION("F71808E Watchdog Driver"); | ||
764 | MODULE_AUTHOR("Giel van Schijndel <me@mortis.eu>"); | ||
765 | MODULE_LICENSE("GPL"); | ||
766 | |||
767 | module_init(f71808e_init); | ||
768 | module_exit(f71808e_exit); | ||
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 809e7167a624..fd312fc8940e 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c | |||
@@ -246,8 +246,8 @@ static int __devinit cru_detect(unsigned long map_entry, | |||
246 | physical_bios_offset); | 246 | physical_bios_offset); |
247 | printk(KERN_DEBUG "hpwdt: CRU Length: 0x%lx\n", | 247 | printk(KERN_DEBUG "hpwdt: CRU Length: 0x%lx\n", |
248 | cru_length); | 248 | cru_length); |
249 | printk(KERN_DEBUG "hpwdt: CRU Mapped Address: 0x%x\n", | 249 | printk(KERN_DEBUG "hpwdt: CRU Mapped Address: %p\n", |
250 | (unsigned int)&cru_rom_addr); | 250 | &cru_rom_addr); |
251 | } | 251 | } |
252 | iounmap(bios32_map); | 252 | iounmap(bios32_map); |
253 | return retval; | 253 | return retval; |
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 300932580ded..ae53662c29bc 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c | |||
@@ -532,21 +532,22 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev) | |||
532 | 532 | ||
533 | static int __devexit s3c2410wdt_remove(struct platform_device *dev) | 533 | static int __devexit s3c2410wdt_remove(struct platform_device *dev) |
534 | { | 534 | { |
535 | s3c2410wdt_cpufreq_deregister(); | 535 | misc_deregister(&s3c2410wdt_miscdev); |
536 | |||
537 | release_resource(wdt_mem); | ||
538 | kfree(wdt_mem); | ||
539 | wdt_mem = NULL; | ||
540 | 536 | ||
541 | free_irq(wdt_irq->start, dev); | 537 | s3c2410wdt_cpufreq_deregister(); |
542 | wdt_irq = NULL; | ||
543 | 538 | ||
544 | clk_disable(wdt_clock); | 539 | clk_disable(wdt_clock); |
545 | clk_put(wdt_clock); | 540 | clk_put(wdt_clock); |
546 | wdt_clock = NULL; | 541 | wdt_clock = NULL; |
547 | 542 | ||
543 | free_irq(wdt_irq->start, dev); | ||
544 | wdt_irq = NULL; | ||
545 | |||
548 | iounmap(wdt_base); | 546 | iounmap(wdt_base); |
549 | misc_deregister(&s3c2410wdt_miscdev); | 547 | |
548 | release_resource(wdt_mem); | ||
549 | kfree(wdt_mem); | ||
550 | wdt_mem = NULL; | ||
550 | return 0; | 551 | return 0; |
551 | } | 552 | } |
552 | 553 | ||
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index 9c40f48804f5..0461858e07d0 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c | |||
@@ -425,6 +425,8 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev) | |||
425 | val = therm_trip ? 0x06 : 0x04; | 425 | val = therm_trip ? 0x06 : 0x04; |
426 | outb(val, sch311x_wdt_data.runtime_reg + RESGEN); | 426 | outb(val, sch311x_wdt_data.runtime_reg + RESGEN); |
427 | 427 | ||
428 | sch311x_wdt_miscdev.parent = dev; | ||
429 | |||
428 | err = misc_register(&sch311x_wdt_miscdev); | 430 | err = misc_register(&sch311x_wdt_miscdev); |
429 | if (err != 0) { | 431 | if (err != 0) { |
430 | dev_err(dev, "cannot register miscdev on minor=%d (err=%d)\n", | 432 | dev_err(dev, "cannot register miscdev on minor=%d (err=%d)\n", |
@@ -432,8 +434,6 @@ static int __devinit sch311x_wdt_probe(struct platform_device *pdev) | |||
432 | goto exit_release_region3; | 434 | goto exit_release_region3; |
433 | } | 435 | } |
434 | 436 | ||
435 | sch311x_wdt_miscdev.parent = dev; | ||
436 | |||
437 | dev_info(dev, | 437 | dev_info(dev, |
438 | "SMSC SCH311x WDT initialized. timeout=%d sec (nowayout=%d)\n", | 438 | "SMSC SCH311x WDT initialized. timeout=%d sec (nowayout=%d)\n", |
439 | timeout, nowayout); | 439 | timeout, nowayout); |
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c new file mode 100644 index 000000000000..9127eda2145b --- /dev/null +++ b/drivers/watchdog/sp805_wdt.c | |||
@@ -0,0 +1,387 @@ | |||
1 | /* | ||
2 | * drivers/char/watchdog/sp805-wdt.c | ||
3 | * | ||
4 | * Watchdog driver for ARM SP805 watchdog module | ||
5 | * | ||
6 | * Copyright (C) 2010 ST Microelectronics | ||
7 | * Viresh Kumar<viresh.kumar@st.com> | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public | ||
10 | * License version 2 or later. This program is licensed "as is" without any | ||
11 | * warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/resource.h> | ||
16 | #include <linux/amba/bus.h> | ||
17 | #include <linux/bitops.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/ioport.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/math64.h> | ||
25 | #include <linux/miscdevice.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/moduleparam.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/spinlock.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/uaccess.h> | ||
32 | #include <linux/watchdog.h> | ||
33 | |||
34 | /* default timeout in seconds */ | ||
35 | #define DEFAULT_TIMEOUT 60 | ||
36 | |||
37 | #define MODULE_NAME "sp805-wdt" | ||
38 | |||
39 | /* watchdog register offsets and masks */ | ||
40 | #define WDTLOAD 0x000 | ||
41 | #define LOAD_MIN 0x00000001 | ||
42 | #define LOAD_MAX 0xFFFFFFFF | ||
43 | #define WDTVALUE 0x004 | ||
44 | #define WDTCONTROL 0x008 | ||
45 | /* control register masks */ | ||
46 | #define INT_ENABLE (1 << 0) | ||
47 | #define RESET_ENABLE (1 << 1) | ||
48 | #define WDTINTCLR 0x00C | ||
49 | #define WDTRIS 0x010 | ||
50 | #define WDTMIS 0x014 | ||
51 | #define INT_MASK (1 << 0) | ||
52 | #define WDTLOCK 0xC00 | ||
53 | #define UNLOCK 0x1ACCE551 | ||
54 | #define LOCK 0x00000001 | ||
55 | |||
56 | /** | ||
57 | * struct sp805_wdt: sp805 wdt device structure | ||
58 | * | ||
59 | * lock: spin lock protecting dev structure and io access | ||
60 | * base: base address of wdt | ||
61 | * clk: clock structure of wdt | ||
62 | * dev: amba device structure of wdt | ||
63 | * status: current status of wdt | ||
64 | * load_val: load value to be set for current timeout | ||
65 | * timeout: current programmed timeout | ||
66 | */ | ||
67 | struct sp805_wdt { | ||
68 | spinlock_t lock; | ||
69 | void __iomem *base; | ||
70 | struct clk *clk; | ||
71 | struct amba_device *adev; | ||
72 | unsigned long status; | ||
73 | #define WDT_BUSY 0 | ||
74 | #define WDT_CAN_BE_CLOSED 1 | ||
75 | unsigned int load_val; | ||
76 | unsigned int timeout; | ||
77 | }; | ||
78 | |||
79 | /* local variables */ | ||
80 | static struct sp805_wdt *wdt; | ||
81 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
82 | |||
83 | /* This routine finds load value that will reset system in required timout */ | ||
84 | static void wdt_setload(unsigned int timeout) | ||
85 | { | ||
86 | u64 load, rate; | ||
87 | |||
88 | rate = clk_get_rate(wdt->clk); | ||
89 | |||
90 | /* | ||
91 | * sp805 runs counter with given value twice, after the end of first | ||
92 | * counter it gives an interrupt and then starts counter again. If | ||
93 | * interrupt already occured then it resets the system. This is why | ||
94 | * load is half of what should be required. | ||
95 | */ | ||
96 | load = div_u64(rate, 2) * timeout - 1; | ||
97 | |||
98 | load = (load > LOAD_MAX) ? LOAD_MAX : load; | ||
99 | load = (load < LOAD_MIN) ? LOAD_MIN : load; | ||
100 | |||
101 | spin_lock(&wdt->lock); | ||
102 | wdt->load_val = load; | ||
103 | /* roundup timeout to closest positive integer value */ | ||
104 | wdt->timeout = div_u64((load + 1) * 2 + (rate / 2), rate); | ||
105 | spin_unlock(&wdt->lock); | ||
106 | } | ||
107 | |||
108 | /* returns number of seconds left for reset to occur */ | ||
109 | static u32 wdt_timeleft(void) | ||
110 | { | ||
111 | u64 load, rate; | ||
112 | |||
113 | rate = clk_get_rate(wdt->clk); | ||
114 | |||
115 | spin_lock(&wdt->lock); | ||
116 | load = readl(wdt->base + WDTVALUE); | ||
117 | |||
118 | /*If the interrupt is inactive then time left is WDTValue + WDTLoad. */ | ||
119 | if (!(readl(wdt->base + WDTRIS) & INT_MASK)) | ||
120 | load += wdt->load_val + 1; | ||
121 | spin_unlock(&wdt->lock); | ||
122 | |||
123 | return div_u64(load, rate); | ||
124 | } | ||
125 | |||
126 | /* enables watchdog timers reset */ | ||
127 | static void wdt_enable(void) | ||
128 | { | ||
129 | spin_lock(&wdt->lock); | ||
130 | |||
131 | writel(UNLOCK, wdt->base + WDTLOCK); | ||
132 | writel(wdt->load_val, wdt->base + WDTLOAD); | ||
133 | writel(INT_MASK, wdt->base + WDTINTCLR); | ||
134 | writel(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL); | ||
135 | writel(LOCK, wdt->base + WDTLOCK); | ||
136 | |||
137 | spin_unlock(&wdt->lock); | ||
138 | } | ||
139 | |||
140 | /* disables watchdog timers reset */ | ||
141 | static void wdt_disable(void) | ||
142 | { | ||
143 | spin_lock(&wdt->lock); | ||
144 | |||
145 | writel(UNLOCK, wdt->base + WDTLOCK); | ||
146 | writel(0, wdt->base + WDTCONTROL); | ||
147 | writel(0, wdt->base + WDTLOAD); | ||
148 | writel(LOCK, wdt->base + WDTLOCK); | ||
149 | |||
150 | spin_unlock(&wdt->lock); | ||
151 | } | ||
152 | |||
153 | static ssize_t sp805_wdt_write(struct file *file, const char *data, | ||
154 | size_t len, loff_t *ppos) | ||
155 | { | ||
156 | if (len) { | ||
157 | if (!nowayout) { | ||
158 | size_t i; | ||
159 | |||
160 | clear_bit(WDT_CAN_BE_CLOSED, &wdt->status); | ||
161 | |||
162 | for (i = 0; i != len; i++) { | ||
163 | char c; | ||
164 | |||
165 | if (get_user(c, data + i)) | ||
166 | return -EFAULT; | ||
167 | /* Check for Magic Close character */ | ||
168 | if (c == 'V') { | ||
169 | set_bit(WDT_CAN_BE_CLOSED, | ||
170 | &wdt->status); | ||
171 | break; | ||
172 | } | ||
173 | } | ||
174 | } | ||
175 | wdt_enable(); | ||
176 | } | ||
177 | return len; | ||
178 | } | ||
179 | |||
180 | static const struct watchdog_info ident = { | ||
181 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | ||
182 | .identity = MODULE_NAME, | ||
183 | }; | ||
184 | |||
185 | static long sp805_wdt_ioctl(struct file *file, unsigned int cmd, | ||
186 | unsigned long arg) | ||
187 | { | ||
188 | int ret = -ENOTTY; | ||
189 | unsigned int timeout; | ||
190 | |||
191 | switch (cmd) { | ||
192 | case WDIOC_GETSUPPORT: | ||
193 | ret = copy_to_user((struct watchdog_info *)arg, &ident, | ||
194 | sizeof(ident)) ? -EFAULT : 0; | ||
195 | break; | ||
196 | |||
197 | case WDIOC_GETSTATUS: | ||
198 | ret = put_user(0, (int *)arg); | ||
199 | break; | ||
200 | |||
201 | case WDIOC_KEEPALIVE: | ||
202 | wdt_enable(); | ||
203 | ret = 0; | ||
204 | break; | ||
205 | |||
206 | case WDIOC_SETTIMEOUT: | ||
207 | ret = get_user(timeout, (unsigned int *)arg); | ||
208 | if (ret) | ||
209 | break; | ||
210 | |||
211 | wdt_setload(timeout); | ||
212 | |||
213 | wdt_enable(); | ||
214 | /* Fall through */ | ||
215 | |||
216 | case WDIOC_GETTIMEOUT: | ||
217 | ret = put_user(wdt->timeout, (unsigned int *)arg); | ||
218 | break; | ||
219 | case WDIOC_GETTIMELEFT: | ||
220 | ret = put_user(wdt_timeleft(), (unsigned int *)arg); | ||
221 | break; | ||
222 | } | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static int sp805_wdt_open(struct inode *inode, struct file *file) | ||
227 | { | ||
228 | int ret = 0; | ||
229 | |||
230 | if (test_and_set_bit(WDT_BUSY, &wdt->status)) | ||
231 | return -EBUSY; | ||
232 | |||
233 | ret = clk_enable(wdt->clk); | ||
234 | if (ret) { | ||
235 | dev_err(&wdt->adev->dev, "clock enable fail"); | ||
236 | goto err; | ||
237 | } | ||
238 | |||
239 | wdt_enable(); | ||
240 | |||
241 | /* can not be closed, once enabled */ | ||
242 | clear_bit(WDT_CAN_BE_CLOSED, &wdt->status); | ||
243 | return nonseekable_open(inode, file); | ||
244 | |||
245 | err: | ||
246 | clear_bit(WDT_BUSY, &wdt->status); | ||
247 | return ret; | ||
248 | } | ||
249 | |||
250 | static int sp805_wdt_release(struct inode *inode, struct file *file) | ||
251 | { | ||
252 | if (!test_bit(WDT_CAN_BE_CLOSED, &wdt->status)) { | ||
253 | clear_bit(WDT_BUSY, &wdt->status); | ||
254 | dev_warn(&wdt->adev->dev, "Device closed unexpectedly\n"); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | wdt_disable(); | ||
259 | clk_disable(wdt->clk); | ||
260 | clear_bit(WDT_BUSY, &wdt->status); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static const struct file_operations sp805_wdt_fops = { | ||
266 | .owner = THIS_MODULE, | ||
267 | .llseek = no_llseek, | ||
268 | .write = sp805_wdt_write, | ||
269 | .unlocked_ioctl = sp805_wdt_ioctl, | ||
270 | .open = sp805_wdt_open, | ||
271 | .release = sp805_wdt_release, | ||
272 | }; | ||
273 | |||
274 | static struct miscdevice sp805_wdt_miscdev = { | ||
275 | .minor = WATCHDOG_MINOR, | ||
276 | .name = "watchdog", | ||
277 | .fops = &sp805_wdt_fops, | ||
278 | }; | ||
279 | |||
280 | static int __devinit | ||
281 | sp805_wdt_probe(struct amba_device *adev, struct amba_id *id) | ||
282 | { | ||
283 | int ret = 0; | ||
284 | |||
285 | if (!request_mem_region(adev->res.start, resource_size(&adev->res), | ||
286 | "sp805_wdt")) { | ||
287 | dev_warn(&adev->dev, "Failed to get memory region resource\n"); | ||
288 | ret = -ENOENT; | ||
289 | goto err; | ||
290 | } | ||
291 | |||
292 | wdt = kzalloc(sizeof(*wdt), GFP_KERNEL); | ||
293 | if (!wdt) { | ||
294 | dev_warn(&adev->dev, "Kzalloc failed\n"); | ||
295 | ret = -ENOMEM; | ||
296 | goto err_kzalloc; | ||
297 | } | ||
298 | |||
299 | wdt->clk = clk_get(&adev->dev, NULL); | ||
300 | if (IS_ERR(wdt->clk)) { | ||
301 | dev_warn(&adev->dev, "Clock not found\n"); | ||
302 | ret = PTR_ERR(wdt->clk); | ||
303 | goto err_clk_get; | ||
304 | } | ||
305 | |||
306 | wdt->base = ioremap(adev->res.start, resource_size(&adev->res)); | ||
307 | if (!wdt->base) { | ||
308 | ret = -ENOMEM; | ||
309 | dev_warn(&adev->dev, "ioremap fail\n"); | ||
310 | goto err_ioremap; | ||
311 | } | ||
312 | |||
313 | wdt->adev = adev; | ||
314 | spin_lock_init(&wdt->lock); | ||
315 | wdt_setload(DEFAULT_TIMEOUT); | ||
316 | |||
317 | ret = misc_register(&sp805_wdt_miscdev); | ||
318 | if (ret < 0) { | ||
319 | dev_warn(&adev->dev, "cannot register misc device\n"); | ||
320 | goto err_misc_register; | ||
321 | } | ||
322 | |||
323 | dev_info(&adev->dev, "registration successful\n"); | ||
324 | return 0; | ||
325 | |||
326 | err_misc_register: | ||
327 | iounmap(wdt->base); | ||
328 | err_ioremap: | ||
329 | clk_put(wdt->clk); | ||
330 | err_clk_get: | ||
331 | kfree(wdt); | ||
332 | wdt = NULL; | ||
333 | err_kzalloc: | ||
334 | release_mem_region(adev->res.start, resource_size(&adev->res)); | ||
335 | err: | ||
336 | dev_err(&adev->dev, "Probe Failed!!!\n"); | ||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | static int __devexit sp805_wdt_remove(struct amba_device *adev) | ||
341 | { | ||
342 | misc_deregister(&sp805_wdt_miscdev); | ||
343 | iounmap(wdt->base); | ||
344 | clk_put(wdt->clk); | ||
345 | kfree(wdt); | ||
346 | release_mem_region(adev->res.start, resource_size(&adev->res)); | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static struct amba_id sp805_wdt_ids[] __initdata = { | ||
352 | { | ||
353 | .id = 0x00141805, | ||
354 | .mask = 0x00ffffff, | ||
355 | }, | ||
356 | { 0, 0 }, | ||
357 | }; | ||
358 | |||
359 | static struct amba_driver sp805_wdt_driver = { | ||
360 | .drv = { | ||
361 | .name = MODULE_NAME, | ||
362 | }, | ||
363 | .id_table = sp805_wdt_ids, | ||
364 | .probe = sp805_wdt_probe, | ||
365 | .remove = __devexit_p(sp805_wdt_remove), | ||
366 | }; | ||
367 | |||
368 | static int __init sp805_wdt_init(void) | ||
369 | { | ||
370 | return amba_driver_register(&sp805_wdt_driver); | ||
371 | } | ||
372 | module_init(sp805_wdt_init); | ||
373 | |||
374 | static void __exit sp805_wdt_exit(void) | ||
375 | { | ||
376 | amba_driver_unregister(&sp805_wdt_driver); | ||
377 | } | ||
378 | module_exit(sp805_wdt_exit); | ||
379 | |||
380 | module_param(nowayout, int, 0); | ||
381 | MODULE_PARM_DESC(nowayout, | ||
382 | "Set to 1 to keep watchdog running after device release"); | ||
383 | |||
384 | MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>"); | ||
385 | MODULE_DESCRIPTION("ARM SP805 Watchdog Driver"); | ||
386 | MODULE_LICENSE("GPL"); | ||
387 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index 7b22e3cdbc81..6130c88fa5ac 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c | |||
@@ -60,19 +60,6 @@ | |||
60 | 60 | ||
61 | #define PFX "wdt_pci: " | 61 | #define PFX "wdt_pci: " |
62 | 62 | ||
63 | /* | ||
64 | * Until Access I/O gets their application for a PCI vendor ID approved, | ||
65 | * I don't think that it's appropriate to move these constants into the | ||
66 | * regular pci_ids.h file. -- JPN 2000/01/18 | ||
67 | */ | ||
68 | |||
69 | #ifndef PCI_VENDOR_ID_ACCESSIO | ||
70 | #define PCI_VENDOR_ID_ACCESSIO 0x494f | ||
71 | #endif | ||
72 | #ifndef PCI_DEVICE_ID_WDG_CSM | ||
73 | #define PCI_DEVICE_ID_WDG_CSM 0x22c0 | ||
74 | #endif | ||
75 | |||
76 | /* We can only use 1 card due to the /dev/watchdog restriction */ | 63 | /* We can only use 1 card due to the /dev/watchdog restriction */ |
77 | static int dev_count; | 64 | static int dev_count; |
78 | 65 | ||
@@ -743,7 +730,7 @@ static void __devexit wdtpci_remove_one(struct pci_dev *pdev) | |||
743 | static struct pci_device_id wdtpci_pci_tbl[] = { | 730 | static struct pci_device_id wdtpci_pci_tbl[] = { |
744 | { | 731 | { |
745 | .vendor = PCI_VENDOR_ID_ACCESSIO, | 732 | .vendor = PCI_VENDOR_ID_ACCESSIO, |
746 | .device = PCI_DEVICE_ID_WDG_CSM, | 733 | .device = PCI_DEVICE_ID_ACCESSIO_WDG_CSM, |
747 | .subvendor = PCI_ANY_ID, | 734 | .subvendor = PCI_ANY_ID, |
748 | .subdevice = PCI_ANY_ID, | 735 | .subdevice = PCI_ANY_ID, |
749 | }, | 736 | }, |
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index 3c7046d79654..cafc50454292 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c | |||
@@ -22,8 +22,9 @@ static loff_t | |||
22 | proc_bus_zorro_lseek(struct file *file, loff_t off, int whence) | 22 | proc_bus_zorro_lseek(struct file *file, loff_t off, int whence) |
23 | { | 23 | { |
24 | loff_t new = -1; | 24 | loff_t new = -1; |
25 | struct inode *inode = file->f_path.dentry->d_inode; | ||
25 | 26 | ||
26 | lock_kernel(); | 27 | mutex_lock(&inode->i_mutex); |
27 | switch (whence) { | 28 | switch (whence) { |
28 | case 0: | 29 | case 0: |
29 | new = off; | 30 | new = off; |
@@ -35,12 +36,12 @@ proc_bus_zorro_lseek(struct file *file, loff_t off, int whence) | |||
35 | new = sizeof(struct ConfigDev) + off; | 36 | new = sizeof(struct ConfigDev) + off; |
36 | break; | 37 | break; |
37 | } | 38 | } |
38 | if (new < 0 || new > sizeof(struct ConfigDev)) { | 39 | if (new < 0 || new > sizeof(struct ConfigDev)) |
39 | unlock_kernel(); | 40 | new = -EINVAL; |
40 | return -EINVAL; | 41 | else |
41 | } | 42 | file->f_pos = new; |
42 | unlock_kernel(); | 43 | mutex_unlock(&inode->i_mutex); |
43 | return (file->f_pos = new); | 44 | return new; |
44 | } | 45 | } |
45 | 46 | ||
46 | static ssize_t | 47 | static ssize_t |
@@ -67,7 +68,7 @@ proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t * | |||
67 | cd.cd_BoardAddr = (void *)zorro_resource_start(z); | 68 | cd.cd_BoardAddr = (void *)zorro_resource_start(z); |
68 | cd.cd_BoardSize = zorro_resource_len(z); | 69 | cd.cd_BoardSize = zorro_resource_len(z); |
69 | 70 | ||
70 | if (copy_to_user(buf, &cd, nbytes)) | 71 | if (copy_to_user(buf, (void *)&cd + pos, nbytes)) |
71 | return -EFAULT; | 72 | return -EFAULT; |
72 | *ppos += nbytes; | 73 | *ppos += nbytes; |
73 | 74 | ||