diff options
122 files changed, 4614 insertions, 387 deletions
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt index 7c717699032c..63392c9132b4 100644 --- a/Documentation/DMA-mapping.txt +++ b/Documentation/DMA-mapping.txt | |||
@@ -698,12 +698,12 @@ these interfaces. Remember that, as defined, consistent mappings are | |||
698 | always going to be SAC addressable. | 698 | always going to be SAC addressable. |
699 | 699 | ||
700 | The first thing your driver needs to do is query the PCI platform | 700 | The first thing your driver needs to do is query the PCI platform |
701 | layer with your devices DAC addressing capabilities: | 701 | layer if it is capable of handling your devices DAC addressing |
702 | capabilities: | ||
702 | 703 | ||
703 | int pci_dac_set_dma_mask(struct pci_dev *pdev, u64 mask); | 704 | int pci_dac_dma_supported(struct pci_dev *hwdev, u64 mask); |
704 | 705 | ||
705 | This routine behaves identically to pci_set_dma_mask. You may not | 706 | You may not use the following interfaces if this routine fails. |
706 | use the following interfaces if this routine fails. | ||
707 | 707 | ||
708 | Next, DMA addresses using this API are kept track of using the | 708 | Next, DMA addresses using this API are kept track of using the |
709 | dma64_addr_t type. It is guaranteed to be big enough to hold any | 709 | dma64_addr_t type. It is guaranteed to be big enough to hold any |
diff --git a/Documentation/accounting/delay-accounting.txt b/Documentation/accounting/delay-accounting.txt new file mode 100644 index 000000000000..be215e58423b --- /dev/null +++ b/Documentation/accounting/delay-accounting.txt | |||
@@ -0,0 +1,110 @@ | |||
1 | Delay accounting | ||
2 | ---------------- | ||
3 | |||
4 | Tasks encounter delays in execution when they wait | ||
5 | for some kernel resource to become available e.g. a | ||
6 | runnable task may wait for a free CPU to run on. | ||
7 | |||
8 | The per-task delay accounting functionality measures | ||
9 | the delays experienced by a task while | ||
10 | |||
11 | a) waiting for a CPU (while being runnable) | ||
12 | b) completion of synchronous block I/O initiated by the task | ||
13 | c) swapping in pages | ||
14 | |||
15 | and makes these statistics available to userspace through | ||
16 | the taskstats interface. | ||
17 | |||
18 | Such delays provide feedback for setting a task's cpu priority, | ||
19 | io priority and rss limit values appropriately. Long delays for | ||
20 | important tasks could be a trigger for raising its corresponding priority. | ||
21 | |||
22 | The functionality, through its use of the taskstats interface, also provides | ||
23 | delay statistics aggregated for all tasks (or threads) belonging to a | ||
24 | thread group (corresponding to a traditional Unix process). This is a commonly | ||
25 | needed aggregation that is more efficiently done by the kernel. | ||
26 | |||
27 | Userspace utilities, particularly resource management applications, can also | ||
28 | aggregate delay statistics into arbitrary groups. To enable this, delay | ||
29 | statistics of a task are available both during its lifetime as well as on its | ||
30 | exit, ensuring continuous and complete monitoring can be done. | ||
31 | |||
32 | |||
33 | Interface | ||
34 | --------- | ||
35 | |||
36 | Delay accounting uses the taskstats interface which is described | ||
37 | in detail in a separate document in this directory. Taskstats returns a | ||
38 | generic data structure to userspace corresponding to per-pid and per-tgid | ||
39 | statistics. The delay accounting functionality populates specific fields of | ||
40 | this structure. See | ||
41 | include/linux/taskstats.h | ||
42 | for a description of the fields pertaining to delay accounting. | ||
43 | It will generally be in the form of counters returning the cumulative | ||
44 | delay seen for cpu, sync block I/O, swapin etc. | ||
45 | |||
46 | Taking the difference of two successive readings of a given | ||
47 | counter (say cpu_delay_total) for a task will give the delay | ||
48 | experienced by the task waiting for the corresponding resource | ||
49 | in that interval. | ||
50 | |||
51 | When a task exits, records containing the per-task statistics | ||
52 | are sent to userspace without requiring a command. If it is the last exiting | ||
53 | task of a thread group, the per-tgid statistics are also sent. More details | ||
54 | are given in the taskstats interface description. | ||
55 | |||
56 | The getdelays.c userspace utility in this directory allows simple commands to | ||
57 | be run and the corresponding delay statistics to be displayed. It also serves | ||
58 | as an example of using the taskstats interface. | ||
59 | |||
60 | Usage | ||
61 | ----- | ||
62 | |||
63 | Compile the kernel with | ||
64 | CONFIG_TASK_DELAY_ACCT=y | ||
65 | CONFIG_TASKSTATS=y | ||
66 | |||
67 | Enable the accounting at boot time by adding | ||
68 | the following to the kernel boot options | ||
69 | delayacct | ||
70 | |||
71 | and after the system has booted up, use a utility | ||
72 | similar to getdelays.c to access the delays | ||
73 | seen by a given task or a task group (tgid). | ||
74 | The utility also allows a given command to be | ||
75 | executed and the corresponding delays to be | ||
76 | seen. | ||
77 | |||
78 | General format of the getdelays command | ||
79 | |||
80 | getdelays [-t tgid] [-p pid] [-c cmd...] | ||
81 | |||
82 | |||
83 | Get delays, since system boot, for pid 10 | ||
84 | # ./getdelays -p 10 | ||
85 | (output similar to next case) | ||
86 | |||
87 | Get sum of delays, since system boot, for all pids with tgid 5 | ||
88 | # ./getdelays -t 5 | ||
89 | |||
90 | |||
91 | CPU count real total virtual total delay total | ||
92 | 7876 92005750 100000000 24001500 | ||
93 | IO count delay total | ||
94 | 0 0 | ||
95 | MEM count delay total | ||
96 | 0 0 | ||
97 | |||
98 | Get delays seen in executing a given simple command | ||
99 | # ./getdelays -c ls / | ||
100 | |||
101 | bin data1 data3 data5 dev home media opt root srv sys usr | ||
102 | boot data2 data4 data6 etc lib mnt proc sbin subdomain tmp var | ||
103 | |||
104 | |||
105 | CPU count real total virtual total delay total | ||
106 | 6 4000250 4000000 0 | ||
107 | IO count delay total | ||
108 | 0 0 | ||
109 | MEM count delay total | ||
110 | 0 0 | ||
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c new file mode 100644 index 000000000000..795ca3911cc5 --- /dev/null +++ b/Documentation/accounting/getdelays.c | |||
@@ -0,0 +1,396 @@ | |||
1 | /* getdelays.c | ||
2 | * | ||
3 | * Utility to get per-pid and per-tgid delay accounting statistics | ||
4 | * Also illustrates usage of the taskstats interface | ||
5 | * | ||
6 | * Copyright (C) Shailabh Nagar, IBM Corp. 2005 | ||
7 | * Copyright (C) Balbir Singh, IBM Corp. 2006 | ||
8 | * Copyright (c) Jay Lan, SGI. 2006 | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <stdio.h> | ||
13 | #include <stdlib.h> | ||
14 | #include <errno.h> | ||
15 | #include <unistd.h> | ||
16 | #include <poll.h> | ||
17 | #include <string.h> | ||
18 | #include <fcntl.h> | ||
19 | #include <sys/types.h> | ||
20 | #include <sys/stat.h> | ||
21 | #include <sys/socket.h> | ||
22 | #include <sys/types.h> | ||
23 | #include <signal.h> | ||
24 | |||
25 | #include <linux/genetlink.h> | ||
26 | #include <linux/taskstats.h> | ||
27 | |||
28 | /* | ||
29 | * Generic macros for dealing with netlink sockets. Might be duplicated | ||
30 | * elsewhere. It is recommended that commercial grade applications use | ||
31 | * libnl or libnetlink and use the interfaces provided by the library | ||
32 | */ | ||
33 | #define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN)) | ||
34 | #define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN) | ||
35 | #define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN)) | ||
36 | #define NLA_PAYLOAD(len) (len - NLA_HDRLEN) | ||
37 | |||
38 | #define err(code, fmt, arg...) do { printf(fmt, ##arg); exit(code); } while (0) | ||
39 | int done = 0; | ||
40 | int rcvbufsz=0; | ||
41 | |||
42 | char name[100]; | ||
43 | int dbg=0, print_delays=0; | ||
44 | __u64 stime, utime; | ||
45 | #define PRINTF(fmt, arg...) { \ | ||
46 | if (dbg) { \ | ||
47 | printf(fmt, ##arg); \ | ||
48 | } \ | ||
49 | } | ||
50 | |||
51 | /* Maximum size of response requested or message sent */ | ||
52 | #define MAX_MSG_SIZE 256 | ||
53 | /* Maximum number of cpus expected to be specified in a cpumask */ | ||
54 | #define MAX_CPUS 32 | ||
55 | /* Maximum length of pathname to log file */ | ||
56 | #define MAX_FILENAME 256 | ||
57 | |||
58 | struct msgtemplate { | ||
59 | struct nlmsghdr n; | ||
60 | struct genlmsghdr g; | ||
61 | char buf[MAX_MSG_SIZE]; | ||
62 | }; | ||
63 | |||
64 | char cpumask[100+6*MAX_CPUS]; | ||
65 | |||
66 | /* | ||
67 | * Create a raw netlink socket and bind | ||
68 | */ | ||
69 | static int create_nl_socket(int protocol) | ||
70 | { | ||
71 | int fd; | ||
72 | struct sockaddr_nl local; | ||
73 | |||
74 | fd = socket(AF_NETLINK, SOCK_RAW, protocol); | ||
75 | if (fd < 0) | ||
76 | return -1; | ||
77 | |||
78 | if (rcvbufsz) | ||
79 | if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, | ||
80 | &rcvbufsz, sizeof(rcvbufsz)) < 0) { | ||
81 | printf("Unable to set socket rcv buf size to %d\n", | ||
82 | rcvbufsz); | ||
83 | return -1; | ||
84 | } | ||
85 | |||
86 | memset(&local, 0, sizeof(local)); | ||
87 | local.nl_family = AF_NETLINK; | ||
88 | |||
89 | if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0) | ||
90 | goto error; | ||
91 | |||
92 | return fd; | ||
93 | error: | ||
94 | close(fd); | ||
95 | return -1; | ||
96 | } | ||
97 | |||
98 | |||
99 | int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid, | ||
100 | __u8 genl_cmd, __u16 nla_type, | ||
101 | void *nla_data, int nla_len) | ||
102 | { | ||
103 | struct nlattr *na; | ||
104 | struct sockaddr_nl nladdr; | ||
105 | int r, buflen; | ||
106 | char *buf; | ||
107 | |||
108 | struct msgtemplate msg; | ||
109 | |||
110 | msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); | ||
111 | msg.n.nlmsg_type = nlmsg_type; | ||
112 | msg.n.nlmsg_flags = NLM_F_REQUEST; | ||
113 | msg.n.nlmsg_seq = 0; | ||
114 | msg.n.nlmsg_pid = nlmsg_pid; | ||
115 | msg.g.cmd = genl_cmd; | ||
116 | msg.g.version = 0x1; | ||
117 | na = (struct nlattr *) GENLMSG_DATA(&msg); | ||
118 | na->nla_type = nla_type; | ||
119 | na->nla_len = nla_len + 1 + NLA_HDRLEN; | ||
120 | memcpy(NLA_DATA(na), nla_data, nla_len); | ||
121 | msg.n.nlmsg_len += NLMSG_ALIGN(na->nla_len); | ||
122 | |||
123 | buf = (char *) &msg; | ||
124 | buflen = msg.n.nlmsg_len ; | ||
125 | memset(&nladdr, 0, sizeof(nladdr)); | ||
126 | nladdr.nl_family = AF_NETLINK; | ||
127 | while ((r = sendto(sd, buf, buflen, 0, (struct sockaddr *) &nladdr, | ||
128 | sizeof(nladdr))) < buflen) { | ||
129 | if (r > 0) { | ||
130 | buf += r; | ||
131 | buflen -= r; | ||
132 | } else if (errno != EAGAIN) | ||
133 | return -1; | ||
134 | } | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | |||
139 | /* | ||
140 | * Probe the controller in genetlink to find the family id | ||
141 | * for the TASKSTATS family | ||
142 | */ | ||
143 | int get_family_id(int sd) | ||
144 | { | ||
145 | struct { | ||
146 | struct nlmsghdr n; | ||
147 | struct genlmsghdr g; | ||
148 | char buf[256]; | ||
149 | } ans; | ||
150 | |||
151 | int id, rc; | ||
152 | struct nlattr *na; | ||
153 | int rep_len; | ||
154 | |||
155 | strcpy(name, TASKSTATS_GENL_NAME); | ||
156 | rc = send_cmd(sd, GENL_ID_CTRL, getpid(), CTRL_CMD_GETFAMILY, | ||
157 | CTRL_ATTR_FAMILY_NAME, (void *)name, | ||
158 | strlen(TASKSTATS_GENL_NAME)+1); | ||
159 | |||
160 | rep_len = recv(sd, &ans, sizeof(ans), 0); | ||
161 | if (ans.n.nlmsg_type == NLMSG_ERROR || | ||
162 | (rep_len < 0) || !NLMSG_OK((&ans.n), rep_len)) | ||
163 | return 0; | ||
164 | |||
165 | na = (struct nlattr *) GENLMSG_DATA(&ans); | ||
166 | na = (struct nlattr *) ((char *) na + NLA_ALIGN(na->nla_len)); | ||
167 | if (na->nla_type == CTRL_ATTR_FAMILY_ID) { | ||
168 | id = *(__u16 *) NLA_DATA(na); | ||
169 | } | ||
170 | return id; | ||
171 | } | ||
172 | |||
173 | void print_delayacct(struct taskstats *t) | ||
174 | { | ||
175 | printf("\n\nCPU %15s%15s%15s%15s\n" | ||
176 | " %15llu%15llu%15llu%15llu\n" | ||
177 | "IO %15s%15s\n" | ||
178 | " %15llu%15llu\n" | ||
179 | "MEM %15s%15s\n" | ||
180 | " %15llu%15llu\n\n", | ||
181 | "count", "real total", "virtual total", "delay total", | ||
182 | t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total, | ||
183 | t->cpu_delay_total, | ||
184 | "count", "delay total", | ||
185 | t->blkio_count, t->blkio_delay_total, | ||
186 | "count", "delay total", t->swapin_count, t->swapin_delay_total); | ||
187 | } | ||
188 | |||
189 | int main(int argc, char *argv[]) | ||
190 | { | ||
191 | int c, rc, rep_len, aggr_len, len2, cmd_type; | ||
192 | __u16 id; | ||
193 | __u32 mypid; | ||
194 | |||
195 | struct nlattr *na; | ||
196 | int nl_sd = -1; | ||
197 | int len = 0; | ||
198 | pid_t tid = 0; | ||
199 | pid_t rtid = 0; | ||
200 | |||
201 | int fd = 0; | ||
202 | int count = 0; | ||
203 | int write_file = 0; | ||
204 | int maskset = 0; | ||
205 | char logfile[128]; | ||
206 | int loop = 0; | ||
207 | |||
208 | struct msgtemplate msg; | ||
209 | |||
210 | while (1) { | ||
211 | c = getopt(argc, argv, "dw:r:m:t:p:v:l"); | ||
212 | if (c < 0) | ||
213 | break; | ||
214 | |||
215 | switch (c) { | ||
216 | case 'd': | ||
217 | printf("print delayacct stats ON\n"); | ||
218 | print_delays = 1; | ||
219 | break; | ||
220 | case 'w': | ||
221 | strncpy(logfile, optarg, MAX_FILENAME); | ||
222 | printf("write to file %s\n", logfile); | ||
223 | write_file = 1; | ||
224 | break; | ||
225 | case 'r': | ||
226 | rcvbufsz = atoi(optarg); | ||
227 | printf("receive buf size %d\n", rcvbufsz); | ||
228 | if (rcvbufsz < 0) | ||
229 | err(1, "Invalid rcv buf size\n"); | ||
230 | break; | ||
231 | case 'm': | ||
232 | strncpy(cpumask, optarg, sizeof(cpumask)); | ||
233 | maskset = 1; | ||
234 | printf("cpumask %s maskset %d\n", cpumask, maskset); | ||
235 | break; | ||
236 | case 't': | ||
237 | tid = atoi(optarg); | ||
238 | if (!tid) | ||
239 | err(1, "Invalid tgid\n"); | ||
240 | cmd_type = TASKSTATS_CMD_ATTR_TGID; | ||
241 | print_delays = 1; | ||
242 | break; | ||
243 | case 'p': | ||
244 | tid = atoi(optarg); | ||
245 | if (!tid) | ||
246 | err(1, "Invalid pid\n"); | ||
247 | cmd_type = TASKSTATS_CMD_ATTR_PID; | ||
248 | print_delays = 1; | ||
249 | break; | ||
250 | case 'v': | ||
251 | printf("debug on\n"); | ||
252 | dbg = 1; | ||
253 | break; | ||
254 | case 'l': | ||
255 | printf("listen forever\n"); | ||
256 | loop = 1; | ||
257 | break; | ||
258 | default: | ||
259 | printf("Unknown option %d\n", c); | ||
260 | exit(-1); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | if (write_file) { | ||
265 | fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC, | ||
266 | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | ||
267 | if (fd == -1) { | ||
268 | perror("Cannot open output file\n"); | ||
269 | exit(1); | ||
270 | } | ||
271 | } | ||
272 | |||
273 | if ((nl_sd = create_nl_socket(NETLINK_GENERIC)) < 0) | ||
274 | err(1, "error creating Netlink socket\n"); | ||
275 | |||
276 | |||
277 | mypid = getpid(); | ||
278 | id = get_family_id(nl_sd); | ||
279 | if (!id) { | ||
280 | printf("Error getting family id, errno %d", errno); | ||
281 | goto err; | ||
282 | } | ||
283 | PRINTF("family id %d\n", id); | ||
284 | |||
285 | if (maskset) { | ||
286 | rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET, | ||
287 | TASKSTATS_CMD_ATTR_REGISTER_CPUMASK, | ||
288 | &cpumask, sizeof(cpumask)); | ||
289 | PRINTF("Sent register cpumask, retval %d\n", rc); | ||
290 | if (rc < 0) { | ||
291 | printf("error sending register cpumask\n"); | ||
292 | goto err; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | if (tid) { | ||
297 | rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET, | ||
298 | cmd_type, &tid, sizeof(__u32)); | ||
299 | PRINTF("Sent pid/tgid, retval %d\n", rc); | ||
300 | if (rc < 0) { | ||
301 | printf("error sending tid/tgid cmd\n"); | ||
302 | goto done; | ||
303 | } | ||
304 | } | ||
305 | |||
306 | do { | ||
307 | int i; | ||
308 | |||
309 | rep_len = recv(nl_sd, &msg, sizeof(msg), 0); | ||
310 | PRINTF("received %d bytes\n", rep_len); | ||
311 | |||
312 | if (rep_len < 0) { | ||
313 | printf("nonfatal reply error: errno %d\n", errno); | ||
314 | continue; | ||
315 | } | ||
316 | if (msg.n.nlmsg_type == NLMSG_ERROR || | ||
317 | !NLMSG_OK((&msg.n), rep_len)) { | ||
318 | printf("fatal reply error, errno %d\n", errno); | ||
319 | goto done; | ||
320 | } | ||
321 | |||
322 | PRINTF("nlmsghdr size=%d, nlmsg_len=%d, rep_len=%d\n", | ||
323 | sizeof(struct nlmsghdr), msg.n.nlmsg_len, rep_len); | ||
324 | |||
325 | |||
326 | rep_len = GENLMSG_PAYLOAD(&msg.n); | ||
327 | |||
328 | na = (struct nlattr *) GENLMSG_DATA(&msg); | ||
329 | len = 0; | ||
330 | i = 0; | ||
331 | while (len < rep_len) { | ||
332 | len += NLA_ALIGN(na->nla_len); | ||
333 | switch (na->nla_type) { | ||
334 | case TASKSTATS_TYPE_AGGR_TGID: | ||
335 | /* Fall through */ | ||
336 | case TASKSTATS_TYPE_AGGR_PID: | ||
337 | aggr_len = NLA_PAYLOAD(na->nla_len); | ||
338 | len2 = 0; | ||
339 | /* For nested attributes, na follows */ | ||
340 | na = (struct nlattr *) NLA_DATA(na); | ||
341 | done = 0; | ||
342 | while (len2 < aggr_len) { | ||
343 | switch (na->nla_type) { | ||
344 | case TASKSTATS_TYPE_PID: | ||
345 | rtid = *(int *) NLA_DATA(na); | ||
346 | if (print_delays) | ||
347 | printf("PID\t%d\n", rtid); | ||
348 | break; | ||
349 | case TASKSTATS_TYPE_TGID: | ||
350 | rtid = *(int *) NLA_DATA(na); | ||
351 | if (print_delays) | ||
352 | printf("TGID\t%d\n", rtid); | ||
353 | break; | ||
354 | case TASKSTATS_TYPE_STATS: | ||
355 | count++; | ||
356 | if (print_delays) | ||
357 | print_delayacct((struct taskstats *) NLA_DATA(na)); | ||
358 | if (fd) { | ||
359 | if (write(fd, NLA_DATA(na), na->nla_len) < 0) { | ||
360 | err(1,"write error\n"); | ||
361 | } | ||
362 | } | ||
363 | if (!loop) | ||
364 | goto done; | ||
365 | break; | ||
366 | default: | ||
367 | printf("Unknown nested nla_type %d\n", na->nla_type); | ||
368 | break; | ||
369 | } | ||
370 | len2 += NLA_ALIGN(na->nla_len); | ||
371 | na = (struct nlattr *) ((char *) na + len2); | ||
372 | } | ||
373 | break; | ||
374 | |||
375 | default: | ||
376 | printf("Unknown nla_type %d\n", na->nla_type); | ||
377 | break; | ||
378 | } | ||
379 | na = (struct nlattr *) (GENLMSG_DATA(&msg) + len); | ||
380 | } | ||
381 | } while (loop); | ||
382 | done: | ||
383 | if (maskset) { | ||
384 | rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET, | ||
385 | TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK, | ||
386 | &cpumask, sizeof(cpumask)); | ||
387 | printf("Sent deregister mask, retval %d\n", rc); | ||
388 | if (rc < 0) | ||
389 | err(rc, "error sending deregister cpumask\n"); | ||
390 | } | ||
391 | err: | ||
392 | close(nl_sd); | ||
393 | if (fd) | ||
394 | close(fd); | ||
395 | return 0; | ||
396 | } | ||
diff --git a/Documentation/accounting/taskstats.txt b/Documentation/accounting/taskstats.txt new file mode 100644 index 000000000000..92ebf29e9041 --- /dev/null +++ b/Documentation/accounting/taskstats.txt | |||
@@ -0,0 +1,181 @@ | |||
1 | Per-task statistics interface | ||
2 | ----------------------------- | ||
3 | |||
4 | |||
5 | Taskstats is a netlink-based interface for sending per-task and | ||
6 | per-process statistics from the kernel to userspace. | ||
7 | |||
8 | Taskstats was designed for the following benefits: | ||
9 | |||
10 | - efficiently provide statistics during lifetime of a task and on its exit | ||
11 | - unified interface for multiple accounting subsystems | ||
12 | - extensibility for use by future accounting patches | ||
13 | |||
14 | Terminology | ||
15 | ----------- | ||
16 | |||
17 | "pid", "tid" and "task" are used interchangeably and refer to the standard | ||
18 | Linux task defined by struct task_struct. per-pid stats are the same as | ||
19 | per-task stats. | ||
20 | |||
21 | "tgid", "process" and "thread group" are used interchangeably and refer to the | ||
22 | tasks that share an mm_struct i.e. the traditional Unix process. Despite the | ||
23 | use of tgid, there is no special treatment for the task that is thread group | ||
24 | leader - a process is deemed alive as long as it has any task belonging to it. | ||
25 | |||
26 | Usage | ||
27 | ----- | ||
28 | |||
29 | To get statistics during a task's lifetime, userspace opens a unicast netlink | ||
30 | socket (NETLINK_GENERIC family) and sends commands specifying a pid or a tgid. | ||
31 | The response contains statistics for a task (if pid is specified) or the sum of | ||
32 | statistics for all tasks of the process (if tgid is specified). | ||
33 | |||
34 | To obtain statistics for tasks which are exiting, the userspace listener | ||
35 | sends a register command and specifies a cpumask. Whenever a task exits on | ||
36 | one of the cpus in the cpumask, its per-pid statistics are sent to the | ||
37 | registered listener. Using cpumasks allows the data received by one listener | ||
38 | to be limited and assists in flow control over the netlink interface and is | ||
39 | explained in more detail below. | ||
40 | |||
41 | If the exiting task is the last thread exiting its thread group, | ||
42 | an additional record containing the per-tgid stats is also sent to userspace. | ||
43 | The latter contains the sum of per-pid stats for all threads in the thread | ||
44 | group, both past and present. | ||
45 | |||
46 | getdelays.c is a simple utility demonstrating usage of the taskstats interface | ||
47 | for reporting delay accounting statistics. Users can register cpumasks, | ||
48 | send commands and process responses, listen for per-tid/tgid exit data, | ||
49 | write the data received to a file and do basic flow control by increasing | ||
50 | receive buffer sizes. | ||
51 | |||
52 | Interface | ||
53 | --------- | ||
54 | |||
55 | The user-kernel interface is encapsulated in include/linux/taskstats.h | ||
56 | |||
57 | To avoid this documentation becoming obsolete as the interface evolves, only | ||
58 | an outline of the current version is given. taskstats.h always overrides the | ||
59 | description here. | ||
60 | |||
61 | struct taskstats is the common accounting structure for both per-pid and | ||
62 | per-tgid data. It is versioned and can be extended by each accounting subsystem | ||
63 | that is added to the kernel. The fields and their semantics are defined in the | ||
64 | taskstats.h file. | ||
65 | |||
66 | The data exchanged between user and kernel space is a netlink message belonging | ||
67 | to the NETLINK_GENERIC family and using the netlink attributes interface. | ||
68 | The messages are in the format | ||
69 | |||
70 | +----------+- - -+-------------+-------------------+ | ||
71 | | nlmsghdr | Pad | genlmsghdr | taskstats payload | | ||
72 | +----------+- - -+-------------+-------------------+ | ||
73 | |||
74 | |||
75 | The taskstats payload is one of the following three kinds: | ||
76 | |||
77 | 1. Commands: Sent from user to kernel. Commands to get data on | ||
78 | a pid/tgid consist of one attribute, of type TASKSTATS_CMD_ATTR_PID/TGID, | ||
79 | containing a u32 pid or tgid in the attribute payload. The pid/tgid denotes | ||
80 | the task/process for which userspace wants statistics. | ||
81 | |||
82 | Commands to register/deregister interest in exit data from a set of cpus | ||
83 | consist of one attribute, of type | ||
84 | TASKSTATS_CMD_ATTR_REGISTER/DEREGISTER_CPUMASK and contain a cpumask in the | ||
85 | attribute payload. The cpumask is specified as an ascii string of | ||
86 | comma-separated cpu ranges e.g. to listen to exit data from cpus 1,2,3,5,7,8 | ||
87 | the cpumask would be "1-3,5,7-8". If userspace forgets to deregister interest | ||
88 | in cpus before closing the listening socket, the kernel cleans up its interest | ||
89 | set over time. However, for the sake of efficiency, an explicit deregistration | ||
90 | is advisable. | ||
91 | |||
92 | 2. Response for a command: sent from the kernel in response to a userspace | ||
93 | command. The payload is a series of three attributes of type: | ||
94 | |||
95 | a) TASKSTATS_TYPE_AGGR_PID/TGID : attribute containing no payload but indicates | ||
96 | a pid/tgid will be followed by some stats. | ||
97 | |||
98 | b) TASKSTATS_TYPE_PID/TGID: attribute whose payload is the pid/tgid whose stats | ||
99 | is being returned. | ||
100 | |||
101 | c) TASKSTATS_TYPE_STATS: attribute with a struct taskstsats as payload. The | ||
102 | same structure is used for both per-pid and per-tgid stats. | ||
103 | |||
104 | 3. New message sent by kernel whenever a task exits. The payload consists of a | ||
105 | series of attributes of the following type: | ||
106 | |||
107 | a) TASKSTATS_TYPE_AGGR_PID: indicates next two attributes will be pid+stats | ||
108 | b) TASKSTATS_TYPE_PID: contains exiting task's pid | ||
109 | c) TASKSTATS_TYPE_STATS: contains the exiting task's per-pid stats | ||
110 | d) TASKSTATS_TYPE_AGGR_TGID: indicates next two attributes will be tgid+stats | ||
111 | e) TASKSTATS_TYPE_TGID: contains tgid of process to which task belongs | ||
112 | f) TASKSTATS_TYPE_STATS: contains the per-tgid stats for exiting task's process | ||
113 | |||
114 | |||
115 | per-tgid stats | ||
116 | -------------- | ||
117 | |||
118 | Taskstats provides per-process stats, in addition to per-task stats, since | ||
119 | resource management is often done at a process granularity and aggregating task | ||
120 | stats in userspace alone is inefficient and potentially inaccurate (due to lack | ||
121 | of atomicity). | ||
122 | |||
123 | However, maintaining per-process, in addition to per-task stats, within the | ||
124 | kernel has space and time overheads. To address this, the taskstats code | ||
125 | accumalates each exiting task's statistics into a process-wide data structure. | ||
126 | When the last task of a process exits, the process level data accumalated also | ||
127 | gets sent to userspace (along with the per-task data). | ||
128 | |||
129 | When a user queries to get per-tgid data, the sum of all other live threads in | ||
130 | the group is added up and added to the accumalated total for previously exited | ||
131 | threads of the same thread group. | ||
132 | |||
133 | Extending taskstats | ||
134 | ------------------- | ||
135 | |||
136 | There are two ways to extend the taskstats interface to export more | ||
137 | per-task/process stats as patches to collect them get added to the kernel | ||
138 | in future: | ||
139 | |||
140 | 1. Adding more fields to the end of the existing struct taskstats. Backward | ||
141 | compatibility is ensured by the version number within the | ||
142 | structure. Userspace will use only the fields of the struct that correspond | ||
143 | to the version its using. | ||
144 | |||
145 | 2. Defining separate statistic structs and using the netlink attributes | ||
146 | interface to return them. Since userspace processes each netlink attribute | ||
147 | independently, it can always ignore attributes whose type it does not | ||
148 | understand (because it is using an older version of the interface). | ||
149 | |||
150 | |||
151 | Choosing between 1. and 2. is a matter of trading off flexibility and | ||
152 | overhead. If only a few fields need to be added, then 1. is the preferable | ||
153 | path since the kernel and userspace don't need to incur the overhead of | ||
154 | processing new netlink attributes. But if the new fields expand the existing | ||
155 | struct too much, requiring disparate userspace accounting utilities to | ||
156 | unnecessarily receive large structures whose fields are of no interest, then | ||
157 | extending the attributes structure would be worthwhile. | ||
158 | |||
159 | Flow control for taskstats | ||
160 | -------------------------- | ||
161 | |||
162 | When the rate of task exits becomes large, a listener may not be able to keep | ||
163 | up with the kernel's rate of sending per-tid/tgid exit data leading to data | ||
164 | loss. This possibility gets compounded when the taskstats structure gets | ||
165 | extended and the number of cpus grows large. | ||
166 | |||
167 | To avoid losing statistics, userspace should do one or more of the following: | ||
168 | |||
169 | - increase the receive buffer sizes for the netlink sockets opened by | ||
170 | listeners to receive exit data. | ||
171 | |||
172 | - create more listeners and reduce the number of cpus being listened to by | ||
173 | each listener. In the extreme case, there could be one listener for each cpu. | ||
174 | Users may also consider setting the cpu affinity of the listener to the subset | ||
175 | of cpus to which it listens, especially if they are listening to just one cpu. | ||
176 | |||
177 | Despite these measures, if the userspace receives ENOBUFS error messages | ||
178 | indicated overflow of receive buffers, it should take measures to handle the | ||
179 | loss of data. | ||
180 | |||
181 | ---- | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 149f62ba14a5..e11f7728ec6f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -448,6 +448,8 @@ running once the system is up. | |||
448 | Format: <area>[,<node>] | 448 | Format: <area>[,<node>] |
449 | See also Documentation/networking/decnet.txt. | 449 | See also Documentation/networking/decnet.txt. |
450 | 450 | ||
451 | delayacct [KNL] Enable per-task delay accounting | ||
452 | |||
451 | dhash_entries= [KNL] | 453 | dhash_entries= [KNL] |
452 | Set number of hash buckets for dentry cache. | 454 | Set number of hash buckets for dentry cache. |
453 | 455 | ||
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 28d1bc3edb1c..46b9b389df35 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt | |||
@@ -1015,10 +1015,9 @@ CPU from reordering them. | |||
1015 | There are some more advanced barrier functions: | 1015 | There are some more advanced barrier functions: |
1016 | 1016 | ||
1017 | (*) set_mb(var, value) | 1017 | (*) set_mb(var, value) |
1018 | (*) set_wmb(var, value) | ||
1019 | 1018 | ||
1020 | These assign the value to the variable and then insert at least a write | 1019 | This assigns the value to the variable and then inserts at least a write |
1021 | barrier after it, depending on the function. They aren't guaranteed to | 1020 | barrier after it, depending on the function. It isn't guaranteed to |
1022 | insert anything more than a compiler barrier in a UP compilation. | 1021 | insert anything more than a compiler barrier in a UP compilation. |
1023 | 1022 | ||
1024 | 1023 | ||
diff --git a/Documentation/ramdisk.txt b/Documentation/ramdisk.txt index 7c25584e082c..52f75b7d51c2 100644 --- a/Documentation/ramdisk.txt +++ b/Documentation/ramdisk.txt | |||
@@ -6,7 +6,7 @@ Contents: | |||
6 | 1) Overview | 6 | 1) Overview |
7 | 2) Kernel Command Line Parameters | 7 | 2) Kernel Command Line Parameters |
8 | 3) Using "rdev -r" | 8 | 3) Using "rdev -r" |
9 | 4) An Example of Creating a Compressed RAM Disk | 9 | 4) An Example of Creating a Compressed RAM Disk |
10 | 10 | ||
11 | 11 | ||
12 | 1) Overview | 12 | 1) Overview |
@@ -34,7 +34,7 @@ make it clearer. The original "ramdisk=<ram_size>" has been kept around for | |||
34 | compatibility reasons, but it may be removed in the future. | 34 | compatibility reasons, but it may be removed in the future. |
35 | 35 | ||
36 | The new RAM disk also has the ability to load compressed RAM disk images, | 36 | The new RAM disk also has the ability to load compressed RAM disk images, |
37 | allowing one to squeeze more programs onto an average installation or | 37 | allowing one to squeeze more programs onto an average installation or |
38 | rescue floppy disk. | 38 | rescue floppy disk. |
39 | 39 | ||
40 | 40 | ||
@@ -51,7 +51,7 @@ default is 4096 (4 MB) (8192 (8 MB) on S390). | |||
51 | =================== | 51 | =================== |
52 | 52 | ||
53 | This parameter tells the RAM disk driver how many bytes to use per block. The | 53 | This parameter tells the RAM disk driver how many bytes to use per block. The |
54 | default is 512. | 54 | default is 1024 (BLOCK_SIZE). |
55 | 55 | ||
56 | 56 | ||
57 | 3) Using "rdev -r" | 57 | 3) Using "rdev -r" |
@@ -70,7 +70,7 @@ These numbers are no magical secrets, as seen below: | |||
70 | ./arch/i386/kernel/setup.c:#define RAMDISK_PROMPT_FLAG 0x8000 | 70 | ./arch/i386/kernel/setup.c:#define RAMDISK_PROMPT_FLAG 0x8000 |
71 | ./arch/i386/kernel/setup.c:#define RAMDISK_LOAD_FLAG 0x4000 | 71 | ./arch/i386/kernel/setup.c:#define RAMDISK_LOAD_FLAG 0x4000 |
72 | 72 | ||
73 | Consider a typical two floppy disk setup, where you will have the | 73 | Consider a typical two floppy disk setup, where you will have the |
74 | kernel on disk one, and have already put a RAM disk image onto disk #2. | 74 | kernel on disk one, and have already put a RAM disk image onto disk #2. |
75 | 75 | ||
76 | Hence you want to set bits 0 to 13 as 0, meaning that your RAM disk | 76 | Hence you want to set bits 0 to 13 as 0, meaning that your RAM disk |
@@ -97,12 +97,12 @@ Since the default start = 0 and the default prompt = 1, you could use: | |||
97 | append = "load_ramdisk=1" | 97 | append = "load_ramdisk=1" |
98 | 98 | ||
99 | 99 | ||
100 | 4) An Example of Creating a Compressed RAM Disk | 100 | 4) An Example of Creating a Compressed RAM Disk |
101 | ---------------------------------------------- | 101 | ---------------------------------------------- |
102 | 102 | ||
103 | To create a RAM disk image, you will need a spare block device to | 103 | To create a RAM disk image, you will need a spare block device to |
104 | construct it on. This can be the RAM disk device itself, or an | 104 | construct it on. This can be the RAM disk device itself, or an |
105 | unused disk partition (such as an unmounted swap partition). For this | 105 | unused disk partition (such as an unmounted swap partition). For this |
106 | example, we will use the RAM disk device, "/dev/ram0". | 106 | example, we will use the RAM disk device, "/dev/ram0". |
107 | 107 | ||
108 | Note: This technique should not be done on a machine with less than 8 MB | 108 | Note: This technique should not be done on a machine with less than 8 MB |
diff --git a/MAINTAINERS b/MAINTAINERS index a3462c3414cd..e99028ca2f7c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -771,6 +771,7 @@ M: aliakc@web.de | |||
771 | P: Jamie Lenehan | 771 | P: Jamie Lenehan |
772 | M: lenehan@twibble.org | 772 | M: lenehan@twibble.org |
773 | W: http://twibble.org/dist/dc395x/ | 773 | W: http://twibble.org/dist/dc395x/ |
774 | L: dc395x@twibble.org | ||
774 | L: http://lists.twibble.org/mailman/listinfo/dc395x/ | 775 | L: http://lists.twibble.org/mailman/listinfo/dc395x/ |
775 | S: Maintained | 776 | S: Maintained |
776 | 777 | ||
@@ -1501,6 +1502,7 @@ P: Yi Zhu | |||
1501 | M: yi.zhu@intel.com | 1502 | M: yi.zhu@intel.com |
1502 | P: James Ketrenos | 1503 | P: James Ketrenos |
1503 | M: jketreno@linux.intel.com | 1504 | M: jketreno@linux.intel.com |
1505 | L: ipw2100-devel@lists.sourceforge.net | ||
1504 | L: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel | 1506 | L: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel |
1505 | W: http://ipw2100.sourceforge.net | 1507 | W: http://ipw2100.sourceforge.net |
1506 | S: Supported | 1508 | S: Supported |
@@ -1510,6 +1512,7 @@ P: Yi Zhu | |||
1510 | M: yi.zhu@intel.com | 1512 | M: yi.zhu@intel.com |
1511 | P: James Ketrenos | 1513 | P: James Ketrenos |
1512 | M: jketreno@linux.intel.com | 1514 | M: jketreno@linux.intel.com |
1515 | L: ipw2100-devel@lists.sourceforge.net | ||
1513 | L: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel | 1516 | L: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel |
1514 | W: http://ipw2200.sourceforge.net | 1517 | W: http://ipw2200.sourceforge.net |
1515 | S: Supported | 1518 | S: Supported |
@@ -2226,6 +2229,7 @@ S: Maintained | |||
2226 | 2229 | ||
2227 | PCMCIA SUBSYSTEM | 2230 | PCMCIA SUBSYSTEM |
2228 | P: Linux PCMCIA Team | 2231 | P: Linux PCMCIA Team |
2232 | L: linux-pcmcia@lists.infradead.org | ||
2229 | L: http://lists.infradead.org/mailman/listinfo/linux-pcmcia | 2233 | L: http://lists.infradead.org/mailman/listinfo/linux-pcmcia |
2230 | T: git kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git | 2234 | T: git kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git |
2231 | S: Maintained | 2235 | S: Maintained |
@@ -2236,6 +2240,12 @@ M: tsbogend@alpha.franken.de | |||
2236 | L: netdev@vger.kernel.org | 2240 | L: netdev@vger.kernel.org |
2237 | S: Maintained | 2241 | S: Maintained |
2238 | 2242 | ||
2243 | PER-TASK DELAY ACCOUNTING | ||
2244 | P: Shailabh Nagar | ||
2245 | M: nagar@watson.ibm.com | ||
2246 | L: linux-kernel@vger.kernel.org | ||
2247 | S: Maintained | ||
2248 | |||
2239 | PERSONALITY HANDLING | 2249 | PERSONALITY HANDLING |
2240 | P: Christoph Hellwig | 2250 | P: Christoph Hellwig |
2241 | M: hch@infradead.org | 2251 | M: hch@infradead.org |
@@ -2763,6 +2773,12 @@ P: Deepak Saxena | |||
2763 | M: dsaxena@plexity.net | 2773 | M: dsaxena@plexity.net |
2764 | S: Maintained | 2774 | S: Maintained |
2765 | 2775 | ||
2776 | TASKSTATS STATISTICS INTERFACE | ||
2777 | P: Shailabh Nagar | ||
2778 | M: nagar@watson.ibm.com | ||
2779 | L: linux-kernel@vger.kernel.org | ||
2780 | S: Maintained | ||
2781 | |||
2766 | TI PARALLEL LINK CABLE DRIVER | 2782 | TI PARALLEL LINK CABLE DRIVER |
2767 | P: Romain Lievin | 2783 | P: Romain Lievin |
2768 | M: roms@lpg.ticalc.org | 2784 | M: roms@lpg.ticalc.org |
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c index 48f0f62f781c..5b96f038367f 100644 --- a/arch/i386/kernel/crash.c +++ b/arch/i386/kernel/crash.c | |||
@@ -90,7 +90,7 @@ static void crash_save_self(struct pt_regs *regs) | |||
90 | crash_save_this_cpu(regs, cpu); | 90 | crash_save_this_cpu(regs, cpu); |
91 | } | 91 | } |
92 | 92 | ||
93 | #ifdef CONFIG_SMP | 93 | #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC) |
94 | static atomic_t waiting_for_crash_ipi; | 94 | static atomic_t waiting_for_crash_ipi; |
95 | 95 | ||
96 | static int crash_nmi_callback(struct pt_regs *regs, int cpu) | 96 | static int crash_nmi_callback(struct pt_regs *regs, int cpu) |
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 7864395c1441..f1682206d304 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
@@ -1327,7 +1327,10 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat | |||
1327 | res->start = e820.map[i].addr; | 1327 | res->start = e820.map[i].addr; |
1328 | res->end = res->start + e820.map[i].size - 1; | 1328 | res->end = res->start + e820.map[i].size - 1; |
1329 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; | 1329 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; |
1330 | request_resource(&iomem_resource, res); | 1330 | if (request_resource(&iomem_resource, res)) { |
1331 | kfree(res); | ||
1332 | continue; | ||
1333 | } | ||
1331 | if (e820.map[i].type == E820_RAM) { | 1334 | if (e820.map[i].type == E820_RAM) { |
1332 | /* | 1335 | /* |
1333 | * We don't know which RAM region contains kernel data, | 1336 | * We don't know which RAM region contains kernel data, |
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 5cfd4f42eeba..313ac1f7dc5a 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -324,35 +324,35 @@ void show_registers(struct pt_regs *regs) | |||
324 | 324 | ||
325 | static void handle_BUG(struct pt_regs *regs) | 325 | static void handle_BUG(struct pt_regs *regs) |
326 | { | 326 | { |
327 | unsigned long eip = regs->eip; | ||
327 | unsigned short ud2; | 328 | unsigned short ud2; |
328 | unsigned short line; | ||
329 | char *file; | ||
330 | char c; | ||
331 | unsigned long eip; | ||
332 | |||
333 | eip = regs->eip; | ||
334 | 329 | ||
335 | if (eip < PAGE_OFFSET) | 330 | if (eip < PAGE_OFFSET) |
336 | goto no_bug; | 331 | return; |
337 | if (__get_user(ud2, (unsigned short __user *)eip)) | 332 | if (__get_user(ud2, (unsigned short __user *)eip)) |
338 | goto no_bug; | 333 | return; |
339 | if (ud2 != 0x0b0f) | 334 | if (ud2 != 0x0b0f) |
340 | goto no_bug; | 335 | return; |
341 | if (__get_user(line, (unsigned short __user *)(eip + 2))) | ||
342 | goto bug; | ||
343 | if (__get_user(file, (char * __user *)(eip + 4)) || | ||
344 | (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) | ||
345 | file = "<bad filename>"; | ||
346 | 336 | ||
347 | printk(KERN_EMERG "------------[ cut here ]------------\n"); | 337 | printk(KERN_EMERG "------------[ cut here ]------------\n"); |
348 | printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line); | ||
349 | 338 | ||
350 | no_bug: | 339 | #ifdef CONFIG_DEBUG_BUGVERBOSE |
351 | return; | 340 | do { |
341 | unsigned short line; | ||
342 | char *file; | ||
343 | char c; | ||
352 | 344 | ||
353 | /* Here we know it was a BUG but file-n-line is unavailable */ | 345 | if (__get_user(line, (unsigned short __user *)(eip + 2))) |
354 | bug: | 346 | break; |
355 | printk(KERN_EMERG "Kernel BUG\n"); | 347 | if (__get_user(file, (char * __user *)(eip + 4)) || |
348 | (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) | ||
349 | file = "<bad filename>"; | ||
350 | |||
351 | printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line); | ||
352 | return; | ||
353 | } while (0); | ||
354 | #endif | ||
355 | printk(KERN_EMERG "Kernel BUG at [verbose debug info unavailable]\n"); | ||
356 | } | 356 | } |
357 | 357 | ||
358 | /* This is gone through when something in the kernel | 358 | /* This is gone through when something in the kernel |
diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c index 4b75212ab6dd..efc7e7d5f4d0 100644 --- a/arch/i386/lib/usercopy.c +++ b/arch/i386/lib/usercopy.c | |||
@@ -843,7 +843,6 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr | |||
843 | unsigned long | 843 | unsigned long |
844 | copy_to_user(void __user *to, const void *from, unsigned long n) | 844 | copy_to_user(void __user *to, const void *from, unsigned long n) |
845 | { | 845 | { |
846 | might_sleep(); | ||
847 | BUG_ON((long) n < 0); | 846 | BUG_ON((long) n < 0); |
848 | if (access_ok(VERIFY_WRITE, to, n)) | 847 | if (access_ok(VERIFY_WRITE, to, n)) |
849 | n = __copy_to_user(to, from, n); | 848 | n = __copy_to_user(to, from, n); |
@@ -870,7 +869,6 @@ EXPORT_SYMBOL(copy_to_user); | |||
870 | unsigned long | 869 | unsigned long |
871 | copy_from_user(void *to, const void __user *from, unsigned long n) | 870 | copy_from_user(void *to, const void __user *from, unsigned long n) |
872 | { | 871 | { |
873 | might_sleep(); | ||
874 | BUG_ON((long) n < 0); | 872 | BUG_ON((long) n < 0); |
875 | if (access_ok(VERIFY_READ, from, n)) | 873 | if (access_ok(VERIFY_READ, from, n)) |
876 | n = __copy_from_user(to, from, n); | 874 | n = __copy_from_user(to, from, n); |
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 75684b56767e..c8e9dc9d68a9 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S | |||
@@ -551,9 +551,10 @@ setup_trap_table: | |||
551 | save %sp, -192, %sp | 551 | save %sp, -192, %sp |
552 | 552 | ||
553 | /* Force interrupts to be disabled. */ | 553 | /* Force interrupts to be disabled. */ |
554 | rdpr %pstate, %o1 | 554 | rdpr %pstate, %l0 |
555 | andn %o1, PSTATE_IE, %o1 | 555 | andn %l0, PSTATE_IE, %o1 |
556 | wrpr %o1, 0x0, %pstate | 556 | wrpr %o1, 0x0, %pstate |
557 | rdpr %pil, %l1 | ||
557 | wrpr %g0, 15, %pil | 558 | wrpr %g0, 15, %pil |
558 | 559 | ||
559 | /* Make the firmware call to jump over to the Linux trap table. */ | 560 | /* Make the firmware call to jump over to the Linux trap table. */ |
@@ -622,11 +623,9 @@ setup_trap_table: | |||
622 | call init_irqwork_curcpu | 623 | call init_irqwork_curcpu |
623 | nop | 624 | nop |
624 | 625 | ||
625 | /* Now we can turn interrupts back on. */ | 626 | /* Now we can restore interrupt state. */ |
626 | rdpr %pstate, %o1 | 627 | wrpr %l0, 0, %pstate |
627 | or %o1, PSTATE_IE, %o1 | 628 | wrpr %l1, 0x0, %pil |
628 | wrpr %o1, 0, %pstate | ||
629 | wrpr %g0, 0x0, %pil | ||
630 | 629 | ||
631 | ret | 630 | ret |
632 | restore | 631 | restore |
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 197a7ffd57ee..1ec0aab68c08 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c | |||
@@ -1099,9 +1099,6 @@ static void pbm_register_toplevel_resources(struct pci_controller_info *p, | |||
1099 | { | 1099 | { |
1100 | char *name = pbm->name; | 1100 | char *name = pbm->name; |
1101 | 1101 | ||
1102 | sprintf(name, "PSYCHO%d PBM%c", | ||
1103 | p->index, | ||
1104 | (pbm == &p->pbm_A ? 'A' : 'B')); | ||
1105 | pbm->io_space.name = pbm->mem_space.name = name; | 1102 | pbm->io_space.name = pbm->mem_space.name = name; |
1106 | 1103 | ||
1107 | request_resource(&ioport_resource, &pbm->io_space); | 1104 | request_resource(&ioport_resource, &pbm->io_space); |
@@ -1203,12 +1200,13 @@ static void psycho_pbm_init(struct pci_controller_info *p, | |||
1203 | pbm->io_space.flags = IORESOURCE_IO; | 1200 | pbm->io_space.flags = IORESOURCE_IO; |
1204 | pbm->mem_space.end = pbm->mem_space.start + PSYCHO_MEMSPACE_SIZE; | 1201 | pbm->mem_space.end = pbm->mem_space.start + PSYCHO_MEMSPACE_SIZE; |
1205 | pbm->mem_space.flags = IORESOURCE_MEM; | 1202 | pbm->mem_space.flags = IORESOURCE_MEM; |
1206 | pbm_register_toplevel_resources(p, pbm); | ||
1207 | 1203 | ||
1208 | pbm->parent = p; | 1204 | pbm->parent = p; |
1209 | pbm->prom_node = dp; | 1205 | pbm->prom_node = dp; |
1210 | pbm->name = dp->full_name; | 1206 | pbm->name = dp->full_name; |
1211 | 1207 | ||
1208 | pbm_register_toplevel_resources(p, pbm); | ||
1209 | |||
1212 | printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", | 1210 | printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", |
1213 | pbm->name, | 1211 | pbm->name, |
1214 | pbm->chip_version, pbm->chip_revision); | 1212 | pbm->chip_version, pbm->chip_revision); |
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index b43de647ba73..094d3e35be18 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
@@ -928,8 +928,6 @@ static void sparc64_start_timers(void) | |||
928 | __asm__ __volatile__("wrpr %0, 0x0, %%pstate" | 928 | __asm__ __volatile__("wrpr %0, 0x0, %%pstate" |
929 | : /* no outputs */ | 929 | : /* no outputs */ |
930 | : "r" (pstate)); | 930 | : "r" (pstate)); |
931 | |||
932 | local_irq_enable(); | ||
933 | } | 931 | } |
934 | 932 | ||
935 | struct freq_table { | 933 | struct freq_table { |
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 index dffd1184c956..9558a7cf34d5 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 | |||
@@ -11,6 +11,7 @@ USER_CFLAGS += -fno-builtin -m64 | |||
11 | CHECKFLAGS += -m64 | 11 | CHECKFLAGS += -m64 |
12 | AFLAGS += -m64 | 12 | AFLAGS += -m64 |
13 | LDFLAGS += -m elf_x86_64 | 13 | LDFLAGS += -m elf_x86_64 |
14 | CPPFLAGS += -m64 | ||
14 | 15 | ||
15 | ELF_ARCH := i386:x86-64 | 16 | ELF_ARCH := i386:x86-64 |
16 | ELF_FORMAT := elf64-x86-64 | 17 | ELF_FORMAT := elf64-x86-64 |
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h index 8e7053013f7b..1b5c0131a12e 100644 --- a/arch/um/include/longjmp.h +++ b/arch/um/include/longjmp.h | |||
@@ -8,8 +8,8 @@ | |||
8 | longjmp(*buf, val); \ | 8 | longjmp(*buf, val); \ |
9 | } while(0) | 9 | } while(0) |
10 | 10 | ||
11 | #define UML_SETJMP(buf, enable) ({ \ | 11 | #define UML_SETJMP(buf) ({ \ |
12 | int n; \ | 12 | int n, enable; \ |
13 | enable = get_signals(); \ | 13 | enable = get_signals(); \ |
14 | n = setjmp(*buf); \ | 14 | n = setjmp(*buf); \ |
15 | if(n != 0) \ | 15 | if(n != 0) \ |
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index b6c52496e15a..5316e8a4a4fd 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
@@ -15,9 +15,9 @@ | |||
15 | #include "irq_user.h" | 15 | #include "irq_user.h" |
16 | #include "sysdep/tls.h" | 16 | #include "sysdep/tls.h" |
17 | 17 | ||
18 | #define OS_TYPE_FILE 1 | 18 | #define OS_TYPE_FILE 1 |
19 | #define OS_TYPE_DIR 2 | 19 | #define OS_TYPE_DIR 2 |
20 | #define OS_TYPE_SYMLINK 3 | 20 | #define OS_TYPE_SYMLINK 3 |
21 | #define OS_TYPE_CHARDEV 4 | 21 | #define OS_TYPE_CHARDEV 4 |
22 | #define OS_TYPE_BLOCKDEV 5 | 22 | #define OS_TYPE_BLOCKDEV 5 |
23 | #define OS_TYPE_FIFO 6 | 23 | #define OS_TYPE_FIFO 6 |
@@ -61,68 +61,68 @@ struct openflags { | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | #define OPENFLAGS() ((struct openflags) { .r = 0, .w = 0, .s = 0, .c = 0, \ | 63 | #define OPENFLAGS() ((struct openflags) { .r = 0, .w = 0, .s = 0, .c = 0, \ |
64 | .t = 0, .a = 0, .e = 0, .cl = 0 }) | 64 | .t = 0, .a = 0, .e = 0, .cl = 0 }) |
65 | 65 | ||
66 | static inline struct openflags of_read(struct openflags flags) | 66 | static inline struct openflags of_read(struct openflags flags) |
67 | { | 67 | { |
68 | flags.r = 1; | 68 | flags.r = 1; |
69 | return(flags); | 69 | return flags; |
70 | } | 70 | } |
71 | 71 | ||
72 | static inline struct openflags of_write(struct openflags flags) | 72 | static inline struct openflags of_write(struct openflags flags) |
73 | { | 73 | { |
74 | flags.w = 1; | 74 | flags.w = 1; |
75 | return(flags); | 75 | return flags; |
76 | } | 76 | } |
77 | 77 | ||
78 | static inline struct openflags of_rdwr(struct openflags flags) | 78 | static inline struct openflags of_rdwr(struct openflags flags) |
79 | { | 79 | { |
80 | return(of_read(of_write(flags))); | 80 | return of_read(of_write(flags)); |
81 | } | 81 | } |
82 | 82 | ||
83 | static inline struct openflags of_set_rw(struct openflags flags, int r, int w) | 83 | static inline struct openflags of_set_rw(struct openflags flags, int r, int w) |
84 | { | 84 | { |
85 | flags.r = r; | 85 | flags.r = r; |
86 | flags.w = w; | 86 | flags.w = w; |
87 | return(flags); | 87 | return flags; |
88 | } | 88 | } |
89 | 89 | ||
90 | static inline struct openflags of_sync(struct openflags flags) | 90 | static inline struct openflags of_sync(struct openflags flags) |
91 | { | 91 | { |
92 | flags.s = 1; | 92 | flags.s = 1; |
93 | return(flags); | 93 | return flags; |
94 | } | 94 | } |
95 | 95 | ||
96 | static inline struct openflags of_create(struct openflags flags) | 96 | static inline struct openflags of_create(struct openflags flags) |
97 | { | 97 | { |
98 | flags.c = 1; | 98 | flags.c = 1; |
99 | return(flags); | 99 | return flags; |
100 | } | 100 | } |
101 | 101 | ||
102 | static inline struct openflags of_trunc(struct openflags flags) | 102 | static inline struct openflags of_trunc(struct openflags flags) |
103 | { | 103 | { |
104 | flags.t = 1; | 104 | flags.t = 1; |
105 | return(flags); | 105 | return flags; |
106 | } | 106 | } |
107 | 107 | ||
108 | static inline struct openflags of_append(struct openflags flags) | 108 | static inline struct openflags of_append(struct openflags flags) |
109 | { | 109 | { |
110 | flags.a = 1; | 110 | flags.a = 1; |
111 | return(flags); | 111 | return flags; |
112 | } | 112 | } |
113 | 113 | ||
114 | static inline struct openflags of_excl(struct openflags flags) | 114 | static inline struct openflags of_excl(struct openflags flags) |
115 | { | 115 | { |
116 | flags.e = 1; | 116 | flags.e = 1; |
117 | return(flags); | 117 | return flags; |
118 | } | 118 | } |
119 | 119 | ||
120 | static inline struct openflags of_cloexec(struct openflags flags) | 120 | static inline struct openflags of_cloexec(struct openflags flags) |
121 | { | 121 | { |
122 | flags.cl = 1; | 122 | flags.cl = 1; |
123 | return(flags); | 123 | return flags; |
124 | } | 124 | } |
125 | 125 | ||
126 | /* file.c */ | 126 | /* file.c */ |
127 | extern int os_stat_file(const char *file_name, struct uml_stat *buf); | 127 | extern int os_stat_file(const char *file_name, struct uml_stat *buf); |
128 | extern int os_stat_fd(const int fd, struct uml_stat *buf); | 128 | extern int os_stat_fd(const int fd, struct uml_stat *buf); |
@@ -204,7 +204,7 @@ extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); | |||
204 | 204 | ||
205 | extern int os_map_memory(void *virt, int fd, unsigned long long off, | 205 | extern int os_map_memory(void *virt, int fd, unsigned long long off, |
206 | unsigned long len, int r, int w, int x); | 206 | unsigned long len, int r, int w, int x); |
207 | extern int os_protect_memory(void *addr, unsigned long len, | 207 | extern int os_protect_memory(void *addr, unsigned long len, |
208 | int r, int w, int x); | 208 | int r, int w, int x); |
209 | extern int os_unmap_memory(void *addr, int len); | 209 | extern int os_unmap_memory(void *addr, int len); |
210 | extern int os_drop_memory(void *addr, int length); | 210 | extern int os_drop_memory(void *addr, int length); |
diff --git a/arch/um/kernel/vmlinux.lds.S b/arch/um/kernel/vmlinux.lds.S index 72acdce205e0..f8aeb448aab6 100644 --- a/arch/um/kernel/vmlinux.lds.S +++ b/arch/um/kernel/vmlinux.lds.S | |||
@@ -1,5 +1,3 @@ | |||
1 | /* in case the preprocessor is a 32bit one */ | ||
2 | #undef i386 | ||
3 | #ifdef CONFIG_LD_SCRIPT_STATIC | 1 | #ifdef CONFIG_LD_SCRIPT_STATIC |
4 | #include "uml.lds.S" | 2 | #include "uml.lds.S" |
5 | #else | 3 | #else |
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index b1cda818f5b5..b98d3ca2cd1b 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c | |||
@@ -273,12 +273,12 @@ void init_new_thread_signals(void) | |||
273 | int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) | 273 | int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) |
274 | { | 274 | { |
275 | jmp_buf buf; | 275 | jmp_buf buf; |
276 | int n, enable; | 276 | int n; |
277 | 277 | ||
278 | *jmp_ptr = &buf; | 278 | *jmp_ptr = &buf; |
279 | n = UML_SETJMP(&buf, enable); | 279 | n = UML_SETJMP(&buf); |
280 | if(n != 0) | 280 | if(n != 0) |
281 | return(n); | 281 | return n; |
282 | (*fn)(arg); | 282 | (*fn)(arg); |
283 | return(0); | 283 | return 0; |
284 | } | 284 | } |
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index bf35572d9cfa..7baf90fda58b 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
@@ -435,7 +435,6 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, | |||
435 | { | 435 | { |
436 | unsigned long flags; | 436 | unsigned long flags; |
437 | jmp_buf switch_buf, fork_buf; | 437 | jmp_buf switch_buf, fork_buf; |
438 | int enable; | ||
439 | 438 | ||
440 | *switch_buf_ptr = &switch_buf; | 439 | *switch_buf_ptr = &switch_buf; |
441 | *fork_buf_ptr = &fork_buf; | 440 | *fork_buf_ptr = &fork_buf; |
@@ -450,7 +449,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, | |||
450 | */ | 449 | */ |
451 | flags = get_signals(); | 450 | flags = get_signals(); |
452 | block_signals(); | 451 | block_signals(); |
453 | if(UML_SETJMP(&fork_buf, enable) == 0) | 452 | if(UML_SETJMP(&fork_buf) == 0) |
454 | new_thread_proc(stack, handler); | 453 | new_thread_proc(stack, handler); |
455 | 454 | ||
456 | remove_sigstack(); | 455 | remove_sigstack(); |
@@ -467,21 +466,19 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, | |||
467 | void thread_wait(void *sw, void *fb) | 466 | void thread_wait(void *sw, void *fb) |
468 | { | 467 | { |
469 | jmp_buf buf, **switch_buf = sw, *fork_buf; | 468 | jmp_buf buf, **switch_buf = sw, *fork_buf; |
470 | int enable; | ||
471 | 469 | ||
472 | *switch_buf = &buf; | 470 | *switch_buf = &buf; |
473 | fork_buf = fb; | 471 | fork_buf = fb; |
474 | if(UML_SETJMP(&buf, enable) == 0) | 472 | if(UML_SETJMP(&buf) == 0) |
475 | siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); | 473 | siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); |
476 | } | 474 | } |
477 | 475 | ||
478 | void switch_threads(void *me, void *next) | 476 | void switch_threads(void *me, void *next) |
479 | { | 477 | { |
480 | jmp_buf my_buf, **me_ptr = me, *next_buf = next; | 478 | jmp_buf my_buf, **me_ptr = me, *next_buf = next; |
481 | int enable; | ||
482 | 479 | ||
483 | *me_ptr = &my_buf; | 480 | *me_ptr = &my_buf; |
484 | if(UML_SETJMP(&my_buf, enable) == 0) | 481 | if(UML_SETJMP(&my_buf) == 0) |
485 | UML_LONGJMP(next_buf, 1); | 482 | UML_LONGJMP(next_buf, 1); |
486 | } | 483 | } |
487 | 484 | ||
@@ -495,14 +492,14 @@ static jmp_buf *cb_back; | |||
495 | int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) | 492 | int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) |
496 | { | 493 | { |
497 | jmp_buf **switch_buf = switch_buf_ptr; | 494 | jmp_buf **switch_buf = switch_buf_ptr; |
498 | int n, enable; | 495 | int n; |
499 | 496 | ||
500 | set_handler(SIGWINCH, (__sighandler_t) sig_handler, | 497 | set_handler(SIGWINCH, (__sighandler_t) sig_handler, |
501 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, | 498 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, |
502 | SIGVTALRM, -1); | 499 | SIGVTALRM, -1); |
503 | 500 | ||
504 | *fork_buf_ptr = &initial_jmpbuf; | 501 | *fork_buf_ptr = &initial_jmpbuf; |
505 | n = UML_SETJMP(&initial_jmpbuf, enable); | 502 | n = UML_SETJMP(&initial_jmpbuf); |
506 | switch(n){ | 503 | switch(n){ |
507 | case INIT_JMP_NEW_THREAD: | 504 | case INIT_JMP_NEW_THREAD: |
508 | new_thread_proc((void *) stack, new_thread_handler); | 505 | new_thread_proc((void *) stack, new_thread_handler); |
@@ -529,14 +526,13 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) | |||
529 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) | 526 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) |
530 | { | 527 | { |
531 | jmp_buf here; | 528 | jmp_buf here; |
532 | int enable; | ||
533 | 529 | ||
534 | cb_proc = proc; | 530 | cb_proc = proc; |
535 | cb_arg = arg; | 531 | cb_arg = arg; |
536 | cb_back = &here; | 532 | cb_back = &here; |
537 | 533 | ||
538 | block_signals(); | 534 | block_signals(); |
539 | if(UML_SETJMP(&here, enable) == 0) | 535 | if(UML_SETJMP(&here) == 0) |
540 | UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); | 536 | UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); |
541 | unblock_signals(); | 537 | unblock_signals(); |
542 | 538 | ||
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c index e523719330b2..865f6a6a2590 100644 --- a/arch/um/os-Linux/uaccess.c +++ b/arch/um/os-Linux/uaccess.c | |||
@@ -14,11 +14,10 @@ unsigned long __do_user_copy(void *to, const void *from, int n, | |||
14 | int n), int *faulted_out) | 14 | int n), int *faulted_out) |
15 | { | 15 | { |
16 | unsigned long *faddrp = (unsigned long *) fault_addr, ret; | 16 | unsigned long *faddrp = (unsigned long *) fault_addr, ret; |
17 | int enable; | ||
18 | 17 | ||
19 | jmp_buf jbuf; | 18 | jmp_buf jbuf; |
20 | *fault_catcher = &jbuf; | 19 | *fault_catcher = &jbuf; |
21 | if(UML_SETJMP(&jbuf, enable) == 0){ | 20 | if(UML_SETJMP(&jbuf) == 0){ |
22 | (*op)(to, from, n); | 21 | (*op)(to, from, n); |
23 | ret = 0; | 22 | ret = 0; |
24 | *faulted_out = 0; | 23 | *faulted_out = 0; |
diff --git a/block/ioctl.c b/block/ioctl.c index 9cfa2e1ecb24..309760b7e37f 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
@@ -72,7 +72,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user | |||
72 | bdevp = bdget_disk(disk, part); | 72 | bdevp = bdget_disk(disk, part); |
73 | if (!bdevp) | 73 | if (!bdevp) |
74 | return -ENOMEM; | 74 | return -ENOMEM; |
75 | mutex_lock(&bdevp->bd_mutex); | 75 | mutex_lock_nested(&bdevp->bd_mutex, BD_MUTEX_PARTITION); |
76 | if (bdevp->bd_openers) { | 76 | if (bdevp->bd_openers) { |
77 | mutex_unlock(&bdevp->bd_mutex); | 77 | mutex_unlock(&bdevp->bd_mutex); |
78 | bdput(bdevp); | 78 | bdput(bdevp); |
@@ -82,7 +82,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user | |||
82 | fsync_bdev(bdevp); | 82 | fsync_bdev(bdevp); |
83 | invalidate_bdev(bdevp, 0); | 83 | invalidate_bdev(bdevp, 0); |
84 | 84 | ||
85 | mutex_lock(&bdev->bd_mutex); | 85 | mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_WHOLE); |
86 | delete_partition(disk, part); | 86 | delete_partition(disk, part); |
87 | mutex_unlock(&bdev->bd_mutex); | 87 | mutex_unlock(&bdev->bd_mutex); |
88 | mutex_unlock(&bdevp->bd_mutex); | 88 | mutex_unlock(&bdevp->bd_mutex); |
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 93d94749310b..b5382cedf0c0 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
@@ -400,6 +400,16 @@ config BLK_DEV_RAM_SIZE | |||
400 | what are you doing. If you are using IBM S/390, then set this to | 400 | what are you doing. If you are using IBM S/390, then set this to |
401 | 8192. | 401 | 8192. |
402 | 402 | ||
403 | config BLK_DEV_RAM_BLOCKSIZE | ||
404 | int "Default RAM disk block size (bytes)" | ||
405 | depends on BLK_DEV_RAM | ||
406 | default "1024" | ||
407 | help | ||
408 | The default value is 1024 kilobytes. PAGE_SIZE is a much more | ||
409 | efficient choice however. The default is kept to ensure initrd | ||
410 | setups function - apparently needed by the rd_load_image routine | ||
411 | that supposes the filesystem in the image uses a 1024 blocksize. | ||
412 | |||
403 | config BLK_DEV_INITRD | 413 | config BLK_DEV_INITRD |
404 | bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support" | 414 | bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support" |
405 | depends on BROKEN || !FRV | 415 | depends on BROKEN || !FRV |
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 757f42dd8e86..78082edc14b4 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c | |||
@@ -1739,8 +1739,6 @@ static void getgeometry(int ctlr) | |||
1739 | (log_index < id_ctlr_buf->nr_drvs) | 1739 | (log_index < id_ctlr_buf->nr_drvs) |
1740 | && (log_unit < NWD); | 1740 | && (log_unit < NWD); |
1741 | log_unit++) { | 1741 | log_unit++) { |
1742 | struct gendisk *disk = ida_gendisk[ctlr][log_unit]; | ||
1743 | |||
1744 | size = sizeof(sense_log_drv_stat_t); | 1742 | size = sizeof(sense_log_drv_stat_t); |
1745 | 1743 | ||
1746 | /* | 1744 | /* |
diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 3cf246abb5ec..a3f64bfe6b58 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c | |||
@@ -84,7 +84,7 @@ int rd_size = CONFIG_BLK_DEV_RAM_SIZE; /* Size of the RAM disks */ | |||
84 | * behaviour. The default is still BLOCK_SIZE (needed by rd_load_image that | 84 | * behaviour. The default is still BLOCK_SIZE (needed by rd_load_image that |
85 | * supposes the filesystem in the image uses a BLOCK_SIZE blocksize). | 85 | * supposes the filesystem in the image uses a BLOCK_SIZE blocksize). |
86 | */ | 86 | */ |
87 | static int rd_blocksize = BLOCK_SIZE; /* blocksize of the RAM disks */ | 87 | static int rd_blocksize = CONFIG_BLK_DEV_RAM_BLOCKSIZE; |
88 | 88 | ||
89 | /* | 89 | /* |
90 | * Copyright (C) 2000 Linus Torvalds. | 90 | * Copyright (C) 2000 Linus Torvalds. |
diff --git a/drivers/char/nsc_gpio.c b/drivers/char/nsc_gpio.c index 5b91e4e25641..7719bd75810b 100644 --- a/drivers/char/nsc_gpio.c +++ b/drivers/char/nsc_gpio.c | |||
@@ -68,13 +68,11 @@ ssize_t nsc_gpio_write(struct file *file, const char __user *data, | |||
68 | amp->gpio_config(m, ~1, 0); | 68 | amp->gpio_config(m, ~1, 0); |
69 | break; | 69 | break; |
70 | case 'T': | 70 | case 'T': |
71 | dev_dbg(dev, "GPIO%d output is push pull\n", | 71 | dev_dbg(dev, "GPIO%d output is push pull\n", m); |
72 | m); | ||
73 | amp->gpio_config(m, ~2, 2); | 72 | amp->gpio_config(m, ~2, 2); |
74 | break; | 73 | break; |
75 | case 't': | 74 | case 't': |
76 | dev_dbg(dev, "GPIO%d output is open drain\n", | 75 | dev_dbg(dev, "GPIO%d output is open drain\n", m); |
77 | m); | ||
78 | amp->gpio_config(m, ~2, 0); | 76 | amp->gpio_config(m, ~2, 0); |
79 | break; | 77 | break; |
80 | case 'P': | 78 | case 'P': |
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c index 11bd78c80628..645eb81cb5a9 100644 --- a/drivers/char/pc8736x_gpio.c +++ b/drivers/char/pc8736x_gpio.c | |||
@@ -212,22 +212,21 @@ static void pc8736x_gpio_change(unsigned index) | |||
212 | pc8736x_gpio_set(index, !pc8736x_gpio_current(index)); | 212 | pc8736x_gpio_set(index, !pc8736x_gpio_current(index)); |
213 | } | 213 | } |
214 | 214 | ||
215 | static struct nsc_gpio_ops pc8736x_access = { | 215 | static struct nsc_gpio_ops pc8736x_gpio_ops = { |
216 | .owner = THIS_MODULE, | 216 | .owner = THIS_MODULE, |
217 | .gpio_config = pc8736x_gpio_configure, | 217 | .gpio_config = pc8736x_gpio_configure, |
218 | .gpio_dump = nsc_gpio_dump, | 218 | .gpio_dump = nsc_gpio_dump, |
219 | .gpio_get = pc8736x_gpio_get, | 219 | .gpio_get = pc8736x_gpio_get, |
220 | .gpio_set = pc8736x_gpio_set, | 220 | .gpio_set = pc8736x_gpio_set, |
221 | .gpio_set_high = pc8736x_gpio_set_high, | ||
222 | .gpio_set_low = pc8736x_gpio_set_low, | ||
223 | .gpio_change = pc8736x_gpio_change, | 221 | .gpio_change = pc8736x_gpio_change, |
224 | .gpio_current = pc8736x_gpio_current | 222 | .gpio_current = pc8736x_gpio_current |
225 | }; | 223 | }; |
224 | EXPORT_SYMBOL(pc8736x_gpio_ops); | ||
226 | 225 | ||
227 | static int pc8736x_gpio_open(struct inode *inode, struct file *file) | 226 | static int pc8736x_gpio_open(struct inode *inode, struct file *file) |
228 | { | 227 | { |
229 | unsigned m = iminor(inode); | 228 | unsigned m = iminor(inode); |
230 | file->private_data = &pc8736x_access; | 229 | file->private_data = &pc8736x_gpio_ops; |
231 | 230 | ||
232 | dev_dbg(&pdev->dev, "open %d\n", m); | 231 | dev_dbg(&pdev->dev, "open %d\n", m); |
233 | 232 | ||
@@ -236,7 +235,7 @@ static int pc8736x_gpio_open(struct inode *inode, struct file *file) | |||
236 | return nonseekable_open(inode, file); | 235 | return nonseekable_open(inode, file); |
237 | } | 236 | } |
238 | 237 | ||
239 | static const struct file_operations pc8736x_gpio_fops = { | 238 | static const struct file_operations pc8736x_gpio_fileops = { |
240 | .owner = THIS_MODULE, | 239 | .owner = THIS_MODULE, |
241 | .open = pc8736x_gpio_open, | 240 | .open = pc8736x_gpio_open, |
242 | .write = nsc_gpio_write, | 241 | .write = nsc_gpio_write, |
@@ -278,7 +277,7 @@ static int __init pc8736x_gpio_init(void) | |||
278 | dev_err(&pdev->dev, "no device found\n"); | 277 | dev_err(&pdev->dev, "no device found\n"); |
279 | goto undo_platform_dev_add; | 278 | goto undo_platform_dev_add; |
280 | } | 279 | } |
281 | pc8736x_access.dev = &pdev->dev; | 280 | pc8736x_gpio_ops.dev = &pdev->dev; |
282 | 281 | ||
283 | /* Verify that chip and it's GPIO unit are both enabled. | 282 | /* Verify that chip and it's GPIO unit are both enabled. |
284 | My BIOS does this, so I take minimum action here | 283 | My BIOS does this, so I take minimum action here |
@@ -328,7 +327,7 @@ static int __init pc8736x_gpio_init(void) | |||
328 | pc8736x_init_shadow(); | 327 | pc8736x_init_shadow(); |
329 | 328 | ||
330 | /* ignore minor errs, and succeed */ | 329 | /* ignore minor errs, and succeed */ |
331 | cdev_init(&pc8736x_gpio_cdev, &pc8736x_gpio_fops); | 330 | cdev_init(&pc8736x_gpio_cdev, &pc8736x_gpio_fileops); |
332 | cdev_add(&pc8736x_gpio_cdev, devid, PC8736X_GPIO_CT); | 331 | cdev_add(&pc8736x_gpio_cdev, devid, PC8736X_GPIO_CT); |
333 | 332 | ||
334 | return 0; | 333 | return 0; |
@@ -355,7 +354,5 @@ static void __exit pc8736x_gpio_cleanup(void) | |||
355 | platform_device_put(pdev); | 354 | platform_device_put(pdev); |
356 | } | 355 | } |
357 | 356 | ||
358 | EXPORT_SYMBOL(pc8736x_access); | ||
359 | |||
360 | module_init(pc8736x_gpio_init); | 357 | module_init(pc8736x_gpio_init); |
361 | module_exit(pc8736x_gpio_cleanup); | 358 | module_exit(pc8736x_gpio_cleanup); |
diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c index 425c58719db6..b956c7babd18 100644 --- a/drivers/char/scx200_gpio.c +++ b/drivers/char/scx200_gpio.c | |||
@@ -5,7 +5,6 @@ | |||
5 | 5 | ||
6 | Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> */ | 6 | Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> */ |
7 | 7 | ||
8 | #include <linux/config.h> | ||
9 | #include <linux/device.h> | 8 | #include <linux/device.h> |
10 | #include <linux/fs.h> | 9 | #include <linux/fs.h> |
11 | #include <linux/module.h> | 10 | #include <linux/module.h> |
@@ -22,37 +21,37 @@ | |||
22 | #include <linux/scx200_gpio.h> | 21 | #include <linux/scx200_gpio.h> |
23 | #include <linux/nsc_gpio.h> | 22 | #include <linux/nsc_gpio.h> |
24 | 23 | ||
25 | #define NAME "scx200_gpio" | 24 | #define DRVNAME "scx200_gpio" |
26 | #define DEVNAME NAME | ||
27 | 25 | ||
28 | static struct platform_device *pdev; | 26 | static struct platform_device *pdev; |
29 | 27 | ||
30 | MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>"); | 28 | MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>"); |
31 | MODULE_DESCRIPTION("NatSemi SCx200 GPIO Pin Driver"); | 29 | MODULE_DESCRIPTION("NatSemi/AMD SCx200 GPIO Pin Driver"); |
32 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
33 | 31 | ||
34 | static int major = 0; /* default to dynamic major */ | 32 | static int major = 0; /* default to dynamic major */ |
35 | module_param(major, int, 0); | 33 | module_param(major, int, 0); |
36 | MODULE_PARM_DESC(major, "Major device number"); | 34 | MODULE_PARM_DESC(major, "Major device number"); |
37 | 35 | ||
38 | struct nsc_gpio_ops scx200_access = { | 36 | #define MAX_PINS 32 /* 64 later, when known ok */ |
37 | |||
38 | struct nsc_gpio_ops scx200_gpio_ops = { | ||
39 | .owner = THIS_MODULE, | 39 | .owner = THIS_MODULE, |
40 | .gpio_config = scx200_gpio_configure, | 40 | .gpio_config = scx200_gpio_configure, |
41 | .gpio_dump = nsc_gpio_dump, | 41 | .gpio_dump = nsc_gpio_dump, |
42 | .gpio_get = scx200_gpio_get, | 42 | .gpio_get = scx200_gpio_get, |
43 | .gpio_set = scx200_gpio_set, | 43 | .gpio_set = scx200_gpio_set, |
44 | .gpio_set_high = scx200_gpio_set_high, | ||
45 | .gpio_set_low = scx200_gpio_set_low, | ||
46 | .gpio_change = scx200_gpio_change, | 44 | .gpio_change = scx200_gpio_change, |
47 | .gpio_current = scx200_gpio_current | 45 | .gpio_current = scx200_gpio_current |
48 | }; | 46 | }; |
47 | EXPORT_SYMBOL(scx200_gpio_ops); | ||
49 | 48 | ||
50 | static int scx200_gpio_open(struct inode *inode, struct file *file) | 49 | static int scx200_gpio_open(struct inode *inode, struct file *file) |
51 | { | 50 | { |
52 | unsigned m = iminor(inode); | 51 | unsigned m = iminor(inode); |
53 | file->private_data = &scx200_access; | 52 | file->private_data = &scx200_gpio_ops; |
54 | 53 | ||
55 | if (m > 63) | 54 | if (m >= MAX_PINS) |
56 | return -EINVAL; | 55 | return -EINVAL; |
57 | return nonseekable_open(inode, file); | 56 | return nonseekable_open(inode, file); |
58 | } | 57 | } |
@@ -62,8 +61,7 @@ static int scx200_gpio_release(struct inode *inode, struct file *file) | |||
62 | return 0; | 61 | return 0; |
63 | } | 62 | } |
64 | 63 | ||
65 | 64 | static const struct file_operations scx200_gpio_fileops = { | |
66 | static const struct file_operations scx200_gpio_fops = { | ||
67 | .owner = THIS_MODULE, | 65 | .owner = THIS_MODULE, |
68 | .write = nsc_gpio_write, | 66 | .write = nsc_gpio_write, |
69 | .read = nsc_gpio_read, | 67 | .read = nsc_gpio_read, |
@@ -71,21 +69,20 @@ static const struct file_operations scx200_gpio_fops = { | |||
71 | .release = scx200_gpio_release, | 69 | .release = scx200_gpio_release, |
72 | }; | 70 | }; |
73 | 71 | ||
74 | struct cdev *scx200_devices; | 72 | struct cdev scx200_gpio_cdev; /* use 1 cdev for all pins */ |
75 | static int num_pins = 32; | ||
76 | 73 | ||
77 | static int __init scx200_gpio_init(void) | 74 | static int __init scx200_gpio_init(void) |
78 | { | 75 | { |
79 | int rc, i; | 76 | int rc; |
80 | dev_t dev = MKDEV(major, 0); | 77 | dev_t devid; |
81 | 78 | ||
82 | if (!scx200_gpio_present()) { | 79 | if (!scx200_gpio_present()) { |
83 | printk(KERN_ERR NAME ": no SCx200 gpio present\n"); | 80 | printk(KERN_ERR DRVNAME ": no SCx200 gpio present\n"); |
84 | return -ENODEV; | 81 | return -ENODEV; |
85 | } | 82 | } |
86 | 83 | ||
87 | /* support dev_dbg() with pdev->dev */ | 84 | /* support dev_dbg() with pdev->dev */ |
88 | pdev = platform_device_alloc(DEVNAME, 0); | 85 | pdev = platform_device_alloc(DRVNAME, 0); |
89 | if (!pdev) | 86 | if (!pdev) |
90 | return -ENOMEM; | 87 | return -ENOMEM; |
91 | 88 | ||
@@ -94,37 +91,25 @@ static int __init scx200_gpio_init(void) | |||
94 | goto undo_malloc; | 91 | goto undo_malloc; |
95 | 92 | ||
96 | /* nsc_gpio uses dev_dbg(), so needs this */ | 93 | /* nsc_gpio uses dev_dbg(), so needs this */ |
97 | scx200_access.dev = &pdev->dev; | 94 | scx200_gpio_ops.dev = &pdev->dev; |
98 | 95 | ||
99 | if (major) | 96 | if (major) { |
100 | rc = register_chrdev_region(dev, num_pins, "scx200_gpio"); | 97 | devid = MKDEV(major, 0); |
101 | else { | 98 | rc = register_chrdev_region(devid, MAX_PINS, "scx200_gpio"); |
102 | rc = alloc_chrdev_region(&dev, 0, num_pins, "scx200_gpio"); | 99 | } else { |
103 | major = MAJOR(dev); | 100 | rc = alloc_chrdev_region(&devid, 0, MAX_PINS, "scx200_gpio"); |
101 | major = MAJOR(devid); | ||
104 | } | 102 | } |
105 | if (rc < 0) { | 103 | if (rc < 0) { |
106 | dev_err(&pdev->dev, "SCx200 chrdev_region err: %d\n", rc); | 104 | dev_err(&pdev->dev, "SCx200 chrdev_region err: %d\n", rc); |
107 | goto undo_platform_device_add; | 105 | goto undo_platform_device_add; |
108 | } | 106 | } |
109 | scx200_devices = kzalloc(num_pins * sizeof(struct cdev), GFP_KERNEL); | 107 | |
110 | if (!scx200_devices) { | 108 | cdev_init(&scx200_gpio_cdev, &scx200_gpio_fileops); |
111 | rc = -ENOMEM; | 109 | cdev_add(&scx200_gpio_cdev, devid, MAX_PINS); |
112 | goto undo_chrdev_region; | ||
113 | } | ||
114 | for (i = 0; i < num_pins; i++) { | ||
115 | struct cdev *cdev = &scx200_devices[i]; | ||
116 | cdev_init(cdev, &scx200_gpio_fops); | ||
117 | cdev->owner = THIS_MODULE; | ||
118 | rc = cdev_add(cdev, MKDEV(major, i), 1); | ||
119 | /* tolerate 'minor' errors */ | ||
120 | if (rc) | ||
121 | dev_err(&pdev->dev, "Error %d on minor %d", rc, i); | ||
122 | } | ||
123 | 110 | ||
124 | return 0; /* succeed */ | 111 | return 0; /* succeed */ |
125 | 112 | ||
126 | undo_chrdev_region: | ||
127 | unregister_chrdev_region(dev, num_pins); | ||
128 | undo_platform_device_add: | 113 | undo_platform_device_add: |
129 | platform_device_del(pdev); | 114 | platform_device_del(pdev); |
130 | undo_malloc: | 115 | undo_malloc: |
@@ -135,10 +120,11 @@ undo_malloc: | |||
135 | 120 | ||
136 | static void __exit scx200_gpio_cleanup(void) | 121 | static void __exit scx200_gpio_cleanup(void) |
137 | { | 122 | { |
138 | kfree(scx200_devices); | 123 | cdev_del(&scx200_gpio_cdev); |
139 | unregister_chrdev_region(MKDEV(major, 0), num_pins); | 124 | /* cdev_put(&scx200_gpio_cdev); */ |
125 | |||
126 | unregister_chrdev_region(MKDEV(major, 0), MAX_PINS); | ||
140 | platform_device_unregister(pdev); | 127 | platform_device_unregister(pdev); |
141 | /* kfree(pdev); */ | ||
142 | } | 128 | } |
143 | 129 | ||
144 | module_init(scx200_gpio_init); | 130 | module_init(scx200_gpio_init); |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 6889e7db3aff..a082a2e34252 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -1141,6 +1141,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend | |||
1141 | put_device(dev); | 1141 | put_device(dev); |
1142 | clear_bit(chip->dev_num, dev_mask); | 1142 | clear_bit(chip->dev_num, dev_mask); |
1143 | kfree(chip); | 1143 | kfree(chip); |
1144 | kfree(devname); | ||
1144 | return NULL; | 1145 | return NULL; |
1145 | } | 1146 | } |
1146 | 1147 | ||
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 3232b1932597..ee7ac6f43c65 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -424,6 +424,7 @@ static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
424 | iowrite32(interrupt, | 424 | iowrite32(interrupt, |
425 | chip->vendor.iobase + | 425 | chip->vendor.iobase + |
426 | TPM_INT_STATUS(chip->vendor.locality)); | 426 | TPM_INT_STATUS(chip->vendor.locality)); |
427 | ioread32(chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality)); | ||
427 | return IRQ_HANDLED; | 428 | return IRQ_HANDLED; |
428 | } | 429 | } |
429 | 430 | ||
@@ -431,23 +432,19 @@ static int interrupts = 1; | |||
431 | module_param(interrupts, bool, 0444); | 432 | module_param(interrupts, bool, 0444); |
432 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); | 433 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); |
433 | 434 | ||
434 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | 435 | static int tpm_tis_init(struct device *dev, resource_size_t start, |
435 | const struct pnp_device_id *pnp_id) | 436 | resource_size_t len) |
436 | { | 437 | { |
437 | u32 vendor, intfcaps, intmask; | 438 | u32 vendor, intfcaps, intmask; |
438 | int rc, i; | 439 | int rc, i; |
439 | unsigned long start, len; | ||
440 | struct tpm_chip *chip; | 440 | struct tpm_chip *chip; |
441 | 441 | ||
442 | start = pnp_mem_start(pnp_dev, 0); | ||
443 | len = pnp_mem_len(pnp_dev, 0); | ||
444 | |||
445 | if (!start) | 442 | if (!start) |
446 | start = TIS_MEM_BASE; | 443 | start = TIS_MEM_BASE; |
447 | if (!len) | 444 | if (!len) |
448 | len = TIS_MEM_LEN; | 445 | len = TIS_MEM_LEN; |
449 | 446 | ||
450 | if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis))) | 447 | if (!(chip = tpm_register_hardware(dev, &tpm_tis))) |
451 | return -ENODEV; | 448 | return -ENODEV; |
452 | 449 | ||
453 | chip->vendor.iobase = ioremap(start, len); | 450 | chip->vendor.iobase = ioremap(start, len); |
@@ -464,7 +461,7 @@ static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | |||
464 | chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | 461 | chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); |
465 | chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | 462 | chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); |
466 | 463 | ||
467 | dev_info(&pnp_dev->dev, | 464 | dev_info(dev, |
468 | "1.2 TPM (device-id 0x%X, rev-id %d)\n", | 465 | "1.2 TPM (device-id 0x%X, rev-id %d)\n", |
469 | vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); | 466 | vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); |
470 | 467 | ||
@@ -472,26 +469,26 @@ static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | |||
472 | intfcaps = | 469 | intfcaps = |
473 | ioread32(chip->vendor.iobase + | 470 | ioread32(chip->vendor.iobase + |
474 | TPM_INTF_CAPS(chip->vendor.locality)); | 471 | TPM_INTF_CAPS(chip->vendor.locality)); |
475 | dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n", | 472 | dev_dbg(dev, "TPM interface capabilities (0x%x):\n", |
476 | intfcaps); | 473 | intfcaps); |
477 | if (intfcaps & TPM_INTF_BURST_COUNT_STATIC) | 474 | if (intfcaps & TPM_INTF_BURST_COUNT_STATIC) |
478 | dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n"); | 475 | dev_dbg(dev, "\tBurst Count Static\n"); |
479 | if (intfcaps & TPM_INTF_CMD_READY_INT) | 476 | if (intfcaps & TPM_INTF_CMD_READY_INT) |
480 | dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n"); | 477 | dev_dbg(dev, "\tCommand Ready Int Support\n"); |
481 | if (intfcaps & TPM_INTF_INT_EDGE_FALLING) | 478 | if (intfcaps & TPM_INTF_INT_EDGE_FALLING) |
482 | dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n"); | 479 | dev_dbg(dev, "\tInterrupt Edge Falling\n"); |
483 | if (intfcaps & TPM_INTF_INT_EDGE_RISING) | 480 | if (intfcaps & TPM_INTF_INT_EDGE_RISING) |
484 | dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n"); | 481 | dev_dbg(dev, "\tInterrupt Edge Rising\n"); |
485 | if (intfcaps & TPM_INTF_INT_LEVEL_LOW) | 482 | if (intfcaps & TPM_INTF_INT_LEVEL_LOW) |
486 | dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n"); | 483 | dev_dbg(dev, "\tInterrupt Level Low\n"); |
487 | if (intfcaps & TPM_INTF_INT_LEVEL_HIGH) | 484 | if (intfcaps & TPM_INTF_INT_LEVEL_HIGH) |
488 | dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n"); | 485 | dev_dbg(dev, "\tInterrupt Level High\n"); |
489 | if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) | 486 | if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) |
490 | dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n"); | 487 | dev_dbg(dev, "\tLocality Change Int Support\n"); |
491 | if (intfcaps & TPM_INTF_STS_VALID_INT) | 488 | if (intfcaps & TPM_INTF_STS_VALID_INT) |
492 | dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n"); | 489 | dev_dbg(dev, "\tSts Valid Int Support\n"); |
493 | if (intfcaps & TPM_INTF_DATA_AVAIL_INT) | 490 | if (intfcaps & TPM_INTF_DATA_AVAIL_INT) |
494 | dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n"); | 491 | dev_dbg(dev, "\tData Avail Int Support\n"); |
495 | 492 | ||
496 | if (request_locality(chip, 0) != 0) { | 493 | if (request_locality(chip, 0) != 0) { |
497 | rc = -ENODEV; | 494 | rc = -ENODEV; |
@@ -594,6 +591,16 @@ out_err: | |||
594 | return rc; | 591 | return rc; |
595 | } | 592 | } |
596 | 593 | ||
594 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | ||
595 | const struct pnp_device_id *pnp_id) | ||
596 | { | ||
597 | resource_size_t start, len; | ||
598 | start = pnp_mem_start(pnp_dev, 0); | ||
599 | len = pnp_mem_len(pnp_dev, 0); | ||
600 | |||
601 | return tpm_tis_init(&pnp_dev->dev, start, len); | ||
602 | } | ||
603 | |||
597 | static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg) | 604 | static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg) |
598 | { | 605 | { |
599 | return tpm_pm_suspend(&dev->dev, msg); | 606 | return tpm_pm_suspend(&dev->dev, msg); |
@@ -628,8 +635,36 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, | |||
628 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); | 635 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); |
629 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | 636 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); |
630 | 637 | ||
638 | static struct device_driver tis_drv = { | ||
639 | .name = "tpm_tis", | ||
640 | .bus = &platform_bus_type, | ||
641 | .owner = THIS_MODULE, | ||
642 | .suspend = tpm_pm_suspend, | ||
643 | .resume = tpm_pm_resume, | ||
644 | }; | ||
645 | |||
646 | static struct platform_device *pdev; | ||
647 | |||
648 | static int force; | ||
649 | module_param(force, bool, 0444); | ||
650 | MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); | ||
631 | static int __init init_tis(void) | 651 | static int __init init_tis(void) |
632 | { | 652 | { |
653 | int rc; | ||
654 | |||
655 | if (force) { | ||
656 | rc = driver_register(&tis_drv); | ||
657 | if (rc < 0) | ||
658 | return rc; | ||
659 | if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) | ||
660 | return PTR_ERR(pdev); | ||
661 | if((rc=tpm_tis_init(&pdev->dev, 0, 0)) != 0) { | ||
662 | platform_device_unregister(pdev); | ||
663 | driver_unregister(&tis_drv); | ||
664 | } | ||
665 | return rc; | ||
666 | } | ||
667 | |||
633 | return pnp_register_driver(&tis_pnp_driver); | 668 | return pnp_register_driver(&tis_pnp_driver); |
634 | } | 669 | } |
635 | 670 | ||
@@ -654,7 +689,11 @@ static void __exit cleanup_tis(void) | |||
654 | tpm_remove_hardware(chip->dev); | 689 | tpm_remove_hardware(chip->dev); |
655 | } | 690 | } |
656 | spin_unlock(&tis_lock); | 691 | spin_unlock(&tis_lock); |
657 | pnp_unregister_driver(&tis_pnp_driver); | 692 | if (force) { |
693 | platform_device_unregister(pdev); | ||
694 | driver_unregister(&tis_drv); | ||
695 | } else | ||
696 | pnp_unregister_driver(&tis_pnp_driver); | ||
658 | } | 697 | } |
659 | 698 | ||
660 | module_init(init_tis); | 699 | module_init(init_tis); |
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 3f6705f3083a..f85c97f7500a 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -701,7 +701,7 @@ static void cm_reset_to_idle(struct cm_id_private *cm_id_priv) | |||
701 | } | 701 | } |
702 | } | 702 | } |
703 | 703 | ||
704 | void ib_destroy_cm_id(struct ib_cm_id *cm_id) | 704 | static void cm_destroy_id(struct ib_cm_id *cm_id, int err) |
705 | { | 705 | { |
706 | struct cm_id_private *cm_id_priv; | 706 | struct cm_id_private *cm_id_priv; |
707 | struct cm_work *work; | 707 | struct cm_work *work; |
@@ -735,12 +735,22 @@ retest: | |||
735 | sizeof cm_id_priv->av.port->cm_dev->ca_guid, | 735 | sizeof cm_id_priv->av.port->cm_dev->ca_guid, |
736 | NULL, 0); | 736 | NULL, 0); |
737 | break; | 737 | break; |
738 | case IB_CM_REQ_RCVD: | ||
739 | if (err == -ENOMEM) { | ||
740 | /* Do not reject to allow future retries. */ | ||
741 | cm_reset_to_idle(cm_id_priv); | ||
742 | spin_unlock_irqrestore(&cm_id_priv->lock, flags); | ||
743 | } else { | ||
744 | spin_unlock_irqrestore(&cm_id_priv->lock, flags); | ||
745 | ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, | ||
746 | NULL, 0, NULL, 0); | ||
747 | } | ||
748 | break; | ||
738 | case IB_CM_MRA_REQ_RCVD: | 749 | case IB_CM_MRA_REQ_RCVD: |
739 | case IB_CM_REP_SENT: | 750 | case IB_CM_REP_SENT: |
740 | case IB_CM_MRA_REP_RCVD: | 751 | case IB_CM_MRA_REP_RCVD: |
741 | ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg); | 752 | ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg); |
742 | /* Fall through */ | 753 | /* Fall through */ |
743 | case IB_CM_REQ_RCVD: | ||
744 | case IB_CM_MRA_REQ_SENT: | 754 | case IB_CM_MRA_REQ_SENT: |
745 | case IB_CM_REP_RCVD: | 755 | case IB_CM_REP_RCVD: |
746 | case IB_CM_MRA_REP_SENT: | 756 | case IB_CM_MRA_REP_SENT: |
@@ -775,6 +785,11 @@ retest: | |||
775 | kfree(cm_id_priv->private_data); | 785 | kfree(cm_id_priv->private_data); |
776 | kfree(cm_id_priv); | 786 | kfree(cm_id_priv); |
777 | } | 787 | } |
788 | |||
789 | void ib_destroy_cm_id(struct ib_cm_id *cm_id) | ||
790 | { | ||
791 | cm_destroy_id(cm_id, 0); | ||
792 | } | ||
778 | EXPORT_SYMBOL(ib_destroy_cm_id); | 793 | EXPORT_SYMBOL(ib_destroy_cm_id); |
779 | 794 | ||
780 | int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask, | 795 | int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask, |
@@ -1163,7 +1178,7 @@ static void cm_process_work(struct cm_id_private *cm_id_priv, | |||
1163 | } | 1178 | } |
1164 | cm_deref_id(cm_id_priv); | 1179 | cm_deref_id(cm_id_priv); |
1165 | if (ret) | 1180 | if (ret) |
1166 | ib_destroy_cm_id(&cm_id_priv->id); | 1181 | cm_destroy_id(&cm_id_priv->id, ret); |
1167 | } | 1182 | } |
1168 | 1183 | ||
1169 | static void cm_format_mra(struct cm_mra_msg *mra_msg, | 1184 | static void cm_format_mra(struct cm_mra_msg *mra_msg, |
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 863f64befc7c..d6f99d5720fc 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -262,14 +262,14 @@ static void cma_detach_from_dev(struct rdma_id_private *id_priv) | |||
262 | static int cma_acquire_ib_dev(struct rdma_id_private *id_priv) | 262 | static int cma_acquire_ib_dev(struct rdma_id_private *id_priv) |
263 | { | 263 | { |
264 | struct cma_device *cma_dev; | 264 | struct cma_device *cma_dev; |
265 | union ib_gid *gid; | 265 | union ib_gid gid; |
266 | int ret = -ENODEV; | 266 | int ret = -ENODEV; |
267 | 267 | ||
268 | gid = ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr); | 268 | ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid), |
269 | 269 | ||
270 | mutex_lock(&lock); | 270 | mutex_lock(&lock); |
271 | list_for_each_entry(cma_dev, &dev_list, list) { | 271 | list_for_each_entry(cma_dev, &dev_list, list) { |
272 | ret = ib_find_cached_gid(cma_dev->device, gid, | 272 | ret = ib_find_cached_gid(cma_dev->device, &gid, |
273 | &id_priv->id.port_num, NULL); | 273 | &id_priv->id.port_num, NULL); |
274 | if (!ret) { | 274 | if (!ret) { |
275 | cma_attach_to_dev(id_priv, cma_dev); | 275 | cma_attach_to_dev(id_priv, cma_dev); |
@@ -812,6 +812,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) | |||
812 | cma_modify_qp_err(&id_priv->id); | 812 | cma_modify_qp_err(&id_priv->id); |
813 | status = ib_event->param.rej_rcvd.reason; | 813 | status = ib_event->param.rej_rcvd.reason; |
814 | event = RDMA_CM_EVENT_REJECTED; | 814 | event = RDMA_CM_EVENT_REJECTED; |
815 | private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE; | ||
815 | break; | 816 | break; |
816 | default: | 817 | default: |
817 | printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d", | 818 | printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d", |
@@ -1134,8 +1135,8 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, | |||
1134 | struct ib_sa_path_rec path_rec; | 1135 | struct ib_sa_path_rec path_rec; |
1135 | 1136 | ||
1136 | memset(&path_rec, 0, sizeof path_rec); | 1137 | memset(&path_rec, 0, sizeof path_rec); |
1137 | path_rec.sgid = *ib_addr_get_sgid(addr); | 1138 | ib_addr_get_sgid(addr, &path_rec.sgid); |
1138 | path_rec.dgid = *ib_addr_get_dgid(addr); | 1139 | ib_addr_get_dgid(addr, &path_rec.dgid); |
1139 | path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(addr)); | 1140 | path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(addr)); |
1140 | path_rec.numb_path = 1; | 1141 | path_rec.numb_path = 1; |
1141 | 1142 | ||
@@ -1263,7 +1264,7 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv) | |||
1263 | { | 1264 | { |
1264 | struct cma_device *cma_dev; | 1265 | struct cma_device *cma_dev; |
1265 | struct ib_port_attr port_attr; | 1266 | struct ib_port_attr port_attr; |
1266 | union ib_gid *gid; | 1267 | union ib_gid gid; |
1267 | u16 pkey; | 1268 | u16 pkey; |
1268 | int ret; | 1269 | int ret; |
1269 | u8 p; | 1270 | u8 p; |
@@ -1284,8 +1285,7 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv) | |||
1284 | } | 1285 | } |
1285 | 1286 | ||
1286 | port_found: | 1287 | port_found: |
1287 | gid = ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr); | 1288 | ret = ib_get_cached_gid(cma_dev->device, p, 0, &gid); |
1288 | ret = ib_get_cached_gid(cma_dev->device, p, 0, gid); | ||
1289 | if (ret) | 1289 | if (ret) |
1290 | goto out; | 1290 | goto out; |
1291 | 1291 | ||
@@ -1293,6 +1293,7 @@ port_found: | |||
1293 | if (ret) | 1293 | if (ret) |
1294 | goto out; | 1294 | goto out; |
1295 | 1295 | ||
1296 | ib_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid); | ||
1296 | ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); | 1297 | ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); |
1297 | id_priv->id.port_num = p; | 1298 | id_priv->id.port_num = p; |
1298 | cma_attach_to_dev(id_priv, cma_dev); | 1299 | cma_attach_to_dev(id_priv, cma_dev); |
@@ -1339,6 +1340,7 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) | |||
1339 | { | 1340 | { |
1340 | struct cma_work *work; | 1341 | struct cma_work *work; |
1341 | struct sockaddr_in *src_in, *dst_in; | 1342 | struct sockaddr_in *src_in, *dst_in; |
1343 | union ib_gid gid; | ||
1342 | int ret; | 1344 | int ret; |
1343 | 1345 | ||
1344 | work = kzalloc(sizeof *work, GFP_KERNEL); | 1346 | work = kzalloc(sizeof *work, GFP_KERNEL); |
@@ -1351,8 +1353,8 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) | |||
1351 | goto err; | 1353 | goto err; |
1352 | } | 1354 | } |
1353 | 1355 | ||
1354 | ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr, | 1356 | ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid); |
1355 | ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr)); | 1357 | ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid); |
1356 | 1358 | ||
1357 | if (cma_zero_addr(&id_priv->id.route.addr.src_addr)) { | 1359 | if (cma_zero_addr(&id_priv->id.route.addr.src_addr)) { |
1358 | src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr; | 1360 | src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr; |
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c index 615fe9cc6c56..86a3b2d401db 100644 --- a/drivers/infiniband/core/fmr_pool.c +++ b/drivers/infiniband/core/fmr_pool.c | |||
@@ -426,7 +426,7 @@ EXPORT_SYMBOL(ib_flush_fmr_pool); | |||
426 | struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle, | 426 | struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle, |
427 | u64 *page_list, | 427 | u64 *page_list, |
428 | int list_len, | 428 | int list_len, |
429 | u64 *io_virtual_address) | 429 | u64 io_virtual_address) |
430 | { | 430 | { |
431 | struct ib_fmr_pool *pool = pool_handle; | 431 | struct ib_fmr_pool *pool = pool_handle; |
432 | struct ib_pool_fmr *fmr; | 432 | struct ib_pool_fmr *fmr; |
@@ -440,7 +440,7 @@ struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle, | |||
440 | fmr = ib_fmr_cache_lookup(pool, | 440 | fmr = ib_fmr_cache_lookup(pool, |
441 | page_list, | 441 | page_list, |
442 | list_len, | 442 | list_len, |
443 | *io_virtual_address); | 443 | io_virtual_address); |
444 | if (fmr) { | 444 | if (fmr) { |
445 | /* found in cache */ | 445 | /* found in cache */ |
446 | ++fmr->ref_count; | 446 | ++fmr->ref_count; |
@@ -464,7 +464,7 @@ struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle, | |||
464 | spin_unlock_irqrestore(&pool->pool_lock, flags); | 464 | spin_unlock_irqrestore(&pool->pool_lock, flags); |
465 | 465 | ||
466 | result = ib_map_phys_fmr(fmr->fmr, page_list, list_len, | 466 | result = ib_map_phys_fmr(fmr->fmr, page_list, list_len, |
467 | *io_virtual_address); | 467 | io_virtual_address); |
468 | 468 | ||
469 | if (result) { | 469 | if (result) { |
470 | spin_lock_irqsave(&pool->pool_lock, flags); | 470 | spin_lock_irqsave(&pool->pool_lock, flags); |
@@ -481,7 +481,7 @@ struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle, | |||
481 | fmr->ref_count = 1; | 481 | fmr->ref_count = 1; |
482 | 482 | ||
483 | if (pool->cache_bucket) { | 483 | if (pool->cache_bucket) { |
484 | fmr->io_virtual_address = *io_virtual_address; | 484 | fmr->io_virtual_address = io_virtual_address; |
485 | fmr->page_list_len = list_len; | 485 | fmr->page_list_len = list_len; |
486 | memcpy(fmr->page_list, page_list, list_len * sizeof(*page_list)); | 486 | memcpy(fmr->page_list, page_list, list_len * sizeof(*page_list)); |
487 | 487 | ||
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index e911c99ff843..aeda484ffd82 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c | |||
@@ -488,13 +488,13 @@ static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent) | |||
488 | spin_unlock_irqrestore(&tid_lock, flags); | 488 | spin_unlock_irqrestore(&tid_lock, flags); |
489 | } | 489 | } |
490 | 490 | ||
491 | static int send_mad(struct ib_sa_query *query, int timeout_ms) | 491 | static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask) |
492 | { | 492 | { |
493 | unsigned long flags; | 493 | unsigned long flags; |
494 | int ret, id; | 494 | int ret, id; |
495 | 495 | ||
496 | retry: | 496 | retry: |
497 | if (!idr_pre_get(&query_idr, GFP_ATOMIC)) | 497 | if (!idr_pre_get(&query_idr, gfp_mask)) |
498 | return -ENOMEM; | 498 | return -ENOMEM; |
499 | spin_lock_irqsave(&idr_lock, flags); | 499 | spin_lock_irqsave(&idr_lock, flags); |
500 | ret = idr_get_new(&query_idr, query, &id); | 500 | ret = idr_get_new(&query_idr, query, &id); |
@@ -630,7 +630,7 @@ int ib_sa_path_rec_get(struct ib_device *device, u8 port_num, | |||
630 | 630 | ||
631 | *sa_query = &query->sa_query; | 631 | *sa_query = &query->sa_query; |
632 | 632 | ||
633 | ret = send_mad(&query->sa_query, timeout_ms); | 633 | ret = send_mad(&query->sa_query, timeout_ms, gfp_mask); |
634 | if (ret < 0) | 634 | if (ret < 0) |
635 | goto err2; | 635 | goto err2; |
636 | 636 | ||
@@ -752,7 +752,7 @@ int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method, | |||
752 | 752 | ||
753 | *sa_query = &query->sa_query; | 753 | *sa_query = &query->sa_query; |
754 | 754 | ||
755 | ret = send_mad(&query->sa_query, timeout_ms); | 755 | ret = send_mad(&query->sa_query, timeout_ms, gfp_mask); |
756 | if (ret < 0) | 756 | if (ret < 0) |
757 | goto err2; | 757 | goto err2; |
758 | 758 | ||
@@ -844,7 +844,7 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num, | |||
844 | 844 | ||
845 | *sa_query = &query->sa_query; | 845 | *sa_query = &query->sa_query; |
846 | 846 | ||
847 | ret = send_mad(&query->sa_query, timeout_ms); | 847 | ret = send_mad(&query->sa_query, timeout_ms, gfp_mask); |
848 | if (ret < 0) | 848 | if (ret < 0) |
849 | goto err2; | 849 | goto err2; |
850 | 850 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index b12aa03be251..e215041b2db9 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c | |||
@@ -303,9 +303,10 @@ int mthca_ah_query(struct ib_ah *ibah, struct ib_ah_attr *attr) | |||
303 | memset(attr, 0, sizeof *attr); | 303 | memset(attr, 0, sizeof *attr); |
304 | attr->dlid = be16_to_cpu(ah->av->dlid); | 304 | attr->dlid = be16_to_cpu(ah->av->dlid); |
305 | attr->sl = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; | 305 | attr->sl = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; |
306 | attr->static_rate = ah->av->msg_sr & 0x7; | ||
307 | attr->src_path_bits = ah->av->g_slid & 0x7F; | ||
308 | attr->port_num = be32_to_cpu(ah->av->port_pd) >> 24; | 306 | attr->port_num = be32_to_cpu(ah->av->port_pd) >> 24; |
307 | attr->static_rate = mthca_rate_to_ib(dev, ah->av->msg_sr & 0x7, | ||
308 | attr->port_num); | ||
309 | attr->src_path_bits = ah->av->g_slid & 0x7F; | ||
309 | attr->ah_flags = mthca_ah_grh_present(ah) ? IB_AH_GRH : 0; | 310 | attr->ah_flags = mthca_ah_grh_present(ah) ? IB_AH_GRH : 0; |
310 | 311 | ||
311 | if (attr->ah_flags) { | 312 | if (attr->ah_flags) { |
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 490fc783bb0c..cd8b6721ac9c 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
@@ -222,9 +222,8 @@ static void *get_send_wqe(struct mthca_qp *qp, int n) | |||
222 | (PAGE_SIZE - 1)); | 222 | (PAGE_SIZE - 1)); |
223 | } | 223 | } |
224 | 224 | ||
225 | static void mthca_wq_init(struct mthca_wq *wq) | 225 | static void mthca_wq_reset(struct mthca_wq *wq) |
226 | { | 226 | { |
227 | /* mthca_alloc_qp_common() initializes the locks */ | ||
228 | wq->next_ind = 0; | 227 | wq->next_ind = 0; |
229 | wq->last_comp = wq->max - 1; | 228 | wq->last_comp = wq->max - 1; |
230 | wq->head = 0; | 229 | wq->head = 0; |
@@ -845,10 +844,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
845 | mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn, | 844 | mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn, |
846 | qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL); | 845 | qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL); |
847 | 846 | ||
848 | mthca_wq_init(&qp->sq); | 847 | mthca_wq_reset(&qp->sq); |
849 | qp->sq.last = get_send_wqe(qp, qp->sq.max - 1); | 848 | qp->sq.last = get_send_wqe(qp, qp->sq.max - 1); |
850 | 849 | ||
851 | mthca_wq_init(&qp->rq); | 850 | mthca_wq_reset(&qp->rq); |
852 | qp->rq.last = get_recv_wqe(qp, qp->rq.max - 1); | 851 | qp->rq.last = get_recv_wqe(qp, qp->rq.max - 1); |
853 | 852 | ||
854 | if (mthca_is_memfree(dev)) { | 853 | if (mthca_is_memfree(dev)) { |
@@ -1112,9 +1111,9 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev, | |||
1112 | qp->atomic_rd_en = 0; | 1111 | qp->atomic_rd_en = 0; |
1113 | qp->resp_depth = 0; | 1112 | qp->resp_depth = 0; |
1114 | qp->sq_policy = send_policy; | 1113 | qp->sq_policy = send_policy; |
1115 | mthca_wq_init(&qp->sq); | 1114 | mthca_wq_reset(&qp->sq); |
1116 | mthca_wq_init(&qp->rq); | 1115 | mthca_wq_reset(&qp->rq); |
1117 | /* these are initialized separately so lockdep can tell them apart */ | 1116 | |
1118 | spin_lock_init(&qp->sq.lock); | 1117 | spin_lock_init(&qp->sq.lock); |
1119 | spin_lock_init(&qp->rq.lock); | 1118 | spin_lock_init(&qp->rq.lock); |
1120 | 1119 | ||
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index ff117bbf81b4..72febf1f8ff8 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c | |||
@@ -594,7 +594,7 @@ int iser_reg_page_vec(struct iser_conn *ib_conn, | |||
594 | mem = ib_fmr_pool_map_phys(ib_conn->fmr_pool, | 594 | mem = ib_fmr_pool_map_phys(ib_conn->fmr_pool, |
595 | page_list, | 595 | page_list, |
596 | page_vec->length, | 596 | page_vec->length, |
597 | &io_addr); | 597 | io_addr); |
598 | 598 | ||
599 | if (IS_ERR(mem)) { | 599 | if (IS_ERR(mem)) { |
600 | status = (int)PTR_ERR(mem); | 600 | status = (int)PTR_ERR(mem); |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 4e22afef7206..8f472e7113b4 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -615,9 +615,10 @@ static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat, | |||
615 | (sg_dma_address(&scat[i]) & dev->fmr_page_mask) + j; | 615 | (sg_dma_address(&scat[i]) & dev->fmr_page_mask) + j; |
616 | 616 | ||
617 | req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool, | 617 | req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool, |
618 | dma_pages, page_cnt, &io_addr); | 618 | dma_pages, page_cnt, io_addr); |
619 | if (IS_ERR(req->fmr)) { | 619 | if (IS_ERR(req->fmr)) { |
620 | ret = PTR_ERR(req->fmr); | 620 | ret = PTR_ERR(req->fmr); |
621 | req->fmr = NULL; | ||
621 | goto out; | 622 | goto out; |
622 | } | 623 | } |
623 | 624 | ||
diff --git a/drivers/leds/leds-net48xx.c b/drivers/leds/leds-net48xx.c index 35ee52f9b79e..713c4a8aa77d 100644 --- a/drivers/leds/leds-net48xx.c +++ b/drivers/leds/leds-net48xx.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
19 | #include <linux/scx200_gpio.h> | 19 | #include <linux/scx200_gpio.h> |
20 | 20 | ||
21 | #define DRVNAME "net48xx-led" | ||
21 | #define NET48XX_ERROR_LED_GPIO 20 | 22 | #define NET48XX_ERROR_LED_GPIO 20 |
22 | 23 | ||
23 | static struct platform_device *pdev; | 24 | static struct platform_device *pdev; |
@@ -66,13 +67,13 @@ static int net48xx_led_remove(struct platform_device *pdev) | |||
66 | } | 67 | } |
67 | 68 | ||
68 | static struct platform_driver net48xx_led_driver = { | 69 | static struct platform_driver net48xx_led_driver = { |
69 | .driver.owner = THIS_MODULE, | ||
70 | .probe = net48xx_led_probe, | 70 | .probe = net48xx_led_probe, |
71 | .remove = net48xx_led_remove, | 71 | .remove = net48xx_led_remove, |
72 | .suspend = net48xx_led_suspend, | 72 | .suspend = net48xx_led_suspend, |
73 | .resume = net48xx_led_resume, | 73 | .resume = net48xx_led_resume, |
74 | .driver = { | 74 | .driver = { |
75 | .name = "net48xx-led", | 75 | .name = DRVNAME, |
76 | .owner = THIS_MODULE, | ||
76 | }, | 77 | }, |
77 | }; | 78 | }; |
78 | 79 | ||
@@ -89,7 +90,7 @@ static int __init net48xx_led_init(void) | |||
89 | if (ret < 0) | 90 | if (ret < 0) |
90 | goto out; | 91 | goto out; |
91 | 92 | ||
92 | pdev = platform_device_register_simple("net48xx-led", -1, NULL, 0); | 93 | pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); |
93 | if (IS_ERR(pdev)) { | 94 | if (IS_ERR(pdev)) { |
94 | ret = PTR_ERR(pdev); | 95 | ret = PTR_ERR(pdev); |
95 | platform_driver_unregister(&net48xx_led_driver); | 96 | platform_driver_unregister(&net48xx_led_driver); |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index f5b9f187a930..7ff1d88094b6 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -121,6 +121,16 @@ config RTC_DRV_DS1553 | |||
121 | This driver can also be built as a module. If so, the module | 121 | This driver can also be built as a module. If so, the module |
122 | will be called rtc-ds1553. | 122 | will be called rtc-ds1553. |
123 | 123 | ||
124 | config RTC_DRV_ISL1208 | ||
125 | tristate "Intersil 1208" | ||
126 | depends on RTC_CLASS && I2C | ||
127 | help | ||
128 | If you say yes here you get support for the | ||
129 | Intersil 1208 RTC chip. | ||
130 | |||
131 | This driver can also be built as a module. If so, the module | ||
132 | will be called rtc-isl1208. | ||
133 | |||
124 | config RTC_DRV_DS1672 | 134 | config RTC_DRV_DS1672 |
125 | tristate "Dallas/Maxim DS1672" | 135 | tristate "Dallas/Maxim DS1672" |
126 | depends on RTC_CLASS && I2C | 136 | depends on RTC_CLASS && I2C |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 54220714ff49..bbcfb09d81d9 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -12,6 +12,7 @@ obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o | |||
12 | obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o | 12 | obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o |
13 | 13 | ||
14 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 14 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
15 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | ||
15 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o | 16 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o |
16 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o | 17 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o |
17 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 18 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c new file mode 100644 index 000000000000..f324d0a635d4 --- /dev/null +++ b/drivers/rtc/rtc-isl1208.c | |||
@@ -0,0 +1,591 @@ | |||
1 | /* | ||
2 | * Intersil ISL1208 rtc class driver | ||
3 | * | ||
4 | * Copyright 2005,2006 Hebert Valerio Riedel <hvr@gnu.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/bcd.h> | ||
16 | #include <linux/rtc.h> | ||
17 | |||
18 | #define DRV_NAME "isl1208" | ||
19 | #define DRV_VERSION "0.2" | ||
20 | |||
21 | /* Register map */ | ||
22 | /* rtc section */ | ||
23 | #define ISL1208_REG_SC 0x00 | ||
24 | #define ISL1208_REG_MN 0x01 | ||
25 | #define ISL1208_REG_HR 0x02 | ||
26 | #define ISL1208_REG_HR_MIL (1<<7) /* 24h/12h mode */ | ||
27 | #define ISL1208_REG_HR_PM (1<<5) /* PM/AM bit in 12h mode */ | ||
28 | #define ISL1208_REG_DT 0x03 | ||
29 | #define ISL1208_REG_MO 0x04 | ||
30 | #define ISL1208_REG_YR 0x05 | ||
31 | #define ISL1208_REG_DW 0x06 | ||
32 | #define ISL1208_RTC_SECTION_LEN 7 | ||
33 | |||
34 | /* control/status section */ | ||
35 | #define ISL1208_REG_SR 0x07 | ||
36 | #define ISL1208_REG_SR_ARST (1<<7) /* auto reset */ | ||
37 | #define ISL1208_REG_SR_XTOSCB (1<<6) /* crystal oscillator */ | ||
38 | #define ISL1208_REG_SR_WRTC (1<<4) /* write rtc */ | ||
39 | #define ISL1208_REG_SR_ALM (1<<2) /* alarm */ | ||
40 | #define ISL1208_REG_SR_BAT (1<<1) /* battery */ | ||
41 | #define ISL1208_REG_SR_RTCF (1<<0) /* rtc fail */ | ||
42 | #define ISL1208_REG_INT 0x08 | ||
43 | #define ISL1208_REG_09 0x09 /* reserved */ | ||
44 | #define ISL1208_REG_ATR 0x0a | ||
45 | #define ISL1208_REG_DTR 0x0b | ||
46 | |||
47 | /* alarm section */ | ||
48 | #define ISL1208_REG_SCA 0x0c | ||
49 | #define ISL1208_REG_MNA 0x0d | ||
50 | #define ISL1208_REG_HRA 0x0e | ||
51 | #define ISL1208_REG_DTA 0x0f | ||
52 | #define ISL1208_REG_MOA 0x10 | ||
53 | #define ISL1208_REG_DWA 0x11 | ||
54 | #define ISL1208_ALARM_SECTION_LEN 6 | ||
55 | |||
56 | /* user section */ | ||
57 | #define ISL1208_REG_USR1 0x12 | ||
58 | #define ISL1208_REG_USR2 0x13 | ||
59 | #define ISL1208_USR_SECTION_LEN 2 | ||
60 | |||
61 | /* i2c configuration */ | ||
62 | #define ISL1208_I2C_ADDR 0xde | ||
63 | |||
64 | static unsigned short normal_i2c[] = { | ||
65 | ISL1208_I2C_ADDR>>1, I2C_CLIENT_END | ||
66 | }; | ||
67 | I2C_CLIENT_INSMOD; /* defines addr_data */ | ||
68 | |||
69 | static int isl1208_attach_adapter(struct i2c_adapter *adapter); | ||
70 | static int isl1208_detach_client(struct i2c_client *client); | ||
71 | |||
72 | static struct i2c_driver isl1208_driver = { | ||
73 | .driver = { | ||
74 | .name = DRV_NAME, | ||
75 | }, | ||
76 | .id = I2C_DRIVERID_ISL1208, | ||
77 | .attach_adapter = &isl1208_attach_adapter, | ||
78 | .detach_client = &isl1208_detach_client, | ||
79 | }; | ||
80 | |||
81 | /* block read */ | ||
82 | static int | ||
83 | isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[], | ||
84 | unsigned len) | ||
85 | { | ||
86 | u8 reg_addr[1] = { reg }; | ||
87 | struct i2c_msg msgs[2] = { | ||
88 | { client->addr, client->flags, sizeof(reg_addr), reg_addr }, | ||
89 | { client->addr, client->flags | I2C_M_RD, len, buf } | ||
90 | }; | ||
91 | int ret; | ||
92 | |||
93 | BUG_ON(len == 0); | ||
94 | BUG_ON(reg > ISL1208_REG_USR2); | ||
95 | BUG_ON(reg + len > ISL1208_REG_USR2 + 1); | ||
96 | |||
97 | ret = i2c_transfer(client->adapter, msgs, 2); | ||
98 | if (ret > 0) | ||
99 | ret = 0; | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | /* block write */ | ||
104 | static int | ||
105 | isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], | ||
106 | unsigned len) | ||
107 | { | ||
108 | u8 i2c_buf[ISL1208_REG_USR2 + 2]; | ||
109 | struct i2c_msg msgs[1] = { | ||
110 | { client->addr, client->flags, len + 1, i2c_buf } | ||
111 | }; | ||
112 | int ret; | ||
113 | |||
114 | BUG_ON(len == 0); | ||
115 | BUG_ON(reg > ISL1208_REG_USR2); | ||
116 | BUG_ON(reg + len > ISL1208_REG_USR2 + 1); | ||
117 | |||
118 | i2c_buf[0] = reg; | ||
119 | memcpy(&i2c_buf[1], &buf[0], len); | ||
120 | |||
121 | ret = i2c_transfer(client->adapter, msgs, 1); | ||
122 | if (ret > 0) | ||
123 | ret = 0; | ||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | /* simple check to see wether we have a isl1208 */ | ||
128 | static int isl1208_i2c_validate_client(struct i2c_client *client) | ||
129 | { | ||
130 | u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; | ||
131 | u8 zero_mask[ISL1208_RTC_SECTION_LEN] = { | ||
132 | 0x80, 0x80, 0x40, 0xc0, 0xe0, 0x00, 0xf8 | ||
133 | }; | ||
134 | int i; | ||
135 | int ret; | ||
136 | |||
137 | ret = isl1208_i2c_read_regs(client, 0, regs, ISL1208_RTC_SECTION_LEN); | ||
138 | if (ret < 0) | ||
139 | return ret; | ||
140 | |||
141 | for (i = 0; i < ISL1208_RTC_SECTION_LEN; ++i) { | ||
142 | if (regs[i] & zero_mask[i]) /* check if bits are cleared */ | ||
143 | return -ENODEV; | ||
144 | } | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int isl1208_i2c_get_sr(struct i2c_client *client) | ||
150 | { | ||
151 | return i2c_smbus_read_byte_data(client, ISL1208_REG_SR) == -1 ? -EIO:0; | ||
152 | } | ||
153 | |||
154 | static int isl1208_i2c_get_atr(struct i2c_client *client) | ||
155 | { | ||
156 | int atr = i2c_smbus_read_byte_data(client, ISL1208_REG_ATR); | ||
157 | |||
158 | if (atr < 0) | ||
159 | return -EIO; | ||
160 | |||
161 | /* The 6bit value in the ATR register controls the load | ||
162 | * capacitance C_load * in steps of 0.25pF | ||
163 | * | ||
164 | * bit (1<<5) of the ATR register is inverted | ||
165 | * | ||
166 | * C_load(ATR=0x20) = 4.50pF | ||
167 | * C_load(ATR=0x00) = 12.50pF | ||
168 | * C_load(ATR=0x1f) = 20.25pF | ||
169 | * | ||
170 | */ | ||
171 | |||
172 | atr &= 0x3f; /* mask out lsb */ | ||
173 | atr ^= 1<<5; /* invert 6th bit */ | ||
174 | atr += 2*9; /* add offset of 4.5pF; unit[atr] = 0.25pF */ | ||
175 | |||
176 | return atr; | ||
177 | } | ||
178 | |||
179 | static int isl1208_i2c_get_dtr(struct i2c_client *client) | ||
180 | { | ||
181 | int dtr = i2c_smbus_read_byte_data(client, ISL1208_REG_DTR); | ||
182 | |||
183 | if (dtr < 0) | ||
184 | return -EIO; | ||
185 | |||
186 | /* dtr encodes adjustments of {-60,-40,-20,0,20,40,60} ppm */ | ||
187 | dtr = ((dtr & 0x3) * 20) * (dtr & (1<<2) ? -1 : 1); | ||
188 | |||
189 | return dtr; | ||
190 | } | ||
191 | |||
192 | static int isl1208_i2c_get_usr(struct i2c_client *client) | ||
193 | { | ||
194 | u8 buf[ISL1208_USR_SECTION_LEN] = { 0, }; | ||
195 | int ret; | ||
196 | |||
197 | ret = isl1208_i2c_read_regs (client, ISL1208_REG_USR1, buf, | ||
198 | ISL1208_USR_SECTION_LEN); | ||
199 | if (ret < 0) | ||
200 | return ret; | ||
201 | |||
202 | return (buf[1] << 8) | buf[0]; | ||
203 | } | ||
204 | |||
205 | static int isl1208_i2c_set_usr(struct i2c_client *client, u16 usr) | ||
206 | { | ||
207 | u8 buf[ISL1208_USR_SECTION_LEN]; | ||
208 | |||
209 | buf[0] = usr & 0xff; | ||
210 | buf[1] = (usr >> 8) & 0xff; | ||
211 | |||
212 | return isl1208_i2c_set_regs (client, ISL1208_REG_USR1, buf, | ||
213 | ISL1208_USR_SECTION_LEN); | ||
214 | } | ||
215 | |||
216 | static int isl1208_rtc_proc(struct device *dev, struct seq_file *seq) | ||
217 | { | ||
218 | struct i2c_client *const client = to_i2c_client(dev); | ||
219 | int sr, dtr, atr, usr; | ||
220 | |||
221 | sr = isl1208_i2c_get_sr(client); | ||
222 | if (sr < 0) { | ||
223 | dev_err(&client->dev, "%s: reading SR failed\n", __func__); | ||
224 | return sr; | ||
225 | } | ||
226 | |||
227 | seq_printf(seq, "status_reg\t:%s%s%s%s%s%s (0x%.2x)\n", | ||
228 | (sr & ISL1208_REG_SR_RTCF) ? " RTCF" : "", | ||
229 | (sr & ISL1208_REG_SR_BAT) ? " BAT" : "", | ||
230 | (sr & ISL1208_REG_SR_ALM) ? " ALM" : "", | ||
231 | (sr & ISL1208_REG_SR_WRTC) ? " WRTC" : "", | ||
232 | (sr & ISL1208_REG_SR_XTOSCB) ? " XTOSCB" : "", | ||
233 | (sr & ISL1208_REG_SR_ARST) ? " ARST" : "", | ||
234 | sr); | ||
235 | |||
236 | seq_printf(seq, "batt_status\t: %s\n", | ||
237 | (sr & ISL1208_REG_SR_RTCF) ? "bad" : "okay"); | ||
238 | |||
239 | dtr = isl1208_i2c_get_dtr(client); | ||
240 | if (dtr >= 0 -1) | ||
241 | seq_printf(seq, "digital_trim\t: %d ppm\n", dtr); | ||
242 | |||
243 | atr = isl1208_i2c_get_atr(client); | ||
244 | if (atr >= 0) | ||
245 | seq_printf(seq, "analog_trim\t: %d.%.2d pF\n", | ||
246 | atr>>2, (atr&0x3)*25); | ||
247 | |||
248 | usr = isl1208_i2c_get_usr(client); | ||
249 | if (usr >= 0) | ||
250 | seq_printf(seq, "user_data\t: 0x%.4x\n", usr); | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | |||
256 | static int isl1208_i2c_read_time(struct i2c_client *client, | ||
257 | struct rtc_time *tm) | ||
258 | { | ||
259 | int sr; | ||
260 | u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; | ||
261 | |||
262 | sr = isl1208_i2c_get_sr(client); | ||
263 | if (sr < 0) { | ||
264 | dev_err(&client->dev, "%s: reading SR failed\n", __func__); | ||
265 | return -EIO; | ||
266 | } | ||
267 | |||
268 | sr = isl1208_i2c_read_regs(client, 0, regs, ISL1208_RTC_SECTION_LEN); | ||
269 | if (sr < 0) { | ||
270 | dev_err(&client->dev, "%s: reading RTC section failed\n", | ||
271 | __func__); | ||
272 | return sr; | ||
273 | } | ||
274 | |||
275 | tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SC]); | ||
276 | tm->tm_min = BCD2BIN(regs[ISL1208_REG_MN]); | ||
277 | { /* HR field has a more complex interpretation */ | ||
278 | const u8 _hr = regs[ISL1208_REG_HR]; | ||
279 | if (_hr & ISL1208_REG_HR_MIL) /* 24h format */ | ||
280 | tm->tm_hour = BCD2BIN(_hr & 0x3f); | ||
281 | else { // 12h format | ||
282 | tm->tm_hour = BCD2BIN(_hr & 0x1f); | ||
283 | if (_hr & ISL1208_REG_HR_PM) /* PM flag set */ | ||
284 | tm->tm_hour += 12; | ||
285 | } | ||
286 | } | ||
287 | |||
288 | tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DT]); | ||
289 | tm->tm_mon = BCD2BIN(regs[ISL1208_REG_MO]) - 1; /* rtc starts at 1 */ | ||
290 | tm->tm_year = BCD2BIN(regs[ISL1208_REG_YR]) + 100; | ||
291 | tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DW]); | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static int isl1208_i2c_read_alarm(struct i2c_client *client, | ||
297 | struct rtc_wkalrm *alarm) | ||
298 | { | ||
299 | struct rtc_time *const tm = &alarm->time; | ||
300 | u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, }; | ||
301 | int sr; | ||
302 | |||
303 | sr = isl1208_i2c_get_sr(client); | ||
304 | if (sr < 0) { | ||
305 | dev_err(&client->dev, "%s: reading SR failed\n", __func__); | ||
306 | return sr; | ||
307 | } | ||
308 | |||
309 | sr = isl1208_i2c_read_regs(client, ISL1208_REG_SCA, regs, | ||
310 | ISL1208_ALARM_SECTION_LEN); | ||
311 | if (sr < 0) { | ||
312 | dev_err(&client->dev, "%s: reading alarm section failed\n", | ||
313 | __func__); | ||
314 | return sr; | ||
315 | } | ||
316 | |||
317 | /* MSB of each alarm register is an enable bit */ | ||
318 | tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SCA-ISL1208_REG_SCA] & 0x7f); | ||
319 | tm->tm_min = BCD2BIN(regs[ISL1208_REG_MNA-ISL1208_REG_SCA] & 0x7f); | ||
320 | tm->tm_hour = BCD2BIN(regs[ISL1208_REG_HRA-ISL1208_REG_SCA] & 0x3f); | ||
321 | tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DTA-ISL1208_REG_SCA] & 0x3f); | ||
322 | tm->tm_mon = BCD2BIN(regs[ISL1208_REG_MOA-ISL1208_REG_SCA] & 0x1f)-1; | ||
323 | tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DWA-ISL1208_REG_SCA] & 0x03); | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int isl1208_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
329 | { | ||
330 | return isl1208_i2c_read_time(to_i2c_client(dev), tm); | ||
331 | } | ||
332 | |||
333 | static int isl1208_i2c_set_time(struct i2c_client *client, | ||
334 | struct rtc_time const *tm) | ||
335 | { | ||
336 | int sr; | ||
337 | u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; | ||
338 | |||
339 | regs[ISL1208_REG_SC] = BIN2BCD(tm->tm_sec); | ||
340 | regs[ISL1208_REG_MN] = BIN2BCD(tm->tm_min); | ||
341 | regs[ISL1208_REG_HR] = BIN2BCD(tm->tm_hour) | ISL1208_REG_HR_MIL; | ||
342 | |||
343 | regs[ISL1208_REG_DT] = BIN2BCD(tm->tm_mday); | ||
344 | regs[ISL1208_REG_MO] = BIN2BCD(tm->tm_mon + 1); | ||
345 | regs[ISL1208_REG_YR] = BIN2BCD(tm->tm_year - 100); | ||
346 | |||
347 | regs[ISL1208_REG_DW] = BIN2BCD(tm->tm_wday & 7); | ||
348 | |||
349 | sr = isl1208_i2c_get_sr(client); | ||
350 | if (sr < 0) { | ||
351 | dev_err(&client->dev, "%s: reading SR failed\n", __func__); | ||
352 | return sr; | ||
353 | } | ||
354 | |||
355 | /* set WRTC */ | ||
356 | sr = i2c_smbus_write_byte_data (client, ISL1208_REG_SR, | ||
357 | sr | ISL1208_REG_SR_WRTC); | ||
358 | if (sr < 0) { | ||
359 | dev_err(&client->dev, "%s: writing SR failed\n", __func__); | ||
360 | return sr; | ||
361 | } | ||
362 | |||
363 | /* write RTC registers */ | ||
364 | sr = isl1208_i2c_set_regs(client, 0, regs, ISL1208_RTC_SECTION_LEN); | ||
365 | if (sr < 0) { | ||
366 | dev_err(&client->dev, "%s: writing RTC section failed\n", | ||
367 | __func__); | ||
368 | return sr; | ||
369 | } | ||
370 | |||
371 | /* clear WRTC again */ | ||
372 | sr = i2c_smbus_write_byte_data (client, ISL1208_REG_SR, | ||
373 | sr & ~ISL1208_REG_SR_WRTC); | ||
374 | if (sr < 0) { | ||
375 | dev_err(&client->dev, "%s: writing SR failed\n", __func__); | ||
376 | return sr; | ||
377 | } | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | |||
383 | static int isl1208_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
384 | { | ||
385 | return isl1208_i2c_set_time(to_i2c_client(dev), tm); | ||
386 | } | ||
387 | |||
388 | static int isl1208_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
389 | { | ||
390 | return isl1208_i2c_read_alarm(to_i2c_client(dev), alarm); | ||
391 | } | ||
392 | |||
393 | static struct rtc_class_ops isl1208_rtc_ops = { | ||
394 | .proc = isl1208_rtc_proc, | ||
395 | .read_time = isl1208_rtc_read_time, | ||
396 | .set_time = isl1208_rtc_set_time, | ||
397 | .read_alarm = isl1208_rtc_read_alarm, | ||
398 | //.set_alarm = isl1208_rtc_set_alarm, | ||
399 | }; | ||
400 | |||
401 | /* sysfs interface */ | ||
402 | |||
403 | static ssize_t isl1208_sysfs_show_atrim(struct device *dev, | ||
404 | struct device_attribute *attr, | ||
405 | char *buf) | ||
406 | { | ||
407 | int atr; | ||
408 | |||
409 | atr = isl1208_i2c_get_atr(to_i2c_client(dev)); | ||
410 | if (atr < 0) | ||
411 | return atr; | ||
412 | |||
413 | return sprintf(buf, "%d.%.2d pF\n", atr>>2, (atr&0x3)*25); | ||
414 | } | ||
415 | static DEVICE_ATTR(atrim, S_IRUGO, isl1208_sysfs_show_atrim, NULL); | ||
416 | |||
417 | static ssize_t isl1208_sysfs_show_dtrim(struct device *dev, | ||
418 | struct device_attribute *attr, | ||
419 | char *buf) | ||
420 | { | ||
421 | int dtr; | ||
422 | |||
423 | dtr = isl1208_i2c_get_dtr(to_i2c_client(dev)); | ||
424 | if (dtr < 0) | ||
425 | return dtr; | ||
426 | |||
427 | return sprintf(buf, "%d ppm\n", dtr); | ||
428 | } | ||
429 | static DEVICE_ATTR(dtrim, S_IRUGO, isl1208_sysfs_show_dtrim, NULL); | ||
430 | |||
431 | static ssize_t isl1208_sysfs_show_usr(struct device *dev, | ||
432 | struct device_attribute *attr, | ||
433 | char *buf) | ||
434 | { | ||
435 | int usr; | ||
436 | |||
437 | usr = isl1208_i2c_get_usr(to_i2c_client(dev)); | ||
438 | if (usr < 0) | ||
439 | return usr; | ||
440 | |||
441 | return sprintf(buf, "0x%.4x\n", usr); | ||
442 | } | ||
443 | |||
444 | static ssize_t isl1208_sysfs_store_usr(struct device *dev, | ||
445 | struct device_attribute *attr, | ||
446 | const char *buf, size_t count) | ||
447 | { | ||
448 | int usr = -1; | ||
449 | |||
450 | if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) { | ||
451 | if (sscanf(buf, "%x", &usr) != 1) | ||
452 | return -EINVAL; | ||
453 | } else { | ||
454 | if (sscanf(buf, "%d", &usr) != 1) | ||
455 | return -EINVAL; | ||
456 | } | ||
457 | |||
458 | if (usr < 0 || usr > 0xffff) | ||
459 | return -EINVAL; | ||
460 | |||
461 | return isl1208_i2c_set_usr(to_i2c_client(dev), usr) ? -EIO : count; | ||
462 | } | ||
463 | static DEVICE_ATTR(usr, S_IRUGO | S_IWUSR, isl1208_sysfs_show_usr, | ||
464 | isl1208_sysfs_store_usr); | ||
465 | |||
466 | static int | ||
467 | isl1208_probe(struct i2c_adapter *adapter, int addr, int kind) | ||
468 | { | ||
469 | int rc = 0; | ||
470 | struct i2c_client *new_client = NULL; | ||
471 | struct rtc_device *rtc = NULL; | ||
472 | |||
473 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | ||
474 | rc = -ENODEV; | ||
475 | goto failout; | ||
476 | } | ||
477 | |||
478 | new_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
479 | if (new_client == NULL) { | ||
480 | rc = -ENOMEM; | ||
481 | goto failout; | ||
482 | } | ||
483 | |||
484 | new_client->addr = addr; | ||
485 | new_client->adapter = adapter; | ||
486 | new_client->driver = &isl1208_driver; | ||
487 | new_client->flags = 0; | ||
488 | strcpy(new_client->name, DRV_NAME); | ||
489 | |||
490 | if (kind < 0) { | ||
491 | rc = isl1208_i2c_validate_client(new_client); | ||
492 | if (rc < 0) | ||
493 | goto failout; | ||
494 | } | ||
495 | |||
496 | rc = i2c_attach_client(new_client); | ||
497 | if (rc < 0) | ||
498 | goto failout; | ||
499 | |||
500 | dev_info(&new_client->dev, | ||
501 | "chip found, driver version " DRV_VERSION "\n"); | ||
502 | |||
503 | rtc = rtc_device_register(isl1208_driver.driver.name, | ||
504 | &new_client->dev, | ||
505 | &isl1208_rtc_ops, THIS_MODULE); | ||
506 | |||
507 | if (IS_ERR(rtc)) { | ||
508 | rc = PTR_ERR(rtc); | ||
509 | goto failout_detach; | ||
510 | } | ||
511 | |||
512 | i2c_set_clientdata(new_client, rtc); | ||
513 | |||
514 | rc = isl1208_i2c_get_sr(new_client); | ||
515 | if (rc < 0) { | ||
516 | dev_err(&new_client->dev, "reading status failed\n"); | ||
517 | goto failout_unregister; | ||
518 | } | ||
519 | |||
520 | if (rc & ISL1208_REG_SR_RTCF) | ||
521 | dev_warn(&new_client->dev, "rtc power failure detected, " | ||
522 | "please set clock.\n"); | ||
523 | |||
524 | rc = device_create_file(&new_client->dev, &dev_attr_atrim); | ||
525 | if (rc < 0) | ||
526 | goto failout_unregister; | ||
527 | rc = device_create_file(&new_client->dev, &dev_attr_dtrim); | ||
528 | if (rc < 0) | ||
529 | goto failout_atrim; | ||
530 | rc = device_create_file(&new_client->dev, &dev_attr_usr); | ||
531 | if (rc < 0) | ||
532 | goto failout_dtrim; | ||
533 | |||
534 | return 0; | ||
535 | |||
536 | failout_dtrim: | ||
537 | device_remove_file(&new_client->dev, &dev_attr_dtrim); | ||
538 | failout_atrim: | ||
539 | device_remove_file(&new_client->dev, &dev_attr_atrim); | ||
540 | failout_unregister: | ||
541 | rtc_device_unregister(rtc); | ||
542 | failout_detach: | ||
543 | i2c_detach_client(new_client); | ||
544 | failout: | ||
545 | kfree(new_client); | ||
546 | return rc; | ||
547 | } | ||
548 | |||
549 | static int | ||
550 | isl1208_attach_adapter (struct i2c_adapter *adapter) | ||
551 | { | ||
552 | return i2c_probe(adapter, &addr_data, isl1208_probe); | ||
553 | } | ||
554 | |||
555 | static int | ||
556 | isl1208_detach_client(struct i2c_client *client) | ||
557 | { | ||
558 | int rc; | ||
559 | struct rtc_device *const rtc = i2c_get_clientdata(client); | ||
560 | |||
561 | if (rtc) | ||
562 | rtc_device_unregister(rtc); /* do we need to kfree? */ | ||
563 | |||
564 | rc = i2c_detach_client(client); | ||
565 | if (rc) | ||
566 | return rc; | ||
567 | |||
568 | kfree(client); | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | /* module management */ | ||
574 | |||
575 | static int __init isl1208_init(void) | ||
576 | { | ||
577 | return i2c_add_driver(&isl1208_driver); | ||
578 | } | ||
579 | |||
580 | static void __exit isl1208_exit(void) | ||
581 | { | ||
582 | i2c_del_driver(&isl1208_driver); | ||
583 | } | ||
584 | |||
585 | MODULE_AUTHOR("Herbert Valerio Riedel <hvr@gnu.org>"); | ||
586 | MODULE_DESCRIPTION("Intersil ISL1208 RTC driver"); | ||
587 | MODULE_LICENSE("GPL"); | ||
588 | MODULE_VERSION(DRV_VERSION); | ||
589 | |||
590 | module_init(isl1208_init); | ||
591 | module_exit(isl1208_exit); | ||
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 0dbd4df44c05..979497f108c8 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c | |||
@@ -1052,7 +1052,7 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id * | |||
1052 | if (err) | 1052 | if (err) |
1053 | return err; | 1053 | return err; |
1054 | 1054 | ||
1055 | err = sunsab_init_one(&up[0], op, 0, | 1055 | err = sunsab_init_one(&up[1], op, 0, |
1056 | (inst * 2) + 1); | 1056 | (inst * 2) + 1); |
1057 | if (err) { | 1057 | if (err) { |
1058 | of_iounmap(up[0].port.membase, | 1058 | of_iounmap(up[0].port.membase, |
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 93bdaa3169fc..d3a5aeee73a3 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c | |||
@@ -1200,6 +1200,11 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up) | |||
1200 | if (up->port.type == PORT_UNKNOWN) | 1200 | if (up->port.type == PORT_UNKNOWN) |
1201 | return -ENODEV; | 1201 | return -ENODEV; |
1202 | 1202 | ||
1203 | printk("%s: %s port at %lx, irq %u\n", | ||
1204 | to_of_device(up->port.dev)->node->full_name, | ||
1205 | (up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse", | ||
1206 | up->port.mapbase, up->port.irq); | ||
1207 | |||
1203 | #ifdef CONFIG_SERIO | 1208 | #ifdef CONFIG_SERIO |
1204 | serio = &up->serio; | 1209 | serio = &up->serio; |
1205 | serio->port_data = up; | 1210 | serio->port_data = up; |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3badb48d662b..6533b0f39231 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -1518,6 +1518,26 @@ config FB_PXA_PARAMETERS | |||
1518 | 1518 | ||
1519 | <file:Documentation/fb/pxafb.txt> describes the available parameters. | 1519 | <file:Documentation/fb/pxafb.txt> describes the available parameters. |
1520 | 1520 | ||
1521 | config FB_MBX | ||
1522 | tristate "2700G LCD framebuffer support" | ||
1523 | depends on FB && ARCH_PXA | ||
1524 | select FB_CFB_FILLRECT | ||
1525 | select FB_CFB_COPYAREA | ||
1526 | select FB_CFB_IMAGEBLIT | ||
1527 | ---help--- | ||
1528 | Framebuffer driver for the Intel 2700G (Marathon) Graphics | ||
1529 | Accelerator | ||
1530 | |||
1531 | config FB_MBX_DEBUG | ||
1532 | bool "Enable debugging info via debugfs" | ||
1533 | depends on FB_MBX && DEBUG_FS | ||
1534 | default n | ||
1535 | ---help--- | ||
1536 | Enable this if you want debugging information using the debug | ||
1537 | filesystem (debugfs) | ||
1538 | |||
1539 | If unsure, say N. | ||
1540 | |||
1521 | config FB_W100 | 1541 | config FB_W100 |
1522 | tristate "W100 frame buffer support" | 1542 | tristate "W100 frame buffer support" |
1523 | depends on FB && PXA_SHARPSL | 1543 | depends on FB && PXA_SHARPSL |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 6283d015f8f5..95563c9c6b9c 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -38,6 +38,7 @@ obj-$(CONFIG_FB_SIS) += sis/ | |||
38 | obj-$(CONFIG_FB_KYRO) += kyro/ | 38 | obj-$(CONFIG_FB_KYRO) += kyro/ |
39 | obj-$(CONFIG_FB_SAVAGE) += savage/ | 39 | obj-$(CONFIG_FB_SAVAGE) += savage/ |
40 | obj-$(CONFIG_FB_GEODE) += geode/ | 40 | obj-$(CONFIG_FB_GEODE) += geode/ |
41 | obj-$(CONFIG_FB_MBX) += mbx/ | ||
41 | obj-$(CONFIG_FB_I810) += vgastate.o | 42 | obj-$(CONFIG_FB_I810) += vgastate.o |
42 | obj-$(CONFIG_FB_NEOMAGIC) += neofb.o vgastate.o | 43 | obj-$(CONFIG_FB_NEOMAGIC) += neofb.o vgastate.o |
43 | obj-$(CONFIG_FB_VIRGE) += virgefb.o | 44 | obj-$(CONFIG_FB_VIRGE) += virgefb.o |
diff --git a/drivers/video/mbx/Makefile b/drivers/video/mbx/Makefile new file mode 100644 index 000000000000..16c1165cf9c7 --- /dev/null +++ b/drivers/video/mbx/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # Makefile for the 2700G controller driver. | ||
2 | |||
3 | obj-$(CONFIG_FB_MBX) += mbxfb.o | ||
4 | obj-$(CONFIG_FB_MBX_DEBUG) += mbxfbdebugfs.o | ||
diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c new file mode 100644 index 000000000000..84aab3ad024e --- /dev/null +++ b/drivers/video/mbx/mbxdebugfs.c | |||
@@ -0,0 +1,188 @@ | |||
1 | #include <linux/debugfs.h> | ||
2 | |||
3 | #define BIG_BUFFER_SIZE (1024) | ||
4 | |||
5 | static char big_buffer[BIG_BUFFER_SIZE]; | ||
6 | |||
7 | struct mbxfb_debugfs_data { | ||
8 | struct dentry *dir; | ||
9 | struct dentry *sysconf; | ||
10 | struct dentry *clock; | ||
11 | struct dentry *display; | ||
12 | struct dentry *gsctl; | ||
13 | }; | ||
14 | |||
15 | static int open_file_generic(struct inode *inode, struct file *file) | ||
16 | { | ||
17 | file->private_data = inode->u.generic_ip; | ||
18 | return 0; | ||
19 | } | ||
20 | |||
21 | static ssize_t write_file_dummy(struct file *file, const char __user *buf, | ||
22 | size_t count, loff_t *ppos) | ||
23 | { | ||
24 | return count; | ||
25 | } | ||
26 | |||
27 | static ssize_t sysconf_read_file(struct file *file, char __user *userbuf, | ||
28 | size_t count, loff_t *ppos) | ||
29 | { | ||
30 | char * s = big_buffer; | ||
31 | |||
32 | s += sprintf(s, "SYSCFG = %08lx\n", SYSCFG); | ||
33 | s += sprintf(s, "PFBASE = %08lx\n", PFBASE); | ||
34 | s += sprintf(s, "PFCEIL = %08lx\n", PFCEIL); | ||
35 | s += sprintf(s, "POLLFLAG = %08lx\n", POLLFLAG); | ||
36 | s += sprintf(s, "SYSRST = %08lx\n", SYSRST); | ||
37 | |||
38 | return simple_read_from_buffer(userbuf, count, ppos, | ||
39 | big_buffer, s-big_buffer); | ||
40 | } | ||
41 | |||
42 | |||
43 | static ssize_t gsctl_read_file(struct file *file, char __user *userbuf, | ||
44 | size_t count, loff_t *ppos) | ||
45 | { | ||
46 | char * s = big_buffer; | ||
47 | |||
48 | s += sprintf(s, "GSCTRL = %08lx\n", GSCTRL); | ||
49 | s += sprintf(s, "VSCTRL = %08lx\n", VSCTRL); | ||
50 | s += sprintf(s, "GBBASE = %08lx\n", GBBASE); | ||
51 | s += sprintf(s, "VBBASE = %08lx\n", VBBASE); | ||
52 | s += sprintf(s, "GDRCTRL = %08lx\n", GDRCTRL); | ||
53 | s += sprintf(s, "VCMSK = %08lx\n", VCMSK); | ||
54 | s += sprintf(s, "GSCADR = %08lx\n", GSCADR); | ||
55 | s += sprintf(s, "VSCADR = %08lx\n", VSCADR); | ||
56 | s += sprintf(s, "VUBASE = %08lx\n", VUBASE); | ||
57 | s += sprintf(s, "VVBASE = %08lx\n", VVBASE); | ||
58 | s += sprintf(s, "GSADR = %08lx\n", GSADR); | ||
59 | s += sprintf(s, "VSADR = %08lx\n", VSADR); | ||
60 | s += sprintf(s, "HCCTRL = %08lx\n", HCCTRL); | ||
61 | s += sprintf(s, "HCSIZE = %08lx\n", HCSIZE); | ||
62 | s += sprintf(s, "HCPOS = %08lx\n", HCPOS); | ||
63 | s += sprintf(s, "HCBADR = %08lx\n", HCBADR); | ||
64 | s += sprintf(s, "HCCKMSK = %08lx\n", HCCKMSK); | ||
65 | s += sprintf(s, "GPLUT = %08lx\n", GPLUT); | ||
66 | |||
67 | return simple_read_from_buffer(userbuf, count, ppos, | ||
68 | big_buffer, s-big_buffer); | ||
69 | } | ||
70 | |||
71 | static ssize_t display_read_file(struct file *file, char __user *userbuf, | ||
72 | size_t count, loff_t *ppos) | ||
73 | { | ||
74 | char * s = big_buffer; | ||
75 | |||
76 | s += sprintf(s, "DSCTRL = %08lx\n", DSCTRL); | ||
77 | s += sprintf(s, "DHT01 = %08lx\n", DHT01); | ||
78 | s += sprintf(s, "DHT02 = %08lx\n", DHT02); | ||
79 | s += sprintf(s, "DHT03 = %08lx\n", DHT03); | ||
80 | s += sprintf(s, "DVT01 = %08lx\n", DVT01); | ||
81 | s += sprintf(s, "DVT02 = %08lx\n", DVT02); | ||
82 | s += sprintf(s, "DVT03 = %08lx\n", DVT03); | ||
83 | s += sprintf(s, "DBCOL = %08lx\n", DBCOL); | ||
84 | s += sprintf(s, "BGCOLOR = %08lx\n", BGCOLOR); | ||
85 | s += sprintf(s, "DINTRS = %08lx\n", DINTRS); | ||
86 | s += sprintf(s, "DINTRE = %08lx\n", DINTRE); | ||
87 | s += sprintf(s, "DINTRCNT = %08lx\n", DINTRCNT); | ||
88 | s += sprintf(s, "DSIG = %08lx\n", DSIG); | ||
89 | s += sprintf(s, "DMCTRL = %08lx\n", DMCTRL); | ||
90 | s += sprintf(s, "CLIPCTRL = %08lx\n", CLIPCTRL); | ||
91 | s += sprintf(s, "SPOCTRL = %08lx\n", SPOCTRL); | ||
92 | s += sprintf(s, "SVCTRL = %08lx\n", SVCTRL); | ||
93 | s += sprintf(s, "DLSTS = %08lx\n", DLSTS); | ||
94 | s += sprintf(s, "DLLCTRL = %08lx\n", DLLCTRL); | ||
95 | s += sprintf(s, "DVLNUM = %08lx\n", DVLNUM); | ||
96 | s += sprintf(s, "DUCTRL = %08lx\n", DUCTRL); | ||
97 | s += sprintf(s, "DVECTRL = %08lx\n", DVECTRL); | ||
98 | s += sprintf(s, "DHDET = %08lx\n", DHDET); | ||
99 | s += sprintf(s, "DVDET = %08lx\n", DVDET); | ||
100 | s += sprintf(s, "DODMSK = %08lx\n", DODMSK); | ||
101 | s += sprintf(s, "CSC01 = %08lx\n", CSC01); | ||
102 | s += sprintf(s, "CSC02 = %08lx\n", CSC02); | ||
103 | s += sprintf(s, "CSC03 = %08lx\n", CSC03); | ||
104 | s += sprintf(s, "CSC04 = %08lx\n", CSC04); | ||
105 | s += sprintf(s, "CSC05 = %08lx\n", CSC05); | ||
106 | |||
107 | return simple_read_from_buffer(userbuf, count, ppos, | ||
108 | big_buffer, s-big_buffer); | ||
109 | } | ||
110 | |||
111 | static ssize_t clock_read_file(struct file *file, char __user *userbuf, | ||
112 | size_t count, loff_t *ppos) | ||
113 | { | ||
114 | char * s = big_buffer; | ||
115 | |||
116 | s += sprintf(s, "SYSCLKSRC = %08lx\n", SYSCLKSRC); | ||
117 | s += sprintf(s, "PIXCLKSRC = %08lx\n", PIXCLKSRC); | ||
118 | s += sprintf(s, "CLKSLEEP = %08lx\n", CLKSLEEP); | ||
119 | s += sprintf(s, "COREPLL = %08lx\n", COREPLL); | ||
120 | s += sprintf(s, "DISPPLL = %08lx\n", DISPPLL); | ||
121 | s += sprintf(s, "PLLSTAT = %08lx\n", PLLSTAT); | ||
122 | s += sprintf(s, "VOVRCLK = %08lx\n", VOVRCLK); | ||
123 | s += sprintf(s, "PIXCLK = %08lx\n", PIXCLK); | ||
124 | s += sprintf(s, "MEMCLK = %08lx\n", MEMCLK); | ||
125 | s += sprintf(s, "M24CLK = %08lx\n", M24CLK); | ||
126 | s += sprintf(s, "MBXCLK = %08lx\n", MBXCLK); | ||
127 | s += sprintf(s, "SDCLK = %08lx\n", SDCLK); | ||
128 | s += sprintf(s, "PIXCLKDIV = %08lx\n", PIXCLKDIV); | ||
129 | |||
130 | return simple_read_from_buffer(userbuf, count, ppos, | ||
131 | big_buffer, s-big_buffer); | ||
132 | } | ||
133 | |||
134 | static struct file_operations sysconf_fops = { | ||
135 | .read = sysconf_read_file, | ||
136 | .write = write_file_dummy, | ||
137 | .open = open_file_generic, | ||
138 | }; | ||
139 | |||
140 | static struct file_operations clock_fops = { | ||
141 | .read = clock_read_file, | ||
142 | .write = write_file_dummy, | ||
143 | .open = open_file_generic, | ||
144 | }; | ||
145 | |||
146 | static struct file_operations display_fops = { | ||
147 | .read = display_read_file, | ||
148 | .write = write_file_dummy, | ||
149 | .open = open_file_generic, | ||
150 | }; | ||
151 | |||
152 | static struct file_operations gsctl_fops = { | ||
153 | .read = gsctl_read_file, | ||
154 | .write = write_file_dummy, | ||
155 | .open = open_file_generic, | ||
156 | }; | ||
157 | |||
158 | |||
159 | static void __devinit mbxfb_debugfs_init(struct fb_info *fbi) | ||
160 | { | ||
161 | struct mbxfb_info *mfbi = fbi->par; | ||
162 | struct mbxfb_debugfs_data *dbg; | ||
163 | |||
164 | dbg = kzalloc(sizeof(struct mbxfb_debugfs_data), GFP_KERNEL); | ||
165 | mfbi->debugfs_data = dbg; | ||
166 | |||
167 | dbg->dir = debugfs_create_dir("mbxfb", NULL); | ||
168 | dbg->sysconf = debugfs_create_file("sysconf", 0444, dbg->dir, | ||
169 | fbi, &sysconf_fops); | ||
170 | dbg->clock = debugfs_create_file("clock", 0444, dbg->dir, | ||
171 | fbi, &clock_fops); | ||
172 | dbg->display = debugfs_create_file("display", 0444, dbg->dir, | ||
173 | fbi, &display_fops); | ||
174 | dbg->gsctl = debugfs_create_file("gsctl", 0444, dbg->dir, | ||
175 | fbi, &gsctl_fops); | ||
176 | } | ||
177 | |||
178 | static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi) | ||
179 | { | ||
180 | struct mbxfb_info *mfbi = fbi->par; | ||
181 | struct mbxfb_debugfs_data *dbg = mfbi->debugfs_data; | ||
182 | |||
183 | debugfs_remove(dbg->gsctl); | ||
184 | debugfs_remove(dbg->display); | ||
185 | debugfs_remove(dbg->clock); | ||
186 | debugfs_remove(dbg->sysconf); | ||
187 | debugfs_remove(dbg->dir); | ||
188 | } | ||
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c new file mode 100644 index 000000000000..6849ab75d403 --- /dev/null +++ b/drivers/video/mbx/mbxfb.c | |||
@@ -0,0 +1,683 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/mbx/mbxfb.c | ||
3 | * | ||
4 | * Copyright (C) 2006 Compulab, Ltd. | ||
5 | * Mike Rapoport <mike@compulab.co.il> | ||
6 | * | ||
7 | * Based on pxafb.c | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file COPYING in the main directory of this archive for | ||
11 | * more details. | ||
12 | * | ||
13 | * Intel 2700G (Marathon) Graphics Accelerator Frame Buffer Driver | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/delay.h> | ||
18 | #include <linux/fb.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | #include <asm/io.h> | ||
24 | |||
25 | #include <video/mbxfb.h> | ||
26 | |||
27 | #include "regs.h" | ||
28 | #include "reg_bits.h" | ||
29 | |||
30 | static unsigned long virt_base_2700; | ||
31 | |||
32 | #define MIN_XRES 16 | ||
33 | #define MIN_YRES 16 | ||
34 | #define MAX_XRES 2048 | ||
35 | #define MAX_YRES 2048 | ||
36 | |||
37 | #define MAX_PALETTES 16 | ||
38 | |||
39 | /* FIXME: take care of different chip revisions with different sizes | ||
40 | of ODFB */ | ||
41 | #define MEMORY_OFFSET 0x60000 | ||
42 | |||
43 | struct mbxfb_info { | ||
44 | struct device *dev; | ||
45 | |||
46 | struct resource *fb_res; | ||
47 | struct resource *fb_req; | ||
48 | |||
49 | struct resource *reg_res; | ||
50 | struct resource *reg_req; | ||
51 | |||
52 | void __iomem *fb_virt_addr; | ||
53 | unsigned long fb_phys_addr; | ||
54 | |||
55 | void __iomem *reg_virt_addr; | ||
56 | unsigned long reg_phys_addr; | ||
57 | |||
58 | int (*platform_probe) (struct fb_info * fb); | ||
59 | int (*platform_remove) (struct fb_info * fb); | ||
60 | |||
61 | u32 pseudo_palette[MAX_PALETTES]; | ||
62 | #ifdef CONFIG_FB_MBX_DEBUG | ||
63 | void *debugfs_data; | ||
64 | #endif | ||
65 | |||
66 | }; | ||
67 | |||
68 | static struct fb_var_screeninfo mbxfb_default __devinitdata = { | ||
69 | .xres = 640, | ||
70 | .yres = 480, | ||
71 | .xres_virtual = 640, | ||
72 | .yres_virtual = 480, | ||
73 | .bits_per_pixel = 16, | ||
74 | .red = {11, 5, 0}, | ||
75 | .green = {5, 6, 0}, | ||
76 | .blue = {0, 5, 0}, | ||
77 | .activate = FB_ACTIVATE_TEST, | ||
78 | .height = -1, | ||
79 | .width = -1, | ||
80 | .pixclock = 40000, | ||
81 | .left_margin = 48, | ||
82 | .right_margin = 16, | ||
83 | .upper_margin = 33, | ||
84 | .lower_margin = 10, | ||
85 | .hsync_len = 96, | ||
86 | .vsync_len = 2, | ||
87 | .vmode = FB_VMODE_NONINTERLACED, | ||
88 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
89 | }; | ||
90 | |||
91 | static struct fb_fix_screeninfo mbxfb_fix __devinitdata = { | ||
92 | .id = "MBX", | ||
93 | .type = FB_TYPE_PACKED_PIXELS, | ||
94 | .visual = FB_VISUAL_TRUECOLOR, | ||
95 | .xpanstep = 0, | ||
96 | .ypanstep = 0, | ||
97 | .ywrapstep = 0, | ||
98 | .accel = FB_ACCEL_NONE, | ||
99 | }; | ||
100 | |||
101 | struct pixclock_div { | ||
102 | u8 m; | ||
103 | u8 n; | ||
104 | u8 p; | ||
105 | }; | ||
106 | |||
107 | static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps, | ||
108 | struct pixclock_div *div) | ||
109 | { | ||
110 | u8 m, n, p; | ||
111 | unsigned int err = 0; | ||
112 | unsigned int min_err = ~0x0; | ||
113 | unsigned int clk; | ||
114 | unsigned int best_clk = 0; | ||
115 | unsigned int ref_clk = 13000; /* FIXME: take from platform data */ | ||
116 | unsigned int pixclock; | ||
117 | |||
118 | /* convert pixclock to KHz */ | ||
119 | pixclock = PICOS2KHZ(pixclock_ps); | ||
120 | |||
121 | for (m = 1; m < 64; m++) { | ||
122 | for (n = 1; n < 8; n++) { | ||
123 | for (p = 0; p < 8; p++) { | ||
124 | clk = (ref_clk * m) / (n * (1 << p)); | ||
125 | err = (clk > pixclock) ? (clk - pixclock) : | ||
126 | (pixclock - clk); | ||
127 | if (err < min_err) { | ||
128 | min_err = err; | ||
129 | best_clk = clk; | ||
130 | div->m = m; | ||
131 | div->n = n; | ||
132 | div->p = p; | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | return KHZ2PICOS(best_clk); | ||
138 | } | ||
139 | |||
140 | static int mbxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | ||
141 | u_int trans, struct fb_info *info) | ||
142 | { | ||
143 | u32 val, ret = 1; | ||
144 | |||
145 | if (regno < MAX_PALETTES) { | ||
146 | u32 *pal = info->pseudo_palette; | ||
147 | |||
148 | val = (red & 0xf800) | ((green & 0xfc00) >> 5) | | ||
149 | ((blue & 0xf800) >> 11); | ||
150 | pal[regno] = val; | ||
151 | ret = 0; | ||
152 | } | ||
153 | |||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | static int mbxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | ||
158 | { | ||
159 | struct pixclock_div div; | ||
160 | |||
161 | var->pixclock = mbxfb_get_pixclock(var->pixclock, &div); | ||
162 | |||
163 | if (var->xres < MIN_XRES) | ||
164 | var->xres = MIN_XRES; | ||
165 | if (var->yres < MIN_YRES) | ||
166 | var->yres = MIN_YRES; | ||
167 | if (var->xres > MAX_XRES) | ||
168 | return -EINVAL; | ||
169 | if (var->yres > MAX_YRES) | ||
170 | return -EINVAL; | ||
171 | var->xres_virtual = max(var->xres_virtual, var->xres); | ||
172 | var->yres_virtual = max(var->yres_virtual, var->yres); | ||
173 | |||
174 | switch (var->bits_per_pixel) { | ||
175 | /* 8 bits-per-pixel is not supported yet */ | ||
176 | case 8: | ||
177 | return -EINVAL; | ||
178 | case 16: | ||
179 | var->green.length = (var->green.length == 5) ? 5 : 6; | ||
180 | var->red.length = 5; | ||
181 | var->blue.length = 5; | ||
182 | var->transp.length = 6 - var->green.length; | ||
183 | var->blue.offset = 0; | ||
184 | var->green.offset = 5; | ||
185 | var->red.offset = 5 + var->green.length; | ||
186 | var->transp.offset = (5 + var->red.offset) & 15; | ||
187 | break; | ||
188 | case 24: /* RGB 888 */ | ||
189 | case 32: /* RGBA 8888 */ | ||
190 | var->red.offset = 16; | ||
191 | var->red.length = 8; | ||
192 | var->green.offset = 8; | ||
193 | var->green.length = 8; | ||
194 | var->blue.offset = 0; | ||
195 | var->blue.length = 8; | ||
196 | var->transp.length = var->bits_per_pixel - 24; | ||
197 | var->transp.offset = (var->transp.length) ? 24 : 0; | ||
198 | break; | ||
199 | } | ||
200 | var->red.msb_right = 0; | ||
201 | var->green.msb_right = 0; | ||
202 | var->blue.msb_right = 0; | ||
203 | var->transp.msb_right = 0; | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int mbxfb_set_par(struct fb_info *info) | ||
209 | { | ||
210 | struct fb_var_screeninfo *var = &info->var; | ||
211 | struct pixclock_div div; | ||
212 | ushort hbps, ht, hfps, has; | ||
213 | ushort vbps, vt, vfps, vas; | ||
214 | u32 gsctrl = readl(GSCTRL); | ||
215 | u32 gsadr = readl(GSADR); | ||
216 | |||
217 | info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; | ||
218 | |||
219 | /* setup color mode */ | ||
220 | gsctrl &= ~(FMsk(GSCTRL_GPIXFMT)); | ||
221 | /* FIXME: add *WORKING* support for 8-bits per color */ | ||
222 | if (info->var.bits_per_pixel == 8) { | ||
223 | return -EINVAL; | ||
224 | } else { | ||
225 | fb_dealloc_cmap(&info->cmap); | ||
226 | gsctrl &= ~GSCTRL_LUT_EN; | ||
227 | |||
228 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
229 | switch (info->var.bits_per_pixel) { | ||
230 | case 16: | ||
231 | if (info->var.green.length == 5) | ||
232 | gsctrl |= GSCTRL_GPIXFMT_ARGB1555; | ||
233 | else | ||
234 | gsctrl |= GSCTRL_GPIXFMT_RGB565; | ||
235 | break; | ||
236 | case 24: | ||
237 | gsctrl |= GSCTRL_GPIXFMT_RGB888; | ||
238 | break; | ||
239 | case 32: | ||
240 | gsctrl |= GSCTRL_GPIXFMT_ARGB8888; | ||
241 | break; | ||
242 | } | ||
243 | } | ||
244 | |||
245 | /* setup resolution */ | ||
246 | gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT)); | ||
247 | gsctrl |= Gsctrl_Width(info->var.xres - 1) | | ||
248 | Gsctrl_Height(info->var.yres - 1); | ||
249 | writel(gsctrl, GSCTRL); | ||
250 | udelay(1000); | ||
251 | |||
252 | gsadr &= ~(FMsk(GSADR_SRCSTRIDE)); | ||
253 | gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel / | ||
254 | (8 * 16) - 1); | ||
255 | writel(gsadr, GSADR); | ||
256 | udelay(1000); | ||
257 | |||
258 | /* setup timings */ | ||
259 | var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div); | ||
260 | |||
261 | writel((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) | | ||
262 | Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL); | ||
263 | |||
264 | hbps = var->hsync_len; | ||
265 | has = hbps + var->left_margin; | ||
266 | hfps = has + var->xres; | ||
267 | ht = hfps + var->right_margin; | ||
268 | |||
269 | vbps = var->vsync_len; | ||
270 | vas = vbps + var->upper_margin; | ||
271 | vfps = vas + var->yres; | ||
272 | vt = vfps + var->lower_margin; | ||
273 | |||
274 | writel((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01); | ||
275 | writel((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02); | ||
276 | writel((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03); | ||
277 | writel((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET); | ||
278 | |||
279 | writel((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01); | ||
280 | writel((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02); | ||
281 | writel((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03); | ||
282 | writel((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET); | ||
283 | writel((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL); | ||
284 | |||
285 | writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static int mbxfb_blank(int blank, struct fb_info *info) | ||
291 | { | ||
292 | switch (blank) { | ||
293 | case FB_BLANK_POWERDOWN: | ||
294 | case FB_BLANK_VSYNC_SUSPEND: | ||
295 | case FB_BLANK_HSYNC_SUSPEND: | ||
296 | case FB_BLANK_NORMAL: | ||
297 | writel((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL); | ||
298 | udelay(1000); | ||
299 | writel((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK); | ||
300 | udelay(1000); | ||
301 | writel((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK); | ||
302 | udelay(1000); | ||
303 | break; | ||
304 | case FB_BLANK_UNBLANK: | ||
305 | writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); | ||
306 | udelay(1000); | ||
307 | writel((readl(PIXCLK) | PIXCLK_EN), PIXCLK); | ||
308 | udelay(1000); | ||
309 | break; | ||
310 | } | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static struct fb_ops mbxfb_ops = { | ||
315 | .owner = THIS_MODULE, | ||
316 | .fb_check_var = mbxfb_check_var, | ||
317 | .fb_set_par = mbxfb_set_par, | ||
318 | .fb_setcolreg = mbxfb_setcolreg, | ||
319 | .fb_fillrect = cfb_fillrect, | ||
320 | .fb_copyarea = cfb_copyarea, | ||
321 | .fb_imageblit = cfb_imageblit, | ||
322 | .fb_blank = mbxfb_blank, | ||
323 | }; | ||
324 | |||
325 | /* | ||
326 | Enable external SDRAM controller. Assume that all clocks are active | ||
327 | by now. | ||
328 | */ | ||
329 | static void __devinit setup_memc(struct fb_info *fbi) | ||
330 | { | ||
331 | struct mbxfb_info *mfbi = fbi->par; | ||
332 | unsigned long tmp; | ||
333 | int i; | ||
334 | |||
335 | /* FIXME: use platfrom specific parameters */ | ||
336 | /* setup SDRAM controller */ | ||
337 | writel((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | | ||
338 | LMCFG_LMA_TS), | ||
339 | LMCFG); | ||
340 | udelay(1000); | ||
341 | |||
342 | writel(LMPWR_MC_PWR_ACT, LMPWR); | ||
343 | udelay(1000); | ||
344 | |||
345 | /* setup SDRAM timings */ | ||
346 | writel((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) | | ||
347 | Lmtim_Trc(9) | Lmtim_Tdpl(2)), | ||
348 | LMTIM); | ||
349 | udelay(1000); | ||
350 | /* setup SDRAM refresh rate */ | ||
351 | writel(0xc2b, LMREFRESH); | ||
352 | udelay(1000); | ||
353 | /* setup SDRAM type parameters */ | ||
354 | writel((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 | | ||
355 | LMTYPE_COLSZ_8), | ||
356 | LMTYPE); | ||
357 | udelay(1000); | ||
358 | /* enable memory controller */ | ||
359 | writel(LMPWR_MC_PWR_ACT, LMPWR); | ||
360 | udelay(1000); | ||
361 | |||
362 | /* perform dummy reads */ | ||
363 | for ( i = 0; i < 16; i++ ) { | ||
364 | tmp = readl(fbi->screen_base); | ||
365 | } | ||
366 | } | ||
367 | |||
368 | static void enable_clocks(struct fb_info *fbi) | ||
369 | { | ||
370 | /* enable clocks */ | ||
371 | writel(SYSCLKSRC_PLL_2, SYSCLKSRC); | ||
372 | udelay(1000); | ||
373 | writel(PIXCLKSRC_PLL_1, PIXCLKSRC); | ||
374 | udelay(1000); | ||
375 | writel(0x00000000, CLKSLEEP); | ||
376 | udelay(1000); | ||
377 | writel((Core_Pll_M(0x17) | Core_Pll_N(0x3) | Core_Pll_P(0x0) | | ||
378 | CORE_PLL_EN), | ||
379 | COREPLL); | ||
380 | udelay(1000); | ||
381 | writel((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) | | ||
382 | DISP_PLL_EN), | ||
383 | DISPPLL); | ||
384 | |||
385 | writel(0x00000000, VOVRCLK); | ||
386 | udelay(1000); | ||
387 | writel(PIXCLK_EN, PIXCLK); | ||
388 | udelay(1000); | ||
389 | writel(MEMCLK_EN, MEMCLK); | ||
390 | udelay(1000); | ||
391 | writel(0x00000006, M24CLK); | ||
392 | udelay(1000); | ||
393 | writel(0x00000006, MBXCLK); | ||
394 | udelay(1000); | ||
395 | writel(SDCLK_EN, SDCLK); | ||
396 | udelay(1000); | ||
397 | writel(0x00000001, PIXCLKDIV); | ||
398 | udelay(1000); | ||
399 | } | ||
400 | |||
401 | static void __devinit setup_graphics(struct fb_info *fbi) | ||
402 | { | ||
403 | unsigned long gsctrl; | ||
404 | |||
405 | gsctrl = GSCTRL_GAMMA_EN | Gsctrl_Width(fbi->var.xres - 1) | | ||
406 | Gsctrl_Height(fbi->var.yres - 1); | ||
407 | switch (fbi->var.bits_per_pixel) { | ||
408 | case 16: | ||
409 | if (fbi->var.green.length == 5) | ||
410 | gsctrl |= GSCTRL_GPIXFMT_ARGB1555; | ||
411 | else | ||
412 | gsctrl |= GSCTRL_GPIXFMT_RGB565; | ||
413 | break; | ||
414 | case 24: | ||
415 | gsctrl |= GSCTRL_GPIXFMT_RGB888; | ||
416 | break; | ||
417 | case 32: | ||
418 | gsctrl |= GSCTRL_GPIXFMT_ARGB8888; | ||
419 | break; | ||
420 | } | ||
421 | |||
422 | writel(gsctrl, GSCTRL); | ||
423 | udelay(1000); | ||
424 | writel(0x00000000, GBBASE); | ||
425 | udelay(1000); | ||
426 | writel(0x00ffffff, GDRCTRL); | ||
427 | udelay(1000); | ||
428 | writel((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR); | ||
429 | udelay(1000); | ||
430 | writel(0x00000000, GPLUT); | ||
431 | udelay(1000); | ||
432 | } | ||
433 | |||
434 | static void __devinit setup_display(struct fb_info *fbi) | ||
435 | { | ||
436 | unsigned long dsctrl = 0; | ||
437 | |||
438 | dsctrl = DSCTRL_BLNK_POL; | ||
439 | if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT) | ||
440 | dsctrl |= DSCTRL_HS_POL; | ||
441 | if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) | ||
442 | dsctrl |= DSCTRL_VS_POL; | ||
443 | writel(dsctrl, DSCTRL); | ||
444 | udelay(1000); | ||
445 | writel(0xd0303010, DMCTRL); | ||
446 | udelay(1000); | ||
447 | writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); | ||
448 | } | ||
449 | |||
450 | static void __devinit enable_controller(struct fb_info *fbi) | ||
451 | { | ||
452 | writel(SYSRST_RST, SYSRST); | ||
453 | udelay(1000); | ||
454 | |||
455 | |||
456 | enable_clocks(fbi); | ||
457 | setup_memc(fbi); | ||
458 | setup_graphics(fbi); | ||
459 | setup_display(fbi); | ||
460 | } | ||
461 | |||
462 | #ifdef CONFIG_PM | ||
463 | /* | ||
464 | * Power management hooks. Note that we won't be called from IRQ context, | ||
465 | * unlike the blank functions above, so we may sleep. | ||
466 | */ | ||
467 | static int mbxfb_suspend(struct platform_device *dev, pm_message_t state) | ||
468 | { | ||
469 | /* make frame buffer memory enter self-refresh mode */ | ||
470 | writel(LMPWR_MC_PWR_SRM, LMPWR); | ||
471 | while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM) | ||
472 | ; /* empty statement */ | ||
473 | |||
474 | /* reset the device, since it's initial state is 'mostly sleeping' */ | ||
475 | writel(SYSRST_RST, SYSRST); | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static int mbxfb_resume(struct platform_device *dev) | ||
480 | { | ||
481 | struct fb_info *fbi = platform_get_drvdata(dev); | ||
482 | |||
483 | enable_clocks(fbi); | ||
484 | /* setup_graphics(fbi); */ | ||
485 | /* setup_display(fbi); */ | ||
486 | |||
487 | writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); | ||
488 | return 0; | ||
489 | } | ||
490 | #else | ||
491 | #define mbxfb_suspend NULL | ||
492 | #define mbxfb_resume NULL | ||
493 | #endif | ||
494 | |||
495 | /* debugfs entries */ | ||
496 | #ifndef CONFIG_FB_MBX_DEBUG | ||
497 | #define mbxfb_debugfs_init(x) do {} while(0) | ||
498 | #define mbxfb_debugfs_remove(x) do {} while(0) | ||
499 | #endif | ||
500 | |||
501 | #define res_size(_r) (((_r)->end - (_r)->start) + 1) | ||
502 | |||
503 | static int __devinit mbxfb_probe(struct platform_device *dev) | ||
504 | { | ||
505 | int ret; | ||
506 | struct fb_info *fbi; | ||
507 | struct mbxfb_info *mfbi; | ||
508 | struct mbxfb_platform_data *pdata; | ||
509 | |||
510 | dev_dbg(dev, "mbxfb_probe\n"); | ||
511 | |||
512 | fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev); | ||
513 | if (fbi == NULL) { | ||
514 | dev_err(&dev->dev, "framebuffer_alloc failed\n"); | ||
515 | return -ENOMEM; | ||
516 | } | ||
517 | |||
518 | mfbi = fbi->par; | ||
519 | fbi->pseudo_palette = mfbi->pseudo_palette; | ||
520 | pdata = dev->dev.platform_data; | ||
521 | if (pdata->probe) | ||
522 | mfbi->platform_probe = pdata->probe; | ||
523 | if (pdata->remove) | ||
524 | mfbi->platform_remove = pdata->remove; | ||
525 | |||
526 | mfbi->fb_res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
527 | mfbi->reg_res = platform_get_resource(dev, IORESOURCE_MEM, 1); | ||
528 | |||
529 | if (!mfbi->fb_res || !mfbi->reg_res) { | ||
530 | dev_err(&dev->dev, "no resources found\n"); | ||
531 | ret = -ENODEV; | ||
532 | goto err1; | ||
533 | } | ||
534 | |||
535 | mfbi->fb_req = request_mem_region(mfbi->fb_res->start, | ||
536 | res_size(mfbi->fb_res), dev->name); | ||
537 | if (mfbi->fb_req == NULL) { | ||
538 | dev_err(&dev->dev, "failed to claim framebuffer memory\n"); | ||
539 | ret = -EINVAL; | ||
540 | goto err1; | ||
541 | } | ||
542 | mfbi->fb_phys_addr = mfbi->fb_res->start; | ||
543 | |||
544 | mfbi->reg_req = request_mem_region(mfbi->reg_res->start, | ||
545 | res_size(mfbi->reg_res), dev->name); | ||
546 | if (mfbi->reg_req == NULL) { | ||
547 | dev_err(&dev->dev, "failed to claim Marathon registers\n"); | ||
548 | ret = -EINVAL; | ||
549 | goto err2; | ||
550 | } | ||
551 | mfbi->reg_phys_addr = mfbi->reg_res->start; | ||
552 | |||
553 | mfbi->reg_virt_addr = ioremap_nocache(mfbi->reg_phys_addr, | ||
554 | res_size(mfbi->reg_req)); | ||
555 | if (!mfbi->reg_virt_addr) { | ||
556 | dev_err(&dev->dev, "failed to ioremap Marathon registers\n"); | ||
557 | ret = -EINVAL; | ||
558 | goto err3; | ||
559 | } | ||
560 | virt_base_2700 = (unsigned long)mfbi->reg_virt_addr; | ||
561 | |||
562 | mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr, | ||
563 | res_size(mfbi->fb_req)); | ||
564 | if (!mfbi->reg_virt_addr) { | ||
565 | dev_err(&dev->dev, "failed to ioremap frame buffer\n"); | ||
566 | ret = -EINVAL; | ||
567 | goto err4; | ||
568 | } | ||
569 | |||
570 | /* FIXME: get from platform */ | ||
571 | fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000); | ||
572 | fbi->screen_size = 8 * 1024 * 1024; /* 8 Megs */ | ||
573 | fbi->fbops = &mbxfb_ops; | ||
574 | |||
575 | fbi->var = mbxfb_default; | ||
576 | fbi->fix = mbxfb_fix; | ||
577 | fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000; | ||
578 | fbi->fix.smem_len = 8 * 1024 * 1024; | ||
579 | fbi->fix.line_length = 640 * 2; | ||
580 | |||
581 | ret = fb_alloc_cmap(&fbi->cmap, 256, 0); | ||
582 | if (ret < 0) { | ||
583 | dev_err(&dev->dev, "fb_alloc_cmap failed\n"); | ||
584 | ret = -EINVAL; | ||
585 | goto err5; | ||
586 | } | ||
587 | |||
588 | platform_set_drvdata(dev, fbi); | ||
589 | |||
590 | printk(KERN_INFO "fb%d: mbx frame buffer device\n", fbi->node); | ||
591 | |||
592 | if (mfbi->platform_probe) | ||
593 | mfbi->platform_probe(fbi); | ||
594 | |||
595 | enable_controller(fbi); | ||
596 | |||
597 | mbxfb_debugfs_init(fbi); | ||
598 | |||
599 | ret = register_framebuffer(fbi); | ||
600 | if (ret < 0) { | ||
601 | dev_err(&dev->dev, "register_framebuffer failed\n"); | ||
602 | ret = -EINVAL; | ||
603 | goto err6; | ||
604 | } | ||
605 | |||
606 | return 0; | ||
607 | |||
608 | err6: | ||
609 | fb_dealloc_cmap(&fbi->cmap); | ||
610 | err5: | ||
611 | iounmap(mfbi->fb_virt_addr); | ||
612 | err4: | ||
613 | iounmap(mfbi->reg_virt_addr); | ||
614 | err3: | ||
615 | release_mem_region(mfbi->reg_res->start, res_size(mfbi->reg_res)); | ||
616 | err2: | ||
617 | release_mem_region(mfbi->fb_res->start, res_size(mfbi->fb_res)); | ||
618 | err1: | ||
619 | framebuffer_release(fbi); | ||
620 | |||
621 | return ret; | ||
622 | } | ||
623 | |||
624 | static int __devexit mbxfb_remove(struct platform_device *dev) | ||
625 | { | ||
626 | struct fb_info *fbi = platform_get_drvdata(dev); | ||
627 | |||
628 | writel(SYSRST_RST, SYSRST); | ||
629 | udelay(1000); | ||
630 | |||
631 | mbxfb_debugfs_remove(fbi); | ||
632 | |||
633 | if (fbi) { | ||
634 | struct mbxfb_info *mfbi = fbi->par; | ||
635 | |||
636 | unregister_framebuffer(fbi); | ||
637 | if (mfbi) { | ||
638 | if (mfbi->platform_remove) | ||
639 | mfbi->platform_remove(fbi); | ||
640 | |||
641 | if (mfbi->fb_virt_addr) | ||
642 | iounmap(mfbi->fb_virt_addr); | ||
643 | if (mfbi->reg_virt_addr) | ||
644 | iounmap(mfbi->reg_virt_addr); | ||
645 | if (mfbi->reg_req) | ||
646 | release_mem_region(mfbi->reg_req->start, | ||
647 | res_size(mfbi->reg_req)); | ||
648 | if (mfbi->fb_req) | ||
649 | release_mem_region(mfbi->fb_req->start, | ||
650 | res_size(mfbi->fb_req)); | ||
651 | } | ||
652 | framebuffer_release(fbi); | ||
653 | } | ||
654 | |||
655 | return 0; | ||
656 | } | ||
657 | |||
658 | static struct platform_driver mbxfb_driver = { | ||
659 | .probe = mbxfb_probe, | ||
660 | .remove = mbxfb_remove, | ||
661 | .suspend = mbxfb_suspend, | ||
662 | .resume = mbxfb_resume, | ||
663 | .driver = { | ||
664 | .name = "mbx-fb", | ||
665 | }, | ||
666 | }; | ||
667 | |||
668 | int __devinit mbxfb_init(void) | ||
669 | { | ||
670 | return platform_driver_register(&mbxfb_driver); | ||
671 | } | ||
672 | |||
673 | static void __devexit mbxfb_exit(void) | ||
674 | { | ||
675 | platform_driver_unregister(&mbxfb_driver); | ||
676 | } | ||
677 | |||
678 | module_init(mbxfb_init); | ||
679 | module_exit(mbxfb_exit); | ||
680 | |||
681 | MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device"); | ||
682 | MODULE_AUTHOR("Mike Rapoport, Compulab"); | ||
683 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/mbx/reg_bits.h b/drivers/video/mbx/reg_bits.h new file mode 100644 index 000000000000..c226a8e45312 --- /dev/null +++ b/drivers/video/mbx/reg_bits.h | |||
@@ -0,0 +1,418 @@ | |||
1 | #ifndef __REG_BITS_2700G_ | ||
2 | #define __REG_BITS_2700G_ | ||
3 | |||
4 | /* use defines from asm-arm/arch-pxa/bitfields.h for bit fields access */ | ||
5 | #define UData(Data) ((unsigned long) (Data)) | ||
6 | #define Fld(Size, Shft) (((Size) << 16) + (Shft)) | ||
7 | #define FSize(Field) ((Field) >> 16) | ||
8 | #define FShft(Field) ((Field) & 0x0000FFFF) | ||
9 | #define FMsk(Field) (((UData (1) << FSize (Field)) - 1) << FShft (Field)) | ||
10 | #define FAlnMsk(Field) ((UData (1) << FSize (Field)) - 1) | ||
11 | #define F1stBit(Field) (UData (1) << FShft (Field)) | ||
12 | |||
13 | #define SYSRST_RST (1 << 0) | ||
14 | |||
15 | /* SYSCLKSRC - SYSCLK Source Control Register */ | ||
16 | #define SYSCLKSRC_SEL Fld(2,0) | ||
17 | #define SYSCLKSRC_REF ((0x0) << FShft(SYSCLKSRC_SEL)) | ||
18 | #define SYSCLKSRC_PLL_1 ((0x1) << FShft(SYSCLKSRC_SEL)) | ||
19 | #define SYSCLKSRC_PLL_2 ((0x2) << FShft(SYSCLKSRC_SEL)) | ||
20 | |||
21 | /* PIXCLKSRC - PIXCLK Source Control Register */ | ||
22 | #define PIXCLKSRC_SEL Fld(2,0) | ||
23 | #define PIXCLKSRC_REF ((0x0) << FShft(PIXCLKSRC_SEL)) | ||
24 | #define PIXCLKSRC_PLL_1 ((0x1) << FShft(PIXCLKSRC_SEL)) | ||
25 | #define PIXCLKSRC_PLL_2 ((0x2) << FShft(PIXCLKSRC_SEL)) | ||
26 | |||
27 | /* Clock Disable Register */ | ||
28 | #define CLKSLEEP_SLP (1 << 0) | ||
29 | |||
30 | /* Core PLL Control Register */ | ||
31 | #define CORE_PLL_M Fld(6,7) | ||
32 | #define Core_Pll_M(x) ((x) << FShft(CORE_PLL_M)) | ||
33 | #define CORE_PLL_N Fld(3,4) | ||
34 | #define Core_Pll_N(x) ((x) << FShft(CORE_PLL_N)) | ||
35 | #define CORE_PLL_P Fld(3,1) | ||
36 | #define Core_Pll_P(x) ((x) << FShft(CORE_PLL_P)) | ||
37 | #define CORE_PLL_EN (1 << 0) | ||
38 | |||
39 | /* Display PLL Control Register */ | ||
40 | #define DISP_PLL_M Fld(6,7) | ||
41 | #define Disp_Pll_M(x) ((x) << FShft(DISP_PLL_M)) | ||
42 | #define DISP_PLL_N Fld(3,4) | ||
43 | #define Disp_Pll_N(x) ((x) << FShft(DISP_PLL_N)) | ||
44 | #define DISP_PLL_P Fld(3,1) | ||
45 | #define Disp_Pll_P(x) ((x) << FShft(DISP_PLL_P)) | ||
46 | #define DISP_PLL_EN (1 << 0) | ||
47 | |||
48 | /* PLL status register */ | ||
49 | #define PLLSTAT_CORE_PLL_LOST_L (1 << 3) | ||
50 | #define PLLSTAT_CORE_PLL_LSTS (1 << 2) | ||
51 | #define PLLSTAT_DISP_PLL_LOST_L (1 << 1) | ||
52 | #define PLLSTAT_DISP_PLL_LSTS (1 << 0) | ||
53 | |||
54 | /* Video and scale clock control register */ | ||
55 | #define VOVRCLK_EN (1 << 0) | ||
56 | |||
57 | /* Pixel clock control register */ | ||
58 | #define PIXCLK_EN (1 << 0) | ||
59 | |||
60 | /* Memory clock control register */ | ||
61 | #define MEMCLK_EN (1 << 0) | ||
62 | |||
63 | /* MBX clock control register */ | ||
64 | #define MBXCLK_DIV Fld(2,2) | ||
65 | #define MBXCLK_DIV_1 ((0x0) << FShft(MBXCLK_DIV)) | ||
66 | #define MBXCLK_DIV_2 ((0x1) << FShft(MBXCLK_DIV)) | ||
67 | #define MBXCLK_DIV_3 ((0x2) << FShft(MBXCLK_DIV)) | ||
68 | #define MBXCLK_DIV_4 ((0x3) << FShft(MBXCLK_DIV)) | ||
69 | #define MBXCLK_EN Fld(2,0) | ||
70 | #define MBXCLK_EN_NONE ((0x0) << FShft(MBXCLK_EN)) | ||
71 | #define MBXCLK_EN_2D ((0x1) << FShft(MBXCLK_EN)) | ||
72 | #define MBXCLK_EN_BOTH ((0x2) << FShft(MBXCLK_EN)) | ||
73 | |||
74 | /* M24 clock control register */ | ||
75 | #define M24CLK_DIV Fld(2,1) | ||
76 | #define M24CLK_DIV_1 ((0x0) << FShft(M24CLK_DIV)) | ||
77 | #define M24CLK_DIV_2 ((0x1) << FShft(M24CLK_DIV)) | ||
78 | #define M24CLK_DIV_3 ((0x2) << FShft(M24CLK_DIV)) | ||
79 | #define M24CLK_DIV_4 ((0x3) << FShft(M24CLK_DIV)) | ||
80 | #define M24CLK_EN (1 << 0) | ||
81 | |||
82 | /* SDRAM clock control register */ | ||
83 | #define SDCLK_EN (1 << 0) | ||
84 | |||
85 | /* PixClk Divisor Register */ | ||
86 | #define PIXCLKDIV_PD Fld(9,0) | ||
87 | #define Pixclkdiv_Pd(x) ((x) << FShft(PIXCLKDIV_PD)) | ||
88 | |||
89 | /* LCD Config control register */ | ||
90 | #define LCDCFG_IN_FMT Fld(3,28) | ||
91 | #define Lcdcfg_In_Fmt(x) ((x) << FShft(LCDCFG_IN_FMT)) | ||
92 | #define LCDCFG_LCD1DEN_POL (1 << 27) | ||
93 | #define LCDCFG_LCD1FCLK_POL (1 << 26) | ||
94 | #define LCDCFG_LCD1LCLK_POL (1 << 25) | ||
95 | #define LCDCFG_LCD1D_POL (1 << 24) | ||
96 | #define LCDCFG_LCD2DEN_POL (1 << 23) | ||
97 | #define LCDCFG_LCD2FCLK_POL (1 << 22) | ||
98 | #define LCDCFG_LCD2LCLK_POL (1 << 21) | ||
99 | #define LCDCFG_LCD2D_POL (1 << 20) | ||
100 | #define LCDCFG_LCD1_TS (1 << 19) | ||
101 | #define LCDCFG_LCD1D_DS (1 << 18) | ||
102 | #define LCDCFG_LCD1C_DS (1 << 17) | ||
103 | #define LCDCFG_LCD1_IS_IN (1 << 16) | ||
104 | #define LCDCFG_LCD2_TS (1 << 3) | ||
105 | #define LCDCFG_LCD2D_DS (1 << 2) | ||
106 | #define LCDCFG_LCD2C_DS (1 << 1) | ||
107 | #define LCDCFG_LCD2_IS_IN (1 << 0) | ||
108 | |||
109 | /* On-Die Frame Buffer Power Control Register */ | ||
110 | #define ODFBPWR_SLOW (1 << 2) | ||
111 | #define ODFBPWR_MODE Fld(2,0) | ||
112 | #define ODFBPWR_MODE_ACT ((0x0) << FShft(ODFBPWR_MODE)) | ||
113 | #define ODFBPWR_MODE_ACT_LP ((0x1) << FShft(ODFBPWR_MODE)) | ||
114 | #define ODFBPWR_MODE_SLEEP ((0x2) << FShft(ODFBPWR_MODE)) | ||
115 | #define ODFBPWR_MODE_SHUTD ((0x3) << FShft(ODFBPWR_MODE)) | ||
116 | |||
117 | /* On-Die Frame Buffer Power State Status Register */ | ||
118 | #define ODFBSTAT_ACT (1 << 2) | ||
119 | #define ODFBSTAT_SLP (1 << 1) | ||
120 | #define ODFBSTAT_SDN (1 << 0) | ||
121 | |||
122 | /* LMRST - Local Memory (SDRAM) Reset */ | ||
123 | #define LMRST_MC_RST (1 << 0) | ||
124 | |||
125 | /* LMCFG - Local Memory (SDRAM) Configuration Register */ | ||
126 | #define LMCFG_LMC_DS (1 << 5) | ||
127 | #define LMCFG_LMD_DS (1 << 4) | ||
128 | #define LMCFG_LMA_DS (1 << 3) | ||
129 | #define LMCFG_LMC_TS (1 << 2) | ||
130 | #define LMCFG_LMD_TS (1 << 1) | ||
131 | #define LMCFG_LMA_TS (1 << 0) | ||
132 | |||
133 | /* LMPWR - Local Memory (SDRAM) Power Control Register */ | ||
134 | #define LMPWR_MC_PWR_CNT Fld(2,0) | ||
135 | #define LMPWR_MC_PWR_ACT ((0x0) << FShft(LMPWR_MC_PWR_CNT)) /* Active */ | ||
136 | #define LMPWR_MC_PWR_SRM ((0x1) << FShft(LMPWR_MC_PWR_CNT)) /* Self-refresh */ | ||
137 | #define LMPWR_MC_PWR_DPD ((0x3) << FShft(LMPWR_MC_PWR_CNT)) /* deep power down */ | ||
138 | |||
139 | /* LMPWRSTAT - Local Memory (SDRAM) Power Status Register */ | ||
140 | #define LMPWRSTAT_MC_PWR_CNT Fld(2,0) | ||
141 | #define LMPWRSTAT_MC_PWR_ACT ((0x0) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Active */ | ||
142 | #define LMPWRSTAT_MC_PWR_SRM ((0x1) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Self-refresh */ | ||
143 | #define LMPWRSTAT_MC_PWR_DPD ((0x3) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* deep power down */ | ||
144 | |||
145 | /* LMTYPE - Local Memory (SDRAM) Type Register */ | ||
146 | #define LMTYPE_CASLAT Fld(3,10) | ||
147 | #define LMTYPE_CASLAT_1 ((0x1) << FShft(LMTYPE_CASLAT)) | ||
148 | #define LMTYPE_CASLAT_2 ((0x2) << FShft(LMTYPE_CASLAT)) | ||
149 | #define LMTYPE_CASLAT_3 ((0x3) << FShft(LMTYPE_CASLAT)) | ||
150 | #define LMTYPE_BKSZ Fld(2,8) | ||
151 | #define LMTYPE_BKSZ_1 ((0x1) << FShft(LMTYPE_BKSZ)) | ||
152 | #define LMTYPE_BKSZ_2 ((0x2) << FShft(LMTYPE_BKSZ)) | ||
153 | #define LMTYPE_ROWSZ Fld(4,4) | ||
154 | #define LMTYPE_ROWSZ_11 ((0xb) << FShft(LMTYPE_ROWSZ)) | ||
155 | #define LMTYPE_ROWSZ_12 ((0xc) << FShft(LMTYPE_ROWSZ)) | ||
156 | #define LMTYPE_ROWSZ_13 ((0xd) << FShft(LMTYPE_ROWSZ)) | ||
157 | #define LMTYPE_COLSZ Fld(4,0) | ||
158 | #define LMTYPE_COLSZ_7 ((0x7) << FShft(LMTYPE_COLSZ)) | ||
159 | #define LMTYPE_COLSZ_8 ((0x8) << FShft(LMTYPE_COLSZ)) | ||
160 | #define LMTYPE_COLSZ_9 ((0x9) << FShft(LMTYPE_COLSZ)) | ||
161 | #define LMTYPE_COLSZ_10 ((0xa) << FShft(LMTYPE_COLSZ)) | ||
162 | #define LMTYPE_COLSZ_11 ((0xb) << FShft(LMTYPE_COLSZ)) | ||
163 | #define LMTYPE_COLSZ_12 ((0xc) << FShft(LMTYPE_COLSZ)) | ||
164 | |||
165 | /* LMTIM - Local Memory (SDRAM) Timing Register */ | ||
166 | #define LMTIM_TRAS Fld(4,16) | ||
167 | #define Lmtim_Tras(x) ((x) << FShft(LMTIM_TRAS)) | ||
168 | #define LMTIM_TRP Fld(4,12) | ||
169 | #define Lmtim_Trp(x) ((x) << FShft(LMTIM_TRP)) | ||
170 | #define LMTIM_TRCD Fld(4,8) | ||
171 | #define Lmtim_Trcd(x) ((x) << FShft(LMTIM_TRCD)) | ||
172 | #define LMTIM_TRC Fld(4,4) | ||
173 | #define Lmtim_Trc(x) ((x) << FShft(LMTIM_TRC)) | ||
174 | #define LMTIM_TDPL Fld(4,0) | ||
175 | #define Lmtim_Tdpl(x) ((x) << FShft(LMTIM_TDPL)) | ||
176 | |||
177 | /* LMREFRESH - Local Memory (SDRAM) tREF Control Register */ | ||
178 | #define LMREFRESH_TREF Fld(2,0) | ||
179 | #define Lmrefresh_Tref(x) ((x) << FShft(LMREFRESH_TREF)) | ||
180 | |||
181 | /* GSCTRL - Graphics surface control register */ | ||
182 | #define GSCTRL_LUT_EN (1 << 31) | ||
183 | #define GSCTRL_GPIXFMT Fld(4,27) | ||
184 | #define GSCTRL_GPIXFMT_INDEXED ((0x0) << FShft(GSCTRL_GPIXFMT)) | ||
185 | #define GSCTRL_GPIXFMT_ARGB4444 ((0x4) << FShft(GSCTRL_GPIXFMT)) | ||
186 | #define GSCTRL_GPIXFMT_ARGB1555 ((0x5) << FShft(GSCTRL_GPIXFMT)) | ||
187 | #define GSCTRL_GPIXFMT_RGB888 ((0x6) << FShft(GSCTRL_GPIXFMT)) | ||
188 | #define GSCTRL_GPIXFMT_RGB565 ((0x7) << FShft(GSCTRL_GPIXFMT)) | ||
189 | #define GSCTRL_GPIXFMT_ARGB8888 ((0x8) << FShft(GSCTRL_GPIXFMT)) | ||
190 | #define GSCTRL_GAMMA_EN (1 << 26) | ||
191 | |||
192 | #define GSCTRL_GSWIDTH Fld(11,11) | ||
193 | #define Gsctrl_Width(Pixel) /* Display Width [1..2048 pix.] */ \ | ||
194 | (((Pixel) - 1) << FShft(GSCTRL_GSWIDTH)) | ||
195 | |||
196 | #define GSCTRL_GSHEIGHT Fld(11,0) | ||
197 | #define Gsctrl_Height(Pixel) /* Display Height [1..2048 pix.] */ \ | ||
198 | (((Pixel) - 1) << FShft(GSCTRL_GSHEIGHT)) | ||
199 | |||
200 | /* GBBASE fileds */ | ||
201 | #define GBBASE_GLALPHA Fld(8,24) | ||
202 | #define Gbbase_Glalpha(x) ((x) << FShft(GBBASE_GLALPHA)) | ||
203 | |||
204 | #define GBBASE_COLKEY Fld(24,0) | ||
205 | #define Gbbase_Colkey(x) ((x) << FShft(GBBASE_COLKEY)) | ||
206 | |||
207 | /* GDRCTRL fields */ | ||
208 | #define GDRCTRL_PIXDBL (1 << 31) | ||
209 | #define GDRCTRL_PIXHLV (1 << 30) | ||
210 | #define GDRCTRL_LNDBL (1 << 29) | ||
211 | #define GDRCTRL_LNHLV (1 << 28) | ||
212 | #define GDRCTRL_COLKEYM Fld(24,0) | ||
213 | #define Gdrctrl_Colkeym(x) ((x) << FShft(GDRCTRL_COLKEYM)) | ||
214 | |||
215 | /* GSCADR graphics stream control address register fields */ | ||
216 | #define GSCADR_STR_EN (1 << 31) | ||
217 | #define GSCADR_COLKEY_EN (1 << 30) | ||
218 | #define GSCADR_COLKEYSCR (1 << 29) | ||
219 | #define GSCADR_BLEND_M Fld(2,27) | ||
220 | #define GSCADR_BLEND_NONE ((0x0) << FShft(GSCADR_BLEND_M)) | ||
221 | #define GSCADR_BLEND_INV ((0x1) << FShft(GSCADR_BLEND_M)) | ||
222 | #define GSCADR_BLEND_GLOB ((0x2) << FShft(GSCADR_BLEND_M)) | ||
223 | #define GSCADR_BLEND_PIX ((0x3) << FShft(GSCADR_BLEND_M)) | ||
224 | #define GSCADR_BLEND_POS Fld(2,24) | ||
225 | #define GSCADR_BLEND_GFX ((0x0) << FShft(GSCADR_BLEND_POS)) | ||
226 | #define GSCADR_BLEND_VID ((0x1) << FShft(GSCADR_BLEND_POS)) | ||
227 | #define GSCADR_BLEND_CUR ((0x2) << FShft(GSCADR_BLEND_POS)) | ||
228 | #define GSCADR_GBASE_ADR Fld(23,0) | ||
229 | #define Gscadr_Gbase_Adr(x) ((x) << FShft(GSCADR_GBASE_ADR)) | ||
230 | |||
231 | /* GSADR graphics stride address register fields */ | ||
232 | #define GSADR_SRCSTRIDE Fld(10,22) | ||
233 | #define Gsadr_Srcstride(x) ((x) << FShft(GSADR_SRCSTRIDE)) | ||
234 | #define GSADR_XSTART Fld(11,11) | ||
235 | #define Gsadr_Xstart(x) ((x) << FShft(GSADR_XSTART)) | ||
236 | #define GSADR_YSTART Fld(11,0) | ||
237 | #define Gsadr_Ystart(y) ((y) << FShft(GSADR_YSTART)) | ||
238 | |||
239 | /* GPLUT graphics palette register fields */ | ||
240 | #define GPLUT_LUTADR Fld(8,24) | ||
241 | #define Gplut_Lutadr(x) ((x) << FShft(GPLUT_LUTADR)) | ||
242 | #define GPLUT_LUTDATA Fld(24,0) | ||
243 | #define Gplut_Lutdata(x) ((x) << FShft(GPLUT_LUTDATA)) | ||
244 | |||
245 | /* HCCTRL - Hardware Cursor Register fields */ | ||
246 | #define HCCTRL_CUR_EN (1 << 31) | ||
247 | #define HCCTRL_COLKEY_EN (1 << 29) | ||
248 | #define HCCTRL_COLKEYSRC (1 << 28) | ||
249 | #define HCCTRL_BLEND_M Fld(2,26) | ||
250 | #define HCCTRL_BLEND_NONE ((0x0) << FShft(HCCTRL_BLEND_M)) | ||
251 | #define HCCTRL_BLEND_INV ((0x1) << FShft(HCCTRL_BLEND_M)) | ||
252 | #define HCCTRL_BLEND_GLOB ((0x2) << FShft(HCCTRL_BLEND_M)) | ||
253 | #define HCCTRL_BLEND_PIX ((0x3) << FShft(HCCTRL_BLEND_M)) | ||
254 | #define HCCTRL_CPIXFMT Fld(3,23) | ||
255 | #define HCCTRL_CPIXFMT_RGB332 ((0x3) << FShft(HCCTRL_CPIXFMT)) | ||
256 | #define HCCTRL_CPIXFMT_ARGB4444 ((0x4) << FShft(HCCTRL_CPIXFMT)) | ||
257 | #define HCCTRL_CPIXFMT_ARGB1555 ((0x5) << FShft(HCCTRL_CPIXFMT)) | ||
258 | #define HCCTRL_CBASE_ADR Fld(23,0) | ||
259 | #define Hcctrl_Cbase_Adr(x) ((x) << FShft(HCCTRL_CBASE_ADR)) | ||
260 | |||
261 | /* HCSIZE Hardware Cursor Size Register fields */ | ||
262 | #define HCSIZE_BLEND_POS Fld(2,29) | ||
263 | #define HCSIZE_BLEND_GFX ((0x0) << FShft(HCSIZE_BLEND_POS)) | ||
264 | #define HCSIZE_BLEND_VID ((0x1) << FShft(HCSIZE_BLEND_POS)) | ||
265 | #define HCSIZE_BLEND_CUR ((0x2) << FShft(HCSIZE_BLEND_POS)) | ||
266 | #define HCSIZE_CWIDTH Fld(3,16) | ||
267 | #define Hcsize_Cwidth(x) ((x) << FShft(HCSIZE_CWIDTH)) | ||
268 | #define HCSIZE_CHEIGHT Fld(3,0) | ||
269 | #define Hcsize_Cheight(x) ((x) << FShft(HCSIZE_CHEIGHT)) | ||
270 | |||
271 | /* HCPOS Hardware Cursor Position Register fields */ | ||
272 | #define HCPOS_SWITCHSRC (1 << 30) | ||
273 | #define HCPOS_CURBLINK Fld(6,24) | ||
274 | #define Hcpos_Curblink(x) ((x) << FShft(HCPOS_CURBLINK)) | ||
275 | #define HCPOS_XSTART Fld(12,12) | ||
276 | #define Hcpos_Xstart(x) ((x) << FShft(HCPOS_XSTART)) | ||
277 | #define HCPOS_YSTART Fld(12,0) | ||
278 | #define Hcpos_Ystart(y) ((y) << FShft(HCPOS_YSTART)) | ||
279 | |||
280 | /* HCBADR Hardware Cursor Blend Address Register */ | ||
281 | #define HCBADR_GLALPHA Fld(8,24) | ||
282 | #define Hcbadr_Glalpha(x) ((x) << FShft(HCBADR_GLALPHA)) | ||
283 | #define HCBADR_COLKEY Fld(24,0) | ||
284 | #define Hcbadr_Colkey(x) ((x) << FShft(HCBADR_COLKEY)) | ||
285 | |||
286 | /* HCCKMSK - Hardware Cursor Color Key Mask Register */ | ||
287 | #define HCCKMSK_COLKEY_M Fld(24,0) | ||
288 | #define Hcckmsk_Colkey_M(x) ((x) << FShft(HCCKMSK_COLKEY_M)) | ||
289 | |||
290 | /* DSCTRL - Display sync control register */ | ||
291 | #define DSCTRL_SYNCGEN_EN (1 << 31) | ||
292 | #define DSCTRL_DPL_RST (1 << 29) | ||
293 | #define DSCTRL_PWRDN_M (1 << 28) | ||
294 | #define DSCTRL_UPDSYNCCNT (1 << 26) | ||
295 | #define DSCTRL_UPDINTCNT (1 << 25) | ||
296 | #define DSCTRL_UPDCNT (1 << 24) | ||
297 | #define DSCTRL_UPDWAIT Fld(4,16) | ||
298 | #define Dsctrl_Updwait(x) ((x) << FShft(DSCTRL_UPDWAIT)) | ||
299 | #define DSCTRL_CLKPOL (1 << 11) | ||
300 | #define DSCTRL_CSYNC_EN (1 << 10) | ||
301 | #define DSCTRL_VS_SLAVE (1 << 7) | ||
302 | #define DSCTRL_HS_SLAVE (1 << 6) | ||
303 | #define DSCTRL_BLNK_POL (1 << 5) | ||
304 | #define DSCTRL_BLNK_DIS (1 << 4) | ||
305 | #define DSCTRL_VS_POL (1 << 3) | ||
306 | #define DSCTRL_VS_DIS (1 << 2) | ||
307 | #define DSCTRL_HS_POL (1 << 1) | ||
308 | #define DSCTRL_HS_DIS (1 << 0) | ||
309 | |||
310 | /* DHT01 - Display horizontal timing register 01 */ | ||
311 | #define DHT01_HBPS Fld(12,16) | ||
312 | #define Dht01_Hbps(x) ((x) << FShft(DHT01_HBPS)) | ||
313 | #define DHT01_HT Fld(12,0) | ||
314 | #define Dht01_Ht(x) ((x) << FShft(DHT01_HT)) | ||
315 | |||
316 | /* DHT02 - Display horizontal timing register 02 */ | ||
317 | #define DHT02_HAS Fld(12,16) | ||
318 | #define Dht02_Has(x) ((x) << FShft(DHT02_HAS)) | ||
319 | #define DHT02_HLBS Fld(12,0) | ||
320 | #define Dht02_Hlbs(x) ((x) << FShft(DHT02_HLBS)) | ||
321 | |||
322 | /* DHT03 - Display horizontal timing register 03 */ | ||
323 | #define DHT03_HFPS Fld(12,16) | ||
324 | #define Dht03_Hfps(x) ((x) << FShft(DHT03_HFPS)) | ||
325 | #define DHT03_HRBS Fld(12,0) | ||
326 | #define Dht03_Hrbs(x) ((x) << FShft(DHT03_HRBS)) | ||
327 | |||
328 | /* DVT01 - Display vertical timing register 01 */ | ||
329 | #define DVT01_VBPS Fld(12,16) | ||
330 | #define Dvt01_Vbps(x) ((x) << FShft(DVT01_VBPS)) | ||
331 | #define DVT01_VT Fld(12,0) | ||
332 | #define Dvt01_Vt(x) ((x) << FShft(DVT01_VT)) | ||
333 | |||
334 | /* DVT02 - Display vertical timing register 02 */ | ||
335 | #define DVT02_VAS Fld(12,16) | ||
336 | #define Dvt02_Vas(x) ((x) << FShft(DVT02_VAS)) | ||
337 | #define DVT02_VTBS Fld(12,0) | ||
338 | #define Dvt02_Vtbs(x) ((x) << FShft(DVT02_VTBS)) | ||
339 | |||
340 | /* DVT03 - Display vertical timing register 03 */ | ||
341 | #define DVT03_VFPS Fld(12,16) | ||
342 | #define Dvt03_Vfps(x) ((x) << FShft(DVT03_VFPS)) | ||
343 | #define DVT03_VBBS Fld(12,0) | ||
344 | #define Dvt03_Vbbs(x) ((x) << FShft(DVT03_VBBS)) | ||
345 | |||
346 | /* DVECTRL - display vertical event control register */ | ||
347 | #define DVECTRL_VEVENT Fld(12,16) | ||
348 | #define Dvectrl_Vevent(x) ((x) << FShft(DVECTRL_VEVENT)) | ||
349 | #define DVECTRL_VFETCH Fld(12,0) | ||
350 | #define Dvectrl_Vfetch(x) ((x) << FShft(DVECTRL_VFETCH)) | ||
351 | |||
352 | /* DHDET - display horizontal DE timing register */ | ||
353 | #define DHDET_HDES Fld(12,16) | ||
354 | #define Dhdet_Hdes(x) ((x) << FShft(DHDET_HDES)) | ||
355 | #define DHDET_HDEF Fld(12,0) | ||
356 | #define Dhdet_Hdef(x) ((x) << FShft(DHDET_HDEF)) | ||
357 | |||
358 | /* DVDET - display vertical DE timing register */ | ||
359 | #define DVDET_VDES Fld(12,16) | ||
360 | #define Dvdet_Vdes(x) ((x) << FShft(DVDET_VDES)) | ||
361 | #define DVDET_VDEF Fld(12,0) | ||
362 | #define Dvdet_Vdef(x) ((x) << FShft(DVDET_VDEF)) | ||
363 | |||
364 | /* DODMSK - display output data mask register */ | ||
365 | #define DODMSK_MASK_LVL (1 << 31) | ||
366 | #define DODMSK_BLNK_LVL (1 << 30) | ||
367 | #define DODMSK_MASK_B Fld(8,16) | ||
368 | #define Dodmsk_Mask_B(x) ((x) << FShft(DODMSK_MASK_B)) | ||
369 | #define DODMSK_MASK_G Fld(8,8) | ||
370 | #define Dodmsk_Mask_G(x) ((x) << FShft(DODMSK_MASK_G)) | ||
371 | #define DODMSK_MASK_R Fld(8,0) | ||
372 | #define Dodmsk_Mask_R(x) ((x) << FShft(DODMSK_MASK_R)) | ||
373 | |||
374 | /* DBCOL - display border color control register */ | ||
375 | #define DBCOL_BORDCOL Fld(24,0) | ||
376 | #define Dbcol_Bordcol(x) ((x) << FShft(DBCOL_BORDCOL)) | ||
377 | |||
378 | /* DVLNUM - display vertical line number register */ | ||
379 | #define DVLNUM_VLINE Fld(12,0) | ||
380 | #define Dvlnum_Vline(x) ((x) << FShft(DVLNUM_VLINE)) | ||
381 | |||
382 | /* DMCTRL - Display Memory Control Register */ | ||
383 | #define DMCTRL_MEM_REF Fld(2,30) | ||
384 | #define DMCTRL_MEM_REF_ACT ((0x0) << FShft(DMCTRL_MEM_REF)) | ||
385 | #define DMCTRL_MEM_REF_HB ((0x1) << FShft(DMCTRL_MEM_REF)) | ||
386 | #define DMCTRL_MEM_REF_VB ((0x2) << FShft(DMCTRL_MEM_REF)) | ||
387 | #define DMCTRL_MEM_REF_BOTH ((0x3) << FShft(DMCTRL_MEM_REF)) | ||
388 | #define DMCTRL_UV_THRHLD Fld(6,24) | ||
389 | #define Dmctrl_Uv_Thrhld(x) ((x) << FShft(DMCTRL_UV_THRHLD)) | ||
390 | #define DMCTRL_V_THRHLD Fld(7,16) | ||
391 | #define Dmctrl_V_Thrhld(x) ((x) << FShft(DMCTRL_V_THRHLD)) | ||
392 | #define DMCTRL_D_THRHLD Fld(7,8) | ||
393 | #define Dmctrl_D_Thrhld(x) ((x) << FShft(DMCTRL_D_THRHLD)) | ||
394 | #define DMCTRL_BURSTLEN Fld(6,0) | ||
395 | #define Dmctrl_Burstlen(x) ((x) << FShft(DMCTRL_BURSTLEN)) | ||
396 | |||
397 | |||
398 | /* DLSTS - display load status register */ | ||
399 | #define DLSTS_RLD_ADONE (1 << 23) | ||
400 | /* #define DLSTS_RLD_ADOUT Fld(23,0) */ | ||
401 | |||
402 | /* DLLCTRL - display list load control register */ | ||
403 | #define DLLCTRL_RLD_ADRLN Fld(8,24) | ||
404 | #define Dllctrl_Rld_Adrln(x) ((x) << FShft(DLLCTRL_RLD_ADRLN)) | ||
405 | |||
406 | /* SPOCTRL - Scale Pitch/Order Control Register */ | ||
407 | #define SPOCTRL_H_SC_BP (1 << 31) | ||
408 | #define SPOCTRL_V_SC_BP (1 << 30) | ||
409 | #define SPOCTRL_HV_SC_OR (1 << 29) | ||
410 | #define SPOCTRL_VS_UR_C (1 << 27) | ||
411 | #define SPOCTRL_VORDER Fld(2,16) | ||
412 | #define SPOCTRL_VORDER_1TAP ((0x0) << FShft(SPOCTRL_VORDER)) | ||
413 | #define SPOCTRL_VORDER_2TAP ((0x1) << FShft(SPOCTRL_VORDER)) | ||
414 | #define SPOCTRL_VORDER_4TAP ((0x3) << FShft(SPOCTRL_VORDER)) | ||
415 | #define SPOCTRL_VPITCH Fld(16,0) | ||
416 | #define Spoctrl_Vpitch(x) ((x) << FShft(SPOCTRL_VPITCH)) | ||
417 | |||
418 | #endif /* __REG_BITS_2700G_ */ | ||
diff --git a/drivers/video/mbx/regs.h b/drivers/video/mbx/regs.h new file mode 100644 index 000000000000..ad20be07666b --- /dev/null +++ b/drivers/video/mbx/regs.h | |||
@@ -0,0 +1,195 @@ | |||
1 | #ifndef __REGS_2700G_ | ||
2 | #define __REGS_2700G_ | ||
3 | |||
4 | /* extern unsigned long virt_base_2700; */ | ||
5 | /* #define __REG_2700G(x) (*(volatile unsigned long*)((x)+virt_base_2700)) */ | ||
6 | #define __REG_2700G(x) ((x)+virt_base_2700) | ||
7 | |||
8 | /* System Configuration Registers (0x0000_0000 0x0000_0010) */ | ||
9 | #define SYSCFG __REG_2700G(0x00000000) | ||
10 | #define PFBASE __REG_2700G(0x00000004) | ||
11 | #define PFCEIL __REG_2700G(0x00000008) | ||
12 | #define POLLFLAG __REG_2700G(0x0000000c) | ||
13 | #define SYSRST __REG_2700G(0x00000010) | ||
14 | |||
15 | /* Interrupt Control Registers (0x0000_0014 0x0000_002F) */ | ||
16 | #define NINTPW __REG_2700G(0x00000014) | ||
17 | #define MINTENABLE __REG_2700G(0x00000018) | ||
18 | #define MINTSTAT __REG_2700G(0x0000001c) | ||
19 | #define SINTENABLE __REG_2700G(0x00000020) | ||
20 | #define SINTSTAT __REG_2700G(0x00000024) | ||
21 | #define SINTCLR __REG_2700G(0x00000028) | ||
22 | |||
23 | /* Clock Control Registers (0x0000_002C 0x0000_005F) */ | ||
24 | #define SYSCLKSRC __REG_2700G(0x0000002c) | ||
25 | #define PIXCLKSRC __REG_2700G(0x00000030) | ||
26 | #define CLKSLEEP __REG_2700G(0x00000034) | ||
27 | #define COREPLL __REG_2700G(0x00000038) | ||
28 | #define DISPPLL __REG_2700G(0x0000003c) | ||
29 | #define PLLSTAT __REG_2700G(0x00000040) | ||
30 | #define VOVRCLK __REG_2700G(0x00000044) | ||
31 | #define PIXCLK __REG_2700G(0x00000048) | ||
32 | #define MEMCLK __REG_2700G(0x0000004c) | ||
33 | #define M24CLK __REG_2700G(0x00000054) | ||
34 | #define MBXCLK __REG_2700G(0x00000054) | ||
35 | #define SDCLK __REG_2700G(0x00000058) | ||
36 | #define PIXCLKDIV __REG_2700G(0x0000005c) | ||
37 | |||
38 | /* LCD Port Control Register (0x0000_0060 0x0000_006F) */ | ||
39 | #define LCD_CONFIG __REG_2700G(0x00000060) | ||
40 | |||
41 | /* On-Die Frame Buffer Registers (0x0000_0064 0x0000_006B) */ | ||
42 | #define ODFBPWR __REG_2700G(0x00000064) | ||
43 | #define ODFBSTAT __REG_2700G(0x00000068) | ||
44 | |||
45 | /* GPIO Registers (0x0000_006C 0x0000_007F) */ | ||
46 | #define GPIOCGF __REG_2700G(0x0000006c) | ||
47 | #define GPIOHI __REG_2700G(0x00000070) | ||
48 | #define GPIOLO __REG_2700G(0x00000074) | ||
49 | #define GPIOSTAT __REG_2700G(0x00000078) | ||
50 | |||
51 | /* Pulse Width Modulator (PWM) Registers (0x0000_0200 0x0000_02FF) */ | ||
52 | #define PWMRST __REG_2700G(0x00000200) | ||
53 | #define PWMCFG __REG_2700G(0x00000204) | ||
54 | #define PWM0DIV __REG_2700G(0x00000210) | ||
55 | #define PWM0DUTY __REG_2700G(0x00000214) | ||
56 | #define PWM0PER __REG_2700G(0x00000218) | ||
57 | #define PWM1DIV __REG_2700G(0x00000220) | ||
58 | #define PWM1DUTY __REG_2700G(0x00000224) | ||
59 | #define PWM1PER __REG_2700G(0x00000228) | ||
60 | |||
61 | /* Identification (ID) Registers (0x0000_0300 0x0000_0FFF) */ | ||
62 | #define ID __REG_2700G(0x00000FF0) | ||
63 | |||
64 | /* Local Memory (SDRAM) Interface Registers (0x0000_1000 0x0000_1FFF) */ | ||
65 | #define LMRST __REG_2700G(0x00001000) | ||
66 | #define LMCFG __REG_2700G(0x00001004) | ||
67 | #define LMPWR __REG_2700G(0x00001008) | ||
68 | #define LMPWRSTAT __REG_2700G(0x0000100c) | ||
69 | #define LMCEMR __REG_2700G(0x00001010) | ||
70 | #define LMTYPE __REG_2700G(0x00001014) | ||
71 | #define LMTIM __REG_2700G(0x00001018) | ||
72 | #define LMREFRESH __REG_2700G(0x0000101c) | ||
73 | #define LMPROTMIN __REG_2700G(0x00001020) | ||
74 | #define LMPROTMAX __REG_2700G(0x00001024) | ||
75 | #define LMPROTCFG __REG_2700G(0x00001028) | ||
76 | #define LMPROTERR __REG_2700G(0x0000102c) | ||
77 | |||
78 | /* Plane Controller Registers (0x0000_2000 0x0000_2FFF) */ | ||
79 | #define GSCTRL __REG_2700G(0x00002000) | ||
80 | #define VSCTRL __REG_2700G(0x00002004) | ||
81 | #define GBBASE __REG_2700G(0x00002020) | ||
82 | #define VBBASE __REG_2700G(0x00002024) | ||
83 | #define GDRCTRL __REG_2700G(0x00002040) | ||
84 | #define VCMSK __REG_2700G(0x00002044) | ||
85 | #define GSCADR __REG_2700G(0x00002060) | ||
86 | #define VSCADR __REG_2700G(0x00002064) | ||
87 | #define VUBASE __REG_2700G(0x00002084) | ||
88 | #define VVBASE __REG_2700G(0x000020a4) | ||
89 | #define GSADR __REG_2700G(0x000020c0) | ||
90 | #define VSADR __REG_2700G(0x000020c4) | ||
91 | #define HCCTRL __REG_2700G(0x00002100) | ||
92 | #define HCSIZE __REG_2700G(0x00002110) | ||
93 | #define HCPOS __REG_2700G(0x00002120) | ||
94 | #define HCBADR __REG_2700G(0x00002130) | ||
95 | #define HCCKMSK __REG_2700G(0x00002140) | ||
96 | #define GPLUT __REG_2700G(0x00002150) | ||
97 | #define DSCTRL __REG_2700G(0x00002154) | ||
98 | #define DHT01 __REG_2700G(0x00002158) | ||
99 | #define DHT02 __REG_2700G(0x0000215c) | ||
100 | #define DHT03 __REG_2700G(0x00002160) | ||
101 | #define DVT01 __REG_2700G(0x00002164) | ||
102 | #define DVT02 __REG_2700G(0x00002168) | ||
103 | #define DVT03 __REG_2700G(0x0000216c) | ||
104 | #define DBCOL __REG_2700G(0x00002170) | ||
105 | #define BGCOLOR __REG_2700G(0x00002174) | ||
106 | #define DINTRS __REG_2700G(0x00002178) | ||
107 | #define DINTRE __REG_2700G(0x0000217c) | ||
108 | #define DINTRCNT __REG_2700G(0x00002180) | ||
109 | #define DSIG __REG_2700G(0x00002184) | ||
110 | #define DMCTRL __REG_2700G(0x00002188) | ||
111 | #define CLIPCTRL __REG_2700G(0x0000218c) | ||
112 | #define SPOCTRL __REG_2700G(0x00002190) | ||
113 | #define SVCTRL __REG_2700G(0x00002194) | ||
114 | |||
115 | /* 0x0000_2198 */ | ||
116 | /* 0x0000_21A8 VSCOEFF[0:4] Video Scalar Vertical Coefficient [0:4] 4.14.5 */ | ||
117 | #define VSCOEFF0 __REG_2700G(0x00002198) | ||
118 | #define VSCOEFF1 __REG_2700G(0x0000219c) | ||
119 | #define VSCOEFF2 __REG_2700G(0x000021a0) | ||
120 | #define VSCOEFF3 __REG_2700G(0x000021a4) | ||
121 | #define VSCOEFF4 __REG_2700G(0x000021a8) | ||
122 | |||
123 | #define SHCTRL __REG_2700G(0x000021b0) | ||
124 | |||
125 | /* 0x0000_21B4 */ | ||
126 | /* 0x0000_21D4 HSCOEFF[0:8] Video Scalar Horizontal Coefficient [0:8] 4.14.7 */ | ||
127 | #define HSCOEFF0 __REG_2700G(0x000021b4) | ||
128 | #define HSCOEFF1 __REG_2700G(0x000021b8) | ||
129 | #define HSCOEFF2 __REG_2700G(0x000021bc) | ||
130 | #define HSCOEFF3 __REG_2700G(0x000021b0) | ||
131 | #define HSCOEFF4 __REG_2700G(0x000021c4) | ||
132 | #define HSCOEFF5 __REG_2700G(0x000021c8) | ||
133 | #define HSCOEFF6 __REG_2700G(0x000021cc) | ||
134 | #define HSCOEFF7 __REG_2700G(0x000021d0) | ||
135 | #define HSCOEFF8 __REG_2700G(0x000021d4) | ||
136 | |||
137 | #define SSSIZE __REG_2700G(0x000021D8) | ||
138 | |||
139 | /* 0x0000_2200 */ | ||
140 | /* 0x0000_2240 VIDGAM[0:16] Video Gamma LUT Index [0:16] 4.15.2 */ | ||
141 | #define VIDGAM0 __REG_2700G(0x00002200) | ||
142 | #define VIDGAM1 __REG_2700G(0x00002204) | ||
143 | #define VIDGAM2 __REG_2700G(0x00002208) | ||
144 | #define VIDGAM3 __REG_2700G(0x0000220c) | ||
145 | #define VIDGAM4 __REG_2700G(0x00002210) | ||
146 | #define VIDGAM5 __REG_2700G(0x00002214) | ||
147 | #define VIDGAM6 __REG_2700G(0x00002218) | ||
148 | #define VIDGAM7 __REG_2700G(0x0000221c) | ||
149 | #define VIDGAM8 __REG_2700G(0x00002220) | ||
150 | #define VIDGAM9 __REG_2700G(0x00002224) | ||
151 | #define VIDGAM10 __REG_2700G(0x00002228) | ||
152 | #define VIDGAM11 __REG_2700G(0x0000222c) | ||
153 | #define VIDGAM12 __REG_2700G(0x00002230) | ||
154 | #define VIDGAM13 __REG_2700G(0x00002234) | ||
155 | #define VIDGAM14 __REG_2700G(0x00002238) | ||
156 | #define VIDGAM15 __REG_2700G(0x0000223c) | ||
157 | #define VIDGAM16 __REG_2700G(0x00002240) | ||
158 | |||
159 | /* 0x0000_2250 */ | ||
160 | /* 0x0000_2290 GFXGAM[0:16] Graphics Gamma LUT Index [0:16] 4.15.3 */ | ||
161 | #define GFXGAM0 __REG_2700G(0x00002250) | ||
162 | #define GFXGAM1 __REG_2700G(0x00002254) | ||
163 | #define GFXGAM2 __REG_2700G(0x00002258) | ||
164 | #define GFXGAM3 __REG_2700G(0x0000225c) | ||
165 | #define GFXGAM4 __REG_2700G(0x00002260) | ||
166 | #define GFXGAM5 __REG_2700G(0x00002264) | ||
167 | #define GFXGAM6 __REG_2700G(0x00002268) | ||
168 | #define GFXGAM7 __REG_2700G(0x0000226c) | ||
169 | #define GFXGAM8 __REG_2700G(0x00002270) | ||
170 | #define GFXGAM9 __REG_2700G(0x00002274) | ||
171 | #define GFXGAM10 __REG_2700G(0x00002278) | ||
172 | #define GFXGAM11 __REG_2700G(0x0000227c) | ||
173 | #define GFXGAM12 __REG_2700G(0x00002280) | ||
174 | #define GFXGAM13 __REG_2700G(0x00002284) | ||
175 | #define GFXGAM14 __REG_2700G(0x00002288) | ||
176 | #define GFXGAM15 __REG_2700G(0x0000228c) | ||
177 | #define GFXGAM16 __REG_2700G(0x00002290) | ||
178 | |||
179 | #define DLSTS __REG_2700G(0x00002300) | ||
180 | #define DLLCTRL __REG_2700G(0x00002304) | ||
181 | #define DVLNUM __REG_2700G(0x00002308) | ||
182 | #define DUCTRL __REG_2700G(0x0000230c) | ||
183 | #define DVECTRL __REG_2700G(0x00002310) | ||
184 | #define DHDET __REG_2700G(0x00002314) | ||
185 | #define DVDET __REG_2700G(0x00002318) | ||
186 | #define DODMSK __REG_2700G(0x0000231c) | ||
187 | #define CSC01 __REG_2700G(0x00002330) | ||
188 | #define CSC02 __REG_2700G(0x00002334) | ||
189 | #define CSC03 __REG_2700G(0x00002338) | ||
190 | #define CSC04 __REG_2700G(0x0000233c) | ||
191 | #define CSC05 __REG_2700G(0x00002340) | ||
192 | |||
193 | #define FB_MEMORY_START __REG_2700G(0x00060000) | ||
194 | |||
195 | #endif /* __REGS_2700G_ */ | ||
diff --git a/fs/char_dev.c b/fs/char_dev.c index a4cbc6706ef0..3483d3cf8087 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
@@ -182,6 +182,28 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, | |||
182 | return 0; | 182 | return 0; |
183 | } | 183 | } |
184 | 184 | ||
185 | /** | ||
186 | * register_chrdev() - Register a major number for character devices. | ||
187 | * @major: major device number or 0 for dynamic allocation | ||
188 | * @name: name of this range of devices | ||
189 | * @fops: file operations associated with this devices | ||
190 | * | ||
191 | * If @major == 0 this functions will dynamically allocate a major and return | ||
192 | * its number. | ||
193 | * | ||
194 | * If @major > 0 this function will attempt to reserve a device with the given | ||
195 | * major number and will return zero on success. | ||
196 | * | ||
197 | * Returns a -ve errno on failure. | ||
198 | * | ||
199 | * The name of this device has nothing to do with the name of the device in | ||
200 | * /dev. It only helps to keep track of the different owners of devices. If | ||
201 | * your module name has only one type of devices it's ok to use e.g. the name | ||
202 | * of the module here. | ||
203 | * | ||
204 | * This function registers a range of 256 minor numbers. The first minor number | ||
205 | * is 0. | ||
206 | */ | ||
185 | int register_chrdev(unsigned int major, const char *name, | 207 | int register_chrdev(unsigned int major, const char *name, |
186 | const struct file_operations *fops) | 208 | const struct file_operations *fops) |
187 | { | 209 | { |
diff --git a/fs/namei.c b/fs/namei.c index c9750d755aff..e01070d7bf58 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1712,8 +1712,14 @@ do_link: | |||
1712 | if (error) | 1712 | if (error) |
1713 | goto exit_dput; | 1713 | goto exit_dput; |
1714 | error = __do_follow_link(&path, nd); | 1714 | error = __do_follow_link(&path, nd); |
1715 | if (error) | 1715 | if (error) { |
1716 | /* Does someone understand code flow here? Or it is only | ||
1717 | * me so stupid? Anathema to whoever designed this non-sense | ||
1718 | * with "intent.open". | ||
1719 | */ | ||
1720 | release_open_intent(nd); | ||
1716 | return error; | 1721 | return error; |
1722 | } | ||
1717 | nd->flags &= ~LOOKUP_PARENT; | 1723 | nd->flags &= ~LOOKUP_PARENT; |
1718 | if (nd->last_type == LAST_BIND) | 1724 | if (nd->last_type == LAST_BIND) |
1719 | goto ok; | 1725 | goto ok; |
diff --git a/fs/proc/array.c b/fs/proc/array.c index 7495d3e20775..0b615d62a159 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -74,6 +74,7 @@ | |||
74 | #include <linux/times.h> | 74 | #include <linux/times.h> |
75 | #include <linux/cpuset.h> | 75 | #include <linux/cpuset.h> |
76 | #include <linux/rcupdate.h> | 76 | #include <linux/rcupdate.h> |
77 | #include <linux/delayacct.h> | ||
77 | 78 | ||
78 | #include <asm/uaccess.h> | 79 | #include <asm/uaccess.h> |
79 | #include <asm/pgtable.h> | 80 | #include <asm/pgtable.h> |
@@ -411,7 +412,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
411 | 412 | ||
412 | res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ | 413 | res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ |
413 | %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \ | 414 | %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \ |
414 | %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu\n", | 415 | %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu %llu\n", |
415 | task->pid, | 416 | task->pid, |
416 | tcomm, | 417 | tcomm, |
417 | state, | 418 | state, |
@@ -455,7 +456,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
455 | task->exit_signal, | 456 | task->exit_signal, |
456 | task_cpu(task), | 457 | task_cpu(task), |
457 | task->rt_priority, | 458 | task->rt_priority, |
458 | task->policy); | 459 | task->policy, |
460 | (unsigned long long)delayacct_blkio_ticks(task)); | ||
459 | if(mm) | 461 | if(mm) |
460 | mmput(mm); | 462 | mmput(mm); |
461 | return res; | 463 | return res; |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 243a94af0427..474eae345068 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1339,6 +1339,7 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1339 | inode->i_uid = 0; | 1339 | inode->i_uid = 0; |
1340 | inode->i_gid = 0; | 1340 | inode->i_gid = 0; |
1341 | } | 1341 | } |
1342 | inode->i_mode &= ~(S_ISUID | S_ISGID); | ||
1342 | security_task_to_inode(task, inode); | 1343 | security_task_to_inode(task, inode); |
1343 | put_task_struct(task); | 1344 | put_task_struct(task); |
1344 | return 1; | 1345 | return 1; |
@@ -1389,6 +1390,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1389 | inode->i_uid = 0; | 1390 | inode->i_uid = 0; |
1390 | inode->i_gid = 0; | 1391 | inode->i_gid = 0; |
1391 | } | 1392 | } |
1393 | inode->i_mode &= ~(S_ISUID | S_ISGID); | ||
1392 | security_task_to_inode(task, inode); | 1394 | security_task_to_inode(task, inode); |
1393 | put_task_struct(task); | 1395 | put_task_struct(task); |
1394 | return 1; | 1396 | return 1; |
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index 5d8a8cfebc70..c533ec1bcaec 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c | |||
@@ -492,9 +492,17 @@ static void add_file(struct super_block *sb, char *name, | |||
492 | 492 | ||
493 | int reiserfs_proc_info_init(struct super_block *sb) | 493 | int reiserfs_proc_info_init(struct super_block *sb) |
494 | { | 494 | { |
495 | char b[BDEVNAME_SIZE]; | ||
496 | char *s; | ||
497 | |||
498 | /* Some block devices use /'s */ | ||
499 | strlcpy(b, reiserfs_bdevname(sb), BDEVNAME_SIZE); | ||
500 | s = strchr(b, '/'); | ||
501 | if (s) | ||
502 | *s = '!'; | ||
503 | |||
495 | spin_lock_init(&__PINFO(sb).lock); | 504 | spin_lock_init(&__PINFO(sb).lock); |
496 | REISERFS_SB(sb)->procdir = | 505 | REISERFS_SB(sb)->procdir = proc_mkdir(b, proc_info_root); |
497 | proc_mkdir(reiserfs_bdevname(sb), proc_info_root); | ||
498 | if (REISERFS_SB(sb)->procdir) { | 506 | if (REISERFS_SB(sb)->procdir) { |
499 | REISERFS_SB(sb)->procdir->owner = THIS_MODULE; | 507 | REISERFS_SB(sb)->procdir->owner = THIS_MODULE; |
500 | REISERFS_SB(sb)->procdir->data = sb; | 508 | REISERFS_SB(sb)->procdir->data = sb; |
@@ -508,13 +516,22 @@ int reiserfs_proc_info_init(struct super_block *sb) | |||
508 | return 0; | 516 | return 0; |
509 | } | 517 | } |
510 | reiserfs_warning(sb, "reiserfs: cannot create /proc/%s/%s", | 518 | reiserfs_warning(sb, "reiserfs: cannot create /proc/%s/%s", |
511 | proc_info_root_name, reiserfs_bdevname(sb)); | 519 | proc_info_root_name, b); |
512 | return 1; | 520 | return 1; |
513 | } | 521 | } |
514 | 522 | ||
515 | int reiserfs_proc_info_done(struct super_block *sb) | 523 | int reiserfs_proc_info_done(struct super_block *sb) |
516 | { | 524 | { |
517 | struct proc_dir_entry *de = REISERFS_SB(sb)->procdir; | 525 | struct proc_dir_entry *de = REISERFS_SB(sb)->procdir; |
526 | char b[BDEVNAME_SIZE]; | ||
527 | char *s; | ||
528 | |||
529 | /* Some block devices use /'s */ | ||
530 | strlcpy(b, reiserfs_bdevname(sb), BDEVNAME_SIZE); | ||
531 | s = strchr(b, '/'); | ||
532 | if (s) | ||
533 | *s = '!'; | ||
534 | |||
518 | if (de) { | 535 | if (de) { |
519 | remove_proc_entry("journal", de); | 536 | remove_proc_entry("journal", de); |
520 | remove_proc_entry("oidmap", de); | 537 | remove_proc_entry("oidmap", de); |
@@ -528,7 +545,7 @@ int reiserfs_proc_info_done(struct super_block *sb) | |||
528 | __PINFO(sb).exiting = 1; | 545 | __PINFO(sb).exiting = 1; |
529 | spin_unlock(&__PINFO(sb).lock); | 546 | spin_unlock(&__PINFO(sb).lock); |
530 | if (proc_info_root) { | 547 | if (proc_info_root) { |
531 | remove_proc_entry(reiserfs_bdevname(sb), proc_info_root); | 548 | remove_proc_entry(b, proc_info_root); |
532 | REISERFS_SB(sb)->procdir = NULL; | 549 | REISERFS_SB(sb)->procdir = NULL; |
533 | } | 550 | } |
534 | return 0; | 551 | return 0; |
diff --git a/include/asm-alpha/barrier.h b/include/asm-alpha/barrier.h index 681ff581afa5..384dc08d6f53 100644 --- a/include/asm-alpha/barrier.h +++ b/include/asm-alpha/barrier.h | |||
@@ -30,7 +30,4 @@ __asm__ __volatile__("mb": : :"memory") | |||
30 | #define set_mb(var, value) \ | 30 | #define set_mb(var, value) \ |
31 | do { var = value; mb(); } while (0) | 31 | do { var = value; mb(); } while (0) |
32 | 32 | ||
33 | #define set_wmb(var, value) \ | ||
34 | do { var = value; wmb(); } while (0) | ||
35 | |||
36 | #endif /* __BARRIER_H */ | 33 | #endif /* __BARRIER_H */ |
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h index 6001febfe63b..0947cbf9b69a 100644 --- a/include/asm-arm/system.h +++ b/include/asm-arm/system.h | |||
@@ -176,7 +176,6 @@ extern unsigned int user_debug; | |||
176 | #define wmb() mb() | 176 | #define wmb() mb() |
177 | #define read_barrier_depends() do { } while(0) | 177 | #define read_barrier_depends() do { } while(0) |
178 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 178 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
179 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
180 | #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t"); | 179 | #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t"); |
181 | 180 | ||
182 | /* | 181 | /* |
diff --git a/include/asm-arm26/system.h b/include/asm-arm26/system.h index d1f69d706198..00ae32aa1dba 100644 --- a/include/asm-arm26/system.h +++ b/include/asm-arm26/system.h | |||
@@ -90,7 +90,6 @@ extern unsigned int user_debug; | |||
90 | 90 | ||
91 | #define read_barrier_depends() do { } while(0) | 91 | #define read_barrier_depends() do { } while(0) |
92 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 92 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
93 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
94 | 93 | ||
95 | /* | 94 | /* |
96 | * We assume knowledge of how | 95 | * We assume knowledge of how |
diff --git a/include/asm-cris/system.h b/include/asm-cris/system.h index b1c593b6dbff..b869f6161aaa 100644 --- a/include/asm-cris/system.h +++ b/include/asm-cris/system.h | |||
@@ -17,7 +17,6 @@ extern struct task_struct *resume(struct task_struct *prev, struct task_struct * | |||
17 | #define wmb() mb() | 17 | #define wmb() mb() |
18 | #define read_barrier_depends() do { } while(0) | 18 | #define read_barrier_depends() do { } while(0) |
19 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 19 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
20 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
21 | 20 | ||
22 | #ifdef CONFIG_SMP | 21 | #ifdef CONFIG_SMP |
23 | #define smp_mb() mb() | 22 | #define smp_mb() mb() |
diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h index 351863dfd06e..1166899317d7 100644 --- a/include/asm-frv/system.h +++ b/include/asm-frv/system.h | |||
@@ -179,7 +179,6 @@ do { \ | |||
179 | #define rmb() asm volatile ("membar" : : :"memory") | 179 | #define rmb() asm volatile ("membar" : : :"memory") |
180 | #define wmb() asm volatile ("membar" : : :"memory") | 180 | #define wmb() asm volatile ("membar" : : :"memory") |
181 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 181 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
182 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
183 | 182 | ||
184 | #define smp_mb() mb() | 183 | #define smp_mb() mb() |
185 | #define smp_rmb() rmb() | 184 | #define smp_rmb() rmb() |
diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm index d8d0bcecd23f..6b16dda18115 100644 --- a/include/asm-generic/Kbuild.asm +++ b/include/asm-generic/Kbuild.asm | |||
@@ -1,11 +1,8 @@ | |||
1 | unifdef-y += a.out.h auxvec.h byteorder.h errno.h fcntl.h ioctl.h \ | 1 | unifdef-y += a.out.h auxvec.h byteorder.h errno.h fcntl.h ioctl.h \ |
2 | ioctls.h ipcbuf.h irq.h mman.h msgbuf.h param.h poll.h \ | 2 | ioctls.h ipcbuf.h mman.h msgbuf.h param.h poll.h \ |
3 | posix_types.h ptrace.h resource.h sembuf.h shmbuf.h shmparam.h \ | 3 | posix_types.h ptrace.h resource.h sembuf.h shmbuf.h shmparam.h \ |
4 | sigcontext.h siginfo.h signal.h socket.h sockios.h stat.h \ | 4 | sigcontext.h siginfo.h signal.h socket.h sockios.h stat.h \ |
5 | statfs.h termbits.h termios.h timex.h types.h unistd.h user.h | 5 | statfs.h termbits.h termios.h timex.h types.h unistd.h user.h |
6 | 6 | ||
7 | # These really shouldn't be exported | ||
8 | unifdef-y += atomic.h io.h | ||
9 | |||
10 | # These probably shouldn't be exported | 7 | # These probably shouldn't be exported |
11 | unifdef-y += elf.h page.h | 8 | unifdef-y += elf.h page.h |
diff --git a/include/asm-h8300/system.h b/include/asm-h8300/system.h index 134e0929fce5..5084a9d42922 100644 --- a/include/asm-h8300/system.h +++ b/include/asm-h8300/system.h | |||
@@ -84,7 +84,6 @@ asmlinkage void resume(void); | |||
84 | #define wmb() asm volatile ("" : : :"memory") | 84 | #define wmb() asm volatile ("" : : :"memory") |
85 | #define set_rmb(var, value) do { xchg(&var, value); } while (0) | 85 | #define set_rmb(var, value) do { xchg(&var, value); } while (0) |
86 | #define set_mb(var, value) set_rmb(var, value) | 86 | #define set_mb(var, value) set_rmb(var, value) |
87 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
88 | 87 | ||
89 | #ifdef CONFIG_SMP | 88 | #ifdef CONFIG_SMP |
90 | #define smp_mb() mb() | 89 | #define smp_mb() mb() |
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index 2db168ef949f..49928eb33f8b 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h | |||
@@ -453,8 +453,6 @@ static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long l | |||
453 | #define set_mb(var, value) do { var = value; barrier(); } while (0) | 453 | #define set_mb(var, value) do { var = value; barrier(); } while (0) |
454 | #endif | 454 | #endif |
455 | 455 | ||
456 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
457 | |||
458 | #include <linux/irqflags.h> | 456 | #include <linux/irqflags.h> |
459 | 457 | ||
460 | /* | 458 | /* |
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h index 65db43ce4de6..fc9677bc87ee 100644 --- a/include/asm-ia64/system.h +++ b/include/asm-ia64/system.h | |||
@@ -98,12 +98,11 @@ extern struct ia64_boot_param { | |||
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | /* | 100 | /* |
101 | * XXX check on these---I suspect what Linus really wants here is | 101 | * XXX check on this ---I suspect what Linus really wants here is |
102 | * acquire vs release semantics but we can't discuss this stuff with | 102 | * acquire vs release semantics but we can't discuss this stuff with |
103 | * Linus just yet. Grrr... | 103 | * Linus just yet. Grrr... |
104 | */ | 104 | */ |
105 | #define set_mb(var, value) do { (var) = (value); mb(); } while (0) | 105 | #define set_mb(var, value) do { (var) = (value); mb(); } while (0) |
106 | #define set_wmb(var, value) do { (var) = (value); mb(); } while (0) | ||
107 | 106 | ||
108 | #define safe_halt() ia64_pal_halt_light() /* PAL_HALT_LIGHT */ | 107 | #define safe_halt() ia64_pal_halt_light() /* PAL_HALT_LIGHT */ |
109 | 108 | ||
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h index 311cebf44eff..9e618afec6ed 100644 --- a/include/asm-m32r/system.h +++ b/include/asm-m32r/system.h | |||
@@ -336,7 +336,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | |||
336 | #endif | 336 | #endif |
337 | 337 | ||
338 | #define set_mb(var, value) do { xchg(&var, value); } while (0) | 338 | #define set_mb(var, value) do { xchg(&var, value); } while (0) |
339 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
340 | 339 | ||
341 | #define arch_align_stack(x) (x) | 340 | #define arch_align_stack(x) (x) |
342 | 341 | ||
diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h index d6dd8052cd6f..131a0cb0f491 100644 --- a/include/asm-m68k/system.h +++ b/include/asm-m68k/system.h | |||
@@ -80,7 +80,6 @@ static inline int irqs_disabled(void) | |||
80 | #define wmb() barrier() | 80 | #define wmb() barrier() |
81 | #define read_barrier_depends() do { } while(0) | 81 | #define read_barrier_depends() do { } while(0) |
82 | #define set_mb(var, value) do { xchg(&var, value); } while (0) | 82 | #define set_mb(var, value) do { xchg(&var, value); } while (0) |
83 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
84 | 83 | ||
85 | #define smp_mb() barrier() | 84 | #define smp_mb() barrier() |
86 | #define smp_rmb() barrier() | 85 | #define smp_rmb() barrier() |
diff --git a/include/asm-m68knommu/system.h b/include/asm-m68knommu/system.h index 2bbe2db00a22..2a814498672d 100644 --- a/include/asm-m68knommu/system.h +++ b/include/asm-m68knommu/system.h | |||
@@ -106,7 +106,6 @@ asmlinkage void resume(void); | |||
106 | #define wmb() asm volatile ("" : : :"memory") | 106 | #define wmb() asm volatile ("" : : :"memory") |
107 | #define set_rmb(var, value) do { xchg(&var, value); } while (0) | 107 | #define set_rmb(var, value) do { xchg(&var, value); } while (0) |
108 | #define set_mb(var, value) set_rmb(var, value) | 108 | #define set_mb(var, value) set_rmb(var, value) |
109 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
110 | 109 | ||
111 | #ifdef CONFIG_SMP | 110 | #ifdef CONFIG_SMP |
112 | #define smp_mb() mb() | 111 | #define smp_mb() mb() |
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index 13c98dde82dc..dcb4701d5728 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h | |||
@@ -143,9 +143,6 @@ | |||
143 | #define set_mb(var, value) \ | 143 | #define set_mb(var, value) \ |
144 | do { var = value; mb(); } while (0) | 144 | do { var = value; mb(); } while (0) |
145 | 145 | ||
146 | #define set_wmb(var, value) \ | ||
147 | do { var = value; wmb(); } while (0) | ||
148 | |||
149 | /* | 146 | /* |
150 | * switch_to(n) should switch tasks to task nr n, first | 147 | * switch_to(n) should switch tasks to task nr n, first |
151 | * checking that n isn't the current task, in which case it does nothing. | 148 | * checking that n isn't the current task, in which case it does nothing. |
diff --git a/include/asm-parisc/system.h b/include/asm-parisc/system.h index 5fe2d2329ab5..74f037a39e6f 100644 --- a/include/asm-parisc/system.h +++ b/include/asm-parisc/system.h | |||
@@ -143,8 +143,6 @@ static inline void set_eiem(unsigned long val) | |||
143 | #define read_barrier_depends() do { } while(0) | 143 | #define read_barrier_depends() do { } while(0) |
144 | 144 | ||
145 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 145 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
146 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
147 | |||
148 | 146 | ||
149 | #ifndef CONFIG_PA20 | 147 | #ifndef CONFIG_PA20 |
150 | /* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data, | 148 | /* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data, |
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index c6569516ba35..7307aa775671 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h | |||
@@ -39,7 +39,6 @@ | |||
39 | #define read_barrier_depends() do { } while(0) | 39 | #define read_barrier_depends() do { } while(0) |
40 | 40 | ||
41 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 41 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
42 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
43 | 42 | ||
44 | #ifdef __KERNEL__ | 43 | #ifdef __KERNEL__ |
45 | #ifdef CONFIG_SMP | 44 | #ifdef CONFIG_SMP |
diff --git a/include/asm-ppc/system.h b/include/asm-ppc/system.h index fb49c0c49ea1..738943584c01 100644 --- a/include/asm-ppc/system.h +++ b/include/asm-ppc/system.h | |||
@@ -33,7 +33,6 @@ | |||
33 | #define read_barrier_depends() do { } while(0) | 33 | #define read_barrier_depends() do { } while(0) |
34 | 34 | ||
35 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 35 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
36 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
37 | 36 | ||
38 | #ifdef CONFIG_SMP | 37 | #ifdef CONFIG_SMP |
39 | #define smp_mb() mb() | 38 | #define smp_mb() mb() |
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index 9ab186ffde23..36a3a85d611a 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h | |||
@@ -299,7 +299,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | |||
299 | 299 | ||
300 | 300 | ||
301 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 301 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
302 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
303 | 302 | ||
304 | #ifdef __s390x__ | 303 | #ifdef __s390x__ |
305 | 304 | ||
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h index ce2e60664a86..ad35ad4958f4 100644 --- a/include/asm-sh/system.h +++ b/include/asm-sh/system.h | |||
@@ -101,7 +101,6 @@ extern void __xchg_called_with_bad_pointer(void); | |||
101 | #endif | 101 | #endif |
102 | 102 | ||
103 | #define set_mb(var, value) do { xchg(&var, value); } while (0) | 103 | #define set_mb(var, value) do { xchg(&var, value); } while (0) |
104 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
105 | 104 | ||
106 | /* Interrupt Control */ | 105 | /* Interrupt Control */ |
107 | static __inline__ void local_irq_enable(void) | 106 | static __inline__ void local_irq_enable(void) |
diff --git a/include/asm-sh64/system.h b/include/asm-sh64/system.h index 7606f6e1f01e..87ef6f1ad5a4 100644 --- a/include/asm-sh64/system.h +++ b/include/asm-sh64/system.h | |||
@@ -66,7 +66,6 @@ extern void __xchg_called_with_bad_pointer(void); | |||
66 | 66 | ||
67 | #define set_rmb(var, value) do { xchg(&var, value); } while (0) | 67 | #define set_rmb(var, value) do { xchg(&var, value); } while (0) |
68 | #define set_mb(var, value) set_rmb(var, value) | 68 | #define set_mb(var, value) set_rmb(var, value) |
69 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
70 | 69 | ||
71 | /* Interrupt Control */ | 70 | /* Interrupt Control */ |
72 | #ifndef HARD_CLI | 71 | #ifndef HARD_CLI |
diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h index cb7dda1e5e91..100c3eaf3c1f 100644 --- a/include/asm-sparc/system.h +++ b/include/asm-sparc/system.h | |||
@@ -199,7 +199,6 @@ static inline unsigned long getipl(void) | |||
199 | #define wmb() mb() | 199 | #define wmb() mb() |
200 | #define read_barrier_depends() do { } while(0) | 200 | #define read_barrier_depends() do { } while(0) |
201 | #define set_mb(__var, __value) do { __var = __value; mb(); } while(0) | 201 | #define set_mb(__var, __value) do { __var = __value; mb(); } while(0) |
202 | #define set_wmb(__var, __value) set_mb(__var, __value) | ||
203 | #define smp_mb() __asm__ __volatile__("":::"memory") | 202 | #define smp_mb() __asm__ __volatile__("":::"memory") |
204 | #define smp_rmb() __asm__ __volatile__("":::"memory") | 203 | #define smp_rmb() __asm__ __volatile__("":::"memory") |
205 | #define smp_wmb() __asm__ __volatile__("":::"memory") | 204 | #define smp_wmb() __asm__ __volatile__("":::"memory") |
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h index 4ca68600c670..a8b7432c9a70 100644 --- a/include/asm-sparc64/system.h +++ b/include/asm-sparc64/system.h | |||
@@ -123,8 +123,6 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ | |||
123 | #define read_barrier_depends() do { } while(0) | 123 | #define read_barrier_depends() do { } while(0) |
124 | #define set_mb(__var, __value) \ | 124 | #define set_mb(__var, __value) \ |
125 | do { __var = __value; membar_storeload_storestore(); } while(0) | 125 | do { __var = __value; membar_storeload_storestore(); } while(0) |
126 | #define set_wmb(__var, __value) \ | ||
127 | do { __var = __value; wmb(); } while(0) | ||
128 | 126 | ||
129 | #ifdef CONFIG_SMP | 127 | #ifdef CONFIG_SMP |
130 | #define smp_mb() mb() | 128 | #define smp_mb() mb() |
diff --git a/include/asm-v850/system.h b/include/asm-v850/system.h index 7091af4b7866..da39916f10b0 100644 --- a/include/asm-v850/system.h +++ b/include/asm-v850/system.h | |||
@@ -68,7 +68,6 @@ static inline int irqs_disabled (void) | |||
68 | #define read_barrier_depends() ((void)0) | 68 | #define read_barrier_depends() ((void)0) |
69 | #define set_rmb(var, value) do { xchg (&var, value); } while (0) | 69 | #define set_rmb(var, value) do { xchg (&var, value); } while (0) |
70 | #define set_mb(var, value) set_rmb (var, value) | 70 | #define set_mb(var, value) set_rmb (var, value) |
71 | #define set_wmb(var, value) do { var = value; wmb (); } while (0) | ||
72 | 71 | ||
73 | #define smp_mb() mb () | 72 | #define smp_mb() mb () |
74 | #define smp_rmb() rmb () | 73 | #define smp_rmb() rmb () |
diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h index f67f2873a922..6bf170bceae1 100644 --- a/include/asm-x86_64/system.h +++ b/include/asm-x86_64/system.h | |||
@@ -240,7 +240,6 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, | |||
240 | #endif | 240 | #endif |
241 | #define read_barrier_depends() do {} while(0) | 241 | #define read_barrier_depends() do {} while(0) |
242 | #define set_mb(var, value) do { (void) xchg(&var, value); } while (0) | 242 | #define set_mb(var, value) do { (void) xchg(&var, value); } while (0) |
243 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
244 | 243 | ||
245 | #define warn_if_not_ulong(x) do { unsigned long foo; (void) (&(x) == &foo); } while (0) | 244 | #define warn_if_not_ulong(x) do { unsigned long foo; (void) (&(x) == &foo); } while (0) |
246 | 245 | ||
diff --git a/include/asm-xtensa/system.h b/include/asm-xtensa/system.h index f986170bd2a1..932bda92a21c 100644 --- a/include/asm-xtensa/system.h +++ b/include/asm-xtensa/system.h | |||
@@ -99,7 +99,6 @@ static inline void disable_coprocessor(int i) | |||
99 | #endif | 99 | #endif |
100 | 100 | ||
101 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 101 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
102 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
103 | 102 | ||
104 | #if !defined (__ASSEMBLY__) | 103 | #if !defined (__ASSEMBLY__) |
105 | 104 | ||
diff --git a/include/linux/delayacct.h b/include/linux/delayacct.h new file mode 100644 index 000000000000..7e8b6011b8f3 --- /dev/null +++ b/include/linux/delayacct.h | |||
@@ -0,0 +1,119 @@ | |||
1 | /* delayacct.h - per-task delay accounting | ||
2 | * | ||
3 | * Copyright (C) Shailabh Nagar, IBM Corp. 2006 | ||
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 as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
13 | * the GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef _LINUX_DELAYACCT_H | ||
18 | #define _LINUX_DELAYACCT_H | ||
19 | |||
20 | #include <linux/sched.h> | ||
21 | #include <linux/taskstats_kern.h> | ||
22 | |||
23 | /* | ||
24 | * Per-task flags relevant to delay accounting | ||
25 | * maintained privately to avoid exhausting similar flags in sched.h:PF_* | ||
26 | * Used to set current->delays->flags | ||
27 | */ | ||
28 | #define DELAYACCT_PF_SWAPIN 0x00000001 /* I am doing a swapin */ | ||
29 | |||
30 | #ifdef CONFIG_TASK_DELAY_ACCT | ||
31 | |||
32 | extern int delayacct_on; /* Delay accounting turned on/off */ | ||
33 | extern kmem_cache_t *delayacct_cache; | ||
34 | extern void delayacct_init(void); | ||
35 | extern void __delayacct_tsk_init(struct task_struct *); | ||
36 | extern void __delayacct_tsk_exit(struct task_struct *); | ||
37 | extern void __delayacct_blkio_start(void); | ||
38 | extern void __delayacct_blkio_end(void); | ||
39 | extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *); | ||
40 | extern __u64 __delayacct_blkio_ticks(struct task_struct *); | ||
41 | |||
42 | static inline void delayacct_set_flag(int flag) | ||
43 | { | ||
44 | if (current->delays) | ||
45 | current->delays->flags |= flag; | ||
46 | } | ||
47 | |||
48 | static inline void delayacct_clear_flag(int flag) | ||
49 | { | ||
50 | if (current->delays) | ||
51 | current->delays->flags &= ~flag; | ||
52 | } | ||
53 | |||
54 | static inline void delayacct_tsk_init(struct task_struct *tsk) | ||
55 | { | ||
56 | /* reinitialize in case parent's non-null pointer was dup'ed*/ | ||
57 | tsk->delays = NULL; | ||
58 | if (unlikely(delayacct_on)) | ||
59 | __delayacct_tsk_init(tsk); | ||
60 | } | ||
61 | |||
62 | static inline void delayacct_tsk_exit(struct task_struct *tsk) | ||
63 | { | ||
64 | if (tsk->delays) | ||
65 | __delayacct_tsk_exit(tsk); | ||
66 | } | ||
67 | |||
68 | static inline void delayacct_blkio_start(void) | ||
69 | { | ||
70 | if (current->delays) | ||
71 | __delayacct_blkio_start(); | ||
72 | } | ||
73 | |||
74 | static inline void delayacct_blkio_end(void) | ||
75 | { | ||
76 | if (current->delays) | ||
77 | __delayacct_blkio_end(); | ||
78 | } | ||
79 | |||
80 | static inline int delayacct_add_tsk(struct taskstats *d, | ||
81 | struct task_struct *tsk) | ||
82 | { | ||
83 | if (likely(!delayacct_on)) | ||
84 | return -EINVAL; | ||
85 | if (!tsk->delays) | ||
86 | return 0; | ||
87 | return __delayacct_add_tsk(d, tsk); | ||
88 | } | ||
89 | |||
90 | static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk) | ||
91 | { | ||
92 | if (tsk->delays) | ||
93 | return __delayacct_blkio_ticks(tsk); | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | #else | ||
98 | static inline void delayacct_set_flag(int flag) | ||
99 | {} | ||
100 | static inline void delayacct_clear_flag(int flag) | ||
101 | {} | ||
102 | static inline void delayacct_init(void) | ||
103 | {} | ||
104 | static inline void delayacct_tsk_init(struct task_struct *tsk) | ||
105 | {} | ||
106 | static inline void delayacct_tsk_exit(struct task_struct *tsk) | ||
107 | {} | ||
108 | static inline void delayacct_blkio_start(void) | ||
109 | {} | ||
110 | static inline void delayacct_blkio_end(void) | ||
111 | {} | ||
112 | static inline int delayacct_add_tsk(struct taskstats *d, | ||
113 | struct task_struct *tsk) | ||
114 | { return 0; } | ||
115 | static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk) | ||
116 | { return 0; } | ||
117 | #endif /* CONFIG_TASK_DELAY_ACCT */ | ||
118 | |||
119 | #endif | ||
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 21338bb3441d..9418519a55d1 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h | |||
@@ -115,6 +115,7 @@ | |||
115 | #define I2C_DRIVERID_BT866 85 /* Conexant bt866 video encoder */ | 115 | #define I2C_DRIVERID_BT866 85 /* Conexant bt866 video encoder */ |
116 | #define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */ | 116 | #define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */ |
117 | #define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */ | 117 | #define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */ |
118 | #define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */ | ||
118 | 119 | ||
119 | #define I2C_DRIVERID_I2CDEV 900 | 120 | #define I2C_DRIVERID_I2CDEV 900 |
120 | #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ | 121 | #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ |
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index eef0876d8307..383627ad328f 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h | |||
@@ -23,8 +23,8 @@ struct vlan_collection; | |||
23 | struct vlan_dev_info; | 23 | struct vlan_dev_info; |
24 | struct hlist_node; | 24 | struct hlist_node; |
25 | 25 | ||
26 | #include <linux/proc_fs.h> /* for proc_dir_entry */ | ||
27 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
27 | #include <linux/etherdevice.h> | ||
28 | 28 | ||
29 | #define VLAN_HLEN 4 /* The additional bytes (on top of the Ethernet header) | 29 | #define VLAN_HLEN 4 /* The additional bytes (on top of the Ethernet header) |
30 | * that VLAN requires. | 30 | * that VLAN requires. |
@@ -185,7 +185,8 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb, | |||
185 | * This allows the VLAN to have a different MAC than the underlying | 185 | * This allows the VLAN to have a different MAC than the underlying |
186 | * device, and still route correctly. | 186 | * device, and still route correctly. |
187 | */ | 187 | */ |
188 | if (!memcmp(eth_hdr(skb)->h_dest, skb->dev->dev_addr, ETH_ALEN)) | 188 | if (!compare_ether_addr(eth_hdr(skb)->h_dest, |
189 | skb->dev->dev_addr)) | ||
189 | skb->pkt_type = PACKET_HOST; | 190 | skb->pkt_type = PACKET_HOST; |
190 | break; | 191 | break; |
191 | }; | 192 | }; |
diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 7cce5dfa092f..1c65e7a9f186 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h | |||
@@ -28,7 +28,6 @@ struct task_struct *kthread_create(int (*threadfn)(void *data), | |||
28 | 28 | ||
29 | void kthread_bind(struct task_struct *k, unsigned int cpu); | 29 | void kthread_bind(struct task_struct *k, unsigned int cpu); |
30 | int kthread_stop(struct task_struct *k); | 30 | int kthread_stop(struct task_struct *k); |
31 | int kthread_stop_sem(struct task_struct *k, struct semaphore *s); | ||
32 | int kthread_should_stop(void); | 31 | int kthread_should_stop(void); |
33 | 32 | ||
34 | #endif /* _LINUX_KTHREAD_H */ | 33 | #endif /* _LINUX_KTHREAD_H */ |
diff --git a/include/linux/list.h b/include/linux/list.h index 6b74adf5297f..65a5b5ceda49 100644 --- a/include/linux/list.h +++ b/include/linux/list.h | |||
@@ -265,6 +265,17 @@ static inline void list_move_tail(struct list_head *list, | |||
265 | } | 265 | } |
266 | 266 | ||
267 | /** | 267 | /** |
268 | * list_is_last - tests whether @list is the last entry in list @head | ||
269 | * @list: the entry to test | ||
270 | * @head: the head of the list | ||
271 | */ | ||
272 | static inline int list_is_last(const struct list_head *list, | ||
273 | const struct list_head *head) | ||
274 | { | ||
275 | return list->next == head; | ||
276 | } | ||
277 | |||
278 | /** | ||
268 | * list_empty - tests whether a list is empty | 279 | * list_empty - tests whether a list is empty |
269 | * @head: the list to test. | 280 | * @head: the list to test. |
270 | */ | 281 | */ |
diff --git a/include/linux/module.h b/include/linux/module.h index d06c74fb8c26..0dfb794c52d3 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -362,10 +362,8 @@ int is_module_address(unsigned long addr); | |||
362 | 362 | ||
363 | /* Returns module and fills in value, defined and namebuf, or NULL if | 363 | /* Returns module and fills in value, defined and namebuf, or NULL if |
364 | symnum out of range. */ | 364 | symnum out of range. */ |
365 | struct module *module_get_kallsym(unsigned int symnum, | 365 | struct module *module_get_kallsym(unsigned int symnum, unsigned long *value, |
366 | unsigned long *value, | 366 | char *type, char *name, size_t namelen); |
367 | char *type, | ||
368 | char namebuf[128]); | ||
369 | 367 | ||
370 | /* Look for this name: can be of form module:name. */ | 368 | /* Look for this name: can be of form module:name. */ |
371 | unsigned long module_kallsyms_lookup_name(const char *name); | 369 | unsigned long module_kallsyms_lookup_name(const char *name); |
@@ -535,8 +533,8 @@ static inline const char *module_address_lookup(unsigned long addr, | |||
535 | 533 | ||
536 | static inline struct module *module_get_kallsym(unsigned int symnum, | 534 | static inline struct module *module_get_kallsym(unsigned int symnum, |
537 | unsigned long *value, | 535 | unsigned long *value, |
538 | char *type, | 536 | char *type, char *name, |
539 | char namebuf[128]) | 537 | size_t namelen) |
540 | { | 538 | { |
541 | return NULL; | 539 | return NULL; |
542 | } | 540 | } |
diff --git a/include/linux/namei.h b/include/linux/namei.h index 58cb3d3d44b4..45511a5918d3 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
@@ -11,7 +11,7 @@ struct open_intent { | |||
11 | struct file *file; | 11 | struct file *file; |
12 | }; | 12 | }; |
13 | 13 | ||
14 | enum { MAX_NESTED_LINKS = 5 }; | 14 | enum { MAX_NESTED_LINKS = 8 }; |
15 | 15 | ||
16 | struct nameidata { | 16 | struct nameidata { |
17 | struct dentry *dentry; | 17 | struct dentry *dentry; |
diff --git a/include/linux/nsc_gpio.h b/include/linux/nsc_gpio.h index 135742cfada5..7da0cf3702ee 100644 --- a/include/linux/nsc_gpio.h +++ b/include/linux/nsc_gpio.h | |||
@@ -25,8 +25,6 @@ struct nsc_gpio_ops { | |||
25 | void (*gpio_dump) (struct nsc_gpio_ops *amp, unsigned iminor); | 25 | void (*gpio_dump) (struct nsc_gpio_ops *amp, unsigned iminor); |
26 | int (*gpio_get) (unsigned iminor); | 26 | int (*gpio_get) (unsigned iminor); |
27 | void (*gpio_set) (unsigned iminor, int state); | 27 | void (*gpio_set) (unsigned iminor, int state); |
28 | void (*gpio_set_high)(unsigned iminor); | ||
29 | void (*gpio_set_low) (unsigned iminor); | ||
30 | void (*gpio_change) (unsigned iminor); | 28 | void (*gpio_change) (unsigned iminor); |
31 | int (*gpio_current) (unsigned iminor); | 29 | int (*gpio_current) (unsigned iminor); |
32 | struct device* dev; /* for dev_dbg() support, set in init */ | 30 | struct device* dev; /* for dev_dbg() support, set in init */ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 1c876e27ff93..6afa72e080cb 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -463,6 +463,10 @@ struct signal_struct { | |||
463 | #ifdef CONFIG_BSD_PROCESS_ACCT | 463 | #ifdef CONFIG_BSD_PROCESS_ACCT |
464 | struct pacct_struct pacct; /* per-process accounting information */ | 464 | struct pacct_struct pacct; /* per-process accounting information */ |
465 | #endif | 465 | #endif |
466 | #ifdef CONFIG_TASKSTATS | ||
467 | spinlock_t stats_lock; | ||
468 | struct taskstats *stats; | ||
469 | #endif | ||
466 | }; | 470 | }; |
467 | 471 | ||
468 | /* Context switch must be unlocked if interrupts are to be enabled */ | 472 | /* Context switch must be unlocked if interrupts are to be enabled */ |
@@ -537,7 +541,7 @@ extern struct user_struct root_user; | |||
537 | struct backing_dev_info; | 541 | struct backing_dev_info; |
538 | struct reclaim_state; | 542 | struct reclaim_state; |
539 | 543 | ||
540 | #ifdef CONFIG_SCHEDSTATS | 544 | #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) |
541 | struct sched_info { | 545 | struct sched_info { |
542 | /* cumulative counters */ | 546 | /* cumulative counters */ |
543 | unsigned long cpu_time, /* time spent on the cpu */ | 547 | unsigned long cpu_time, /* time spent on the cpu */ |
@@ -548,9 +552,53 @@ struct sched_info { | |||
548 | unsigned long last_arrival, /* when we last ran on a cpu */ | 552 | unsigned long last_arrival, /* when we last ran on a cpu */ |
549 | last_queued; /* when we were last queued to run */ | 553 | last_queued; /* when we were last queued to run */ |
550 | }; | 554 | }; |
555 | #endif /* defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) */ | ||
551 | 556 | ||
557 | #ifdef CONFIG_SCHEDSTATS | ||
552 | extern struct file_operations proc_schedstat_operations; | 558 | extern struct file_operations proc_schedstat_operations; |
559 | #endif /* CONFIG_SCHEDSTATS */ | ||
560 | |||
561 | #ifdef CONFIG_TASK_DELAY_ACCT | ||
562 | struct task_delay_info { | ||
563 | spinlock_t lock; | ||
564 | unsigned int flags; /* Private per-task flags */ | ||
565 | |||
566 | /* For each stat XXX, add following, aligned appropriately | ||
567 | * | ||
568 | * struct timespec XXX_start, XXX_end; | ||
569 | * u64 XXX_delay; | ||
570 | * u32 XXX_count; | ||
571 | * | ||
572 | * Atomicity of updates to XXX_delay, XXX_count protected by | ||
573 | * single lock above (split into XXX_lock if contention is an issue). | ||
574 | */ | ||
575 | |||
576 | /* | ||
577 | * XXX_count is incremented on every XXX operation, the delay | ||
578 | * associated with the operation is added to XXX_delay. | ||
579 | * XXX_delay contains the accumulated delay time in nanoseconds. | ||
580 | */ | ||
581 | struct timespec blkio_start, blkio_end; /* Shared by blkio, swapin */ | ||
582 | u64 blkio_delay; /* wait for sync block io completion */ | ||
583 | u64 swapin_delay; /* wait for swapin block io completion */ | ||
584 | u32 blkio_count; /* total count of the number of sync block */ | ||
585 | /* io operations performed */ | ||
586 | u32 swapin_count; /* total count of the number of swapin block */ | ||
587 | /* io operations performed */ | ||
588 | }; | ||
589 | #endif /* CONFIG_TASK_DELAY_ACCT */ | ||
590 | |||
591 | static inline int sched_info_on(void) | ||
592 | { | ||
593 | #ifdef CONFIG_SCHEDSTATS | ||
594 | return 1; | ||
595 | #elif defined(CONFIG_TASK_DELAY_ACCT) | ||
596 | extern int delayacct_on; | ||
597 | return delayacct_on; | ||
598 | #else | ||
599 | return 0; | ||
553 | #endif | 600 | #endif |
601 | } | ||
554 | 602 | ||
555 | enum idle_type | 603 | enum idle_type |
556 | { | 604 | { |
@@ -747,7 +795,7 @@ struct task_struct { | |||
747 | cpumask_t cpus_allowed; | 795 | cpumask_t cpus_allowed; |
748 | unsigned int time_slice, first_time_slice; | 796 | unsigned int time_slice, first_time_slice; |
749 | 797 | ||
750 | #ifdef CONFIG_SCHEDSTATS | 798 | #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) |
751 | struct sched_info sched_info; | 799 | struct sched_info sched_info; |
752 | #endif | 800 | #endif |
753 | 801 | ||
@@ -945,6 +993,10 @@ struct task_struct { | |||
945 | * cache last used pipe for splice | 993 | * cache last used pipe for splice |
946 | */ | 994 | */ |
947 | struct pipe_inode_info *splice_pipe; | 995 | struct pipe_inode_info *splice_pipe; |
996 | #ifdef CONFIG_TASK_DELAY_ACCT | ||
997 | spinlock_t delays_lock; | ||
998 | struct task_delay_info *delays; | ||
999 | #endif | ||
948 | }; | 1000 | }; |
949 | 1001 | ||
950 | static inline pid_t process_group(struct task_struct *tsk) | 1002 | static inline pid_t process_group(struct task_struct *tsk) |
diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h new file mode 100644 index 000000000000..f1cb6cddd19d --- /dev/null +++ b/include/linux/taskstats.h | |||
@@ -0,0 +1,137 @@ | |||
1 | /* taskstats.h - exporting per-task statistics | ||
2 | * | ||
3 | * Copyright (C) Shailabh Nagar, IBM Corp. 2006 | ||
4 | * (C) Balbir Singh, IBM Corp. 2006 | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of version 2.1 of the GNU Lesser General Public License | ||
8 | * as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it would be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
13 | */ | ||
14 | |||
15 | #ifndef _LINUX_TASKSTATS_H | ||
16 | #define _LINUX_TASKSTATS_H | ||
17 | |||
18 | /* Format for per-task data returned to userland when | ||
19 | * - a task exits | ||
20 | * - listener requests stats for a task | ||
21 | * | ||
22 | * The struct is versioned. Newer versions should only add fields to | ||
23 | * the bottom of the struct to maintain backward compatibility. | ||
24 | * | ||
25 | * | ||
26 | * To add new fields | ||
27 | * a) bump up TASKSTATS_VERSION | ||
28 | * b) add comment indicating new version number at end of struct | ||
29 | * c) add new fields after version comment; maintain 64-bit alignment | ||
30 | */ | ||
31 | |||
32 | #define TASKSTATS_VERSION 1 | ||
33 | |||
34 | struct taskstats { | ||
35 | |||
36 | /* Version 1 */ | ||
37 | __u16 version; | ||
38 | __u16 padding[3]; /* Userspace should not interpret the padding | ||
39 | * field which can be replaced by useful | ||
40 | * fields if struct taskstats is extended. | ||
41 | */ | ||
42 | |||
43 | /* Delay accounting fields start | ||
44 | * | ||
45 | * All values, until comment "Delay accounting fields end" are | ||
46 | * available only if delay accounting is enabled, even though the last | ||
47 | * few fields are not delays | ||
48 | * | ||
49 | * xxx_count is the number of delay values recorded | ||
50 | * xxx_delay_total is the corresponding cumulative delay in nanoseconds | ||
51 | * | ||
52 | * xxx_delay_total wraps around to zero on overflow | ||
53 | * xxx_count incremented regardless of overflow | ||
54 | */ | ||
55 | |||
56 | /* Delay waiting for cpu, while runnable | ||
57 | * count, delay_total NOT updated atomically | ||
58 | */ | ||
59 | __u64 cpu_count; | ||
60 | __u64 cpu_delay_total; | ||
61 | |||
62 | /* Following four fields atomically updated using task->delays->lock */ | ||
63 | |||
64 | /* Delay waiting for synchronous block I/O to complete | ||
65 | * does not account for delays in I/O submission | ||
66 | */ | ||
67 | __u64 blkio_count; | ||
68 | __u64 blkio_delay_total; | ||
69 | |||
70 | /* Delay waiting for page fault I/O (swap in only) */ | ||
71 | __u64 swapin_count; | ||
72 | __u64 swapin_delay_total; | ||
73 | |||
74 | /* cpu "wall-clock" running time | ||
75 | * On some architectures, value will adjust for cpu time stolen | ||
76 | * from the kernel in involuntary waits due to virtualization. | ||
77 | * Value is cumulative, in nanoseconds, without a corresponding count | ||
78 | * and wraps around to zero silently on overflow | ||
79 | */ | ||
80 | __u64 cpu_run_real_total; | ||
81 | |||
82 | /* cpu "virtual" running time | ||
83 | * Uses time intervals seen by the kernel i.e. no adjustment | ||
84 | * for kernel's involuntary waits due to virtualization. | ||
85 | * Value is cumulative, in nanoseconds, without a corresponding count | ||
86 | * and wraps around to zero silently on overflow | ||
87 | */ | ||
88 | __u64 cpu_run_virtual_total; | ||
89 | /* Delay accounting fields end */ | ||
90 | /* version 1 ends here */ | ||
91 | }; | ||
92 | |||
93 | |||
94 | /* | ||
95 | * Commands sent from userspace | ||
96 | * Not versioned. New commands should only be inserted at the enum's end | ||
97 | * prior to __TASKSTATS_CMD_MAX | ||
98 | */ | ||
99 | |||
100 | enum { | ||
101 | TASKSTATS_CMD_UNSPEC = 0, /* Reserved */ | ||
102 | TASKSTATS_CMD_GET, /* user->kernel request/get-response */ | ||
103 | TASKSTATS_CMD_NEW, /* kernel->user event */ | ||
104 | __TASKSTATS_CMD_MAX, | ||
105 | }; | ||
106 | |||
107 | #define TASKSTATS_CMD_MAX (__TASKSTATS_CMD_MAX - 1) | ||
108 | |||
109 | enum { | ||
110 | TASKSTATS_TYPE_UNSPEC = 0, /* Reserved */ | ||
111 | TASKSTATS_TYPE_PID, /* Process id */ | ||
112 | TASKSTATS_TYPE_TGID, /* Thread group id */ | ||
113 | TASKSTATS_TYPE_STATS, /* taskstats structure */ | ||
114 | TASKSTATS_TYPE_AGGR_PID, /* contains pid + stats */ | ||
115 | TASKSTATS_TYPE_AGGR_TGID, /* contains tgid + stats */ | ||
116 | __TASKSTATS_TYPE_MAX, | ||
117 | }; | ||
118 | |||
119 | #define TASKSTATS_TYPE_MAX (__TASKSTATS_TYPE_MAX - 1) | ||
120 | |||
121 | enum { | ||
122 | TASKSTATS_CMD_ATTR_UNSPEC = 0, | ||
123 | TASKSTATS_CMD_ATTR_PID, | ||
124 | TASKSTATS_CMD_ATTR_TGID, | ||
125 | TASKSTATS_CMD_ATTR_REGISTER_CPUMASK, | ||
126 | TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK, | ||
127 | __TASKSTATS_CMD_ATTR_MAX, | ||
128 | }; | ||
129 | |||
130 | #define TASKSTATS_CMD_ATTR_MAX (__TASKSTATS_CMD_ATTR_MAX - 1) | ||
131 | |||
132 | /* NETLINK_GENERIC related info */ | ||
133 | |||
134 | #define TASKSTATS_GENL_NAME "TASKSTATS" | ||
135 | #define TASKSTATS_GENL_VERSION 0x1 | ||
136 | |||
137 | #endif /* _LINUX_TASKSTATS_H */ | ||
diff --git a/include/linux/taskstats_kern.h b/include/linux/taskstats_kern.h new file mode 100644 index 000000000000..16894b7edcc8 --- /dev/null +++ b/include/linux/taskstats_kern.h | |||
@@ -0,0 +1,89 @@ | |||
1 | /* taskstats_kern.h - kernel header for per-task statistics interface | ||
2 | * | ||
3 | * Copyright (C) Shailabh Nagar, IBM Corp. 2006 | ||
4 | * (C) Balbir Singh, IBM Corp. 2006 | ||
5 | */ | ||
6 | |||
7 | #ifndef _LINUX_TASKSTATS_KERN_H | ||
8 | #define _LINUX_TASKSTATS_KERN_H | ||
9 | |||
10 | #include <linux/taskstats.h> | ||
11 | #include <linux/sched.h> | ||
12 | #include <net/genetlink.h> | ||
13 | |||
14 | #ifdef CONFIG_TASKSTATS | ||
15 | extern kmem_cache_t *taskstats_cache; | ||
16 | extern struct mutex taskstats_exit_mutex; | ||
17 | |||
18 | static inline void taskstats_exit_free(struct taskstats *tidstats) | ||
19 | { | ||
20 | if (tidstats) | ||
21 | kmem_cache_free(taskstats_cache, tidstats); | ||
22 | } | ||
23 | |||
24 | static inline void taskstats_tgid_init(struct signal_struct *sig) | ||
25 | { | ||
26 | spin_lock_init(&sig->stats_lock); | ||
27 | sig->stats = NULL; | ||
28 | } | ||
29 | |||
30 | static inline void taskstats_tgid_alloc(struct signal_struct *sig) | ||
31 | { | ||
32 | struct taskstats *stats; | ||
33 | unsigned long flags; | ||
34 | |||
35 | stats = kmem_cache_zalloc(taskstats_cache, SLAB_KERNEL); | ||
36 | if (!stats) | ||
37 | return; | ||
38 | |||
39 | spin_lock_irqsave(&sig->stats_lock, flags); | ||
40 | if (!sig->stats) { | ||
41 | sig->stats = stats; | ||
42 | stats = NULL; | ||
43 | } | ||
44 | spin_unlock_irqrestore(&sig->stats_lock, flags); | ||
45 | |||
46 | if (stats) | ||
47 | kmem_cache_free(taskstats_cache, stats); | ||
48 | } | ||
49 | |||
50 | static inline void taskstats_tgid_free(struct signal_struct *sig) | ||
51 | { | ||
52 | struct taskstats *stats = NULL; | ||
53 | unsigned long flags; | ||
54 | |||
55 | spin_lock_irqsave(&sig->stats_lock, flags); | ||
56 | if (sig->stats) { | ||
57 | stats = sig->stats; | ||
58 | sig->stats = NULL; | ||
59 | } | ||
60 | spin_unlock_irqrestore(&sig->stats_lock, flags); | ||
61 | if (stats) | ||
62 | kmem_cache_free(taskstats_cache, stats); | ||
63 | } | ||
64 | |||
65 | extern void taskstats_exit_alloc(struct taskstats **, unsigned int *); | ||
66 | extern void taskstats_exit_send(struct task_struct *, struct taskstats *, int, unsigned int); | ||
67 | extern void taskstats_init_early(void); | ||
68 | extern void taskstats_tgid_alloc(struct signal_struct *); | ||
69 | #else | ||
70 | static inline void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu) | ||
71 | {} | ||
72 | static inline void taskstats_exit_free(struct taskstats *ptidstats) | ||
73 | {} | ||
74 | static inline void taskstats_exit_send(struct task_struct *tsk, | ||
75 | struct taskstats *tidstats, | ||
76 | int group_dead, unsigned int cpu) | ||
77 | {} | ||
78 | static inline void taskstats_tgid_init(struct signal_struct *sig) | ||
79 | {} | ||
80 | static inline void taskstats_tgid_alloc(struct signal_struct *sig) | ||
81 | {} | ||
82 | static inline void taskstats_tgid_free(struct signal_struct *sig) | ||
83 | {} | ||
84 | static inline void taskstats_init_early(void) | ||
85 | {} | ||
86 | #endif /* CONFIG_TASKSTATS */ | ||
87 | |||
88 | #endif | ||
89 | |||
diff --git a/include/linux/time.h b/include/linux/time.h index c05f8bb9a323..a5b739967b74 100644 --- a/include/linux/time.h +++ b/include/linux/time.h | |||
@@ -71,6 +71,18 @@ extern unsigned long mktime(const unsigned int year, const unsigned int mon, | |||
71 | extern void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec); | 71 | extern void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec); |
72 | 72 | ||
73 | /* | 73 | /* |
74 | * sub = lhs - rhs, in normalized form | ||
75 | */ | ||
76 | static inline struct timespec timespec_sub(struct timespec lhs, | ||
77 | struct timespec rhs) | ||
78 | { | ||
79 | struct timespec ts_delta; | ||
80 | set_normalized_timespec(&ts_delta, lhs.tv_sec - rhs.tv_sec, | ||
81 | lhs.tv_nsec - rhs.tv_nsec); | ||
82 | return ts_delta; | ||
83 | } | ||
84 | |||
85 | /* | ||
74 | * Returns true if the timespec is norm, false if denorm: | 86 | * Returns true if the timespec is norm, false if denorm: |
75 | */ | 87 | */ |
76 | #define timespec_valid(ts) \ | 88 | #define timespec_valid(ts) \ |
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index f6024ab4eff0..71b6363caaaf 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h | |||
@@ -11,6 +11,7 @@ struct vm_area_struct; | |||
11 | #define VM_ALLOC 0x00000002 /* vmalloc() */ | 11 | #define VM_ALLOC 0x00000002 /* vmalloc() */ |
12 | #define VM_MAP 0x00000004 /* vmap()ed pages */ | 12 | #define VM_MAP 0x00000004 /* vmap()ed pages */ |
13 | #define VM_USERMAP 0x00000008 /* suitable for remap_vmalloc_range */ | 13 | #define VM_USERMAP 0x00000008 /* suitable for remap_vmalloc_range */ |
14 | #define VM_VPAGES 0x00000010 /* buffer for pages was vmalloc'ed */ | ||
14 | /* bits [20..32] reserved for arch specific ioremap internals */ | 15 | /* bits [20..32] reserved for arch specific ioremap internals */ |
15 | 16 | ||
16 | /* | 17 | /* |
diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 805de50df00d..8c2287264266 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h | |||
@@ -150,4 +150,24 @@ static inline int genlmsg_unicast(struct sk_buff *skb, u32 pid) | |||
150 | return nlmsg_unicast(genl_sock, skb, pid); | 150 | return nlmsg_unicast(genl_sock, skb, pid); |
151 | } | 151 | } |
152 | 152 | ||
153 | /** | ||
154 | * gennlmsg_data - head of message payload | ||
155 | * @gnlh: genetlink messsage header | ||
156 | */ | ||
157 | static inline void *genlmsg_data(const struct genlmsghdr *gnlh) | ||
158 | { | ||
159 | return ((unsigned char *) gnlh + GENL_HDRLEN); | ||
160 | } | ||
161 | |||
162 | /** | ||
163 | * genlmsg_len - length of message payload | ||
164 | * @gnlh: genetlink message header | ||
165 | */ | ||
166 | static inline int genlmsg_len(const struct genlmsghdr *gnlh) | ||
167 | { | ||
168 | struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh - | ||
169 | NLMSG_HDRLEN); | ||
170 | return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); | ||
171 | } | ||
172 | |||
153 | #endif /* __NET_GENERIC_NETLINK_H */ | 173 | #endif /* __NET_GENERIC_NETLINK_H */ |
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h index fcb5ba87dcc5..0ff67398928d 100644 --- a/include/rdma/ib_addr.h +++ b/include/rdma/ib_addr.h | |||
@@ -89,9 +89,10 @@ static inline void ib_addr_set_pkey(struct rdma_dev_addr *dev_addr, u16 pkey) | |||
89 | dev_addr->broadcast[9] = (unsigned char) pkey; | 89 | dev_addr->broadcast[9] = (unsigned char) pkey; |
90 | } | 90 | } |
91 | 91 | ||
92 | static inline union ib_gid *ib_addr_get_sgid(struct rdma_dev_addr *dev_addr) | 92 | static inline void ib_addr_get_sgid(struct rdma_dev_addr *dev_addr, |
93 | union ib_gid *gid) | ||
93 | { | 94 | { |
94 | return (union ib_gid *) (dev_addr->src_dev_addr + 4); | 95 | memcpy(gid, dev_addr->src_dev_addr + 4, sizeof *gid); |
95 | } | 96 | } |
96 | 97 | ||
97 | static inline void ib_addr_set_sgid(struct rdma_dev_addr *dev_addr, | 98 | static inline void ib_addr_set_sgid(struct rdma_dev_addr *dev_addr, |
@@ -100,9 +101,10 @@ static inline void ib_addr_set_sgid(struct rdma_dev_addr *dev_addr, | |||
100 | memcpy(dev_addr->src_dev_addr + 4, gid, sizeof *gid); | 101 | memcpy(dev_addr->src_dev_addr + 4, gid, sizeof *gid); |
101 | } | 102 | } |
102 | 103 | ||
103 | static inline union ib_gid *ib_addr_get_dgid(struct rdma_dev_addr *dev_addr) | 104 | static inline void ib_addr_get_dgid(struct rdma_dev_addr *dev_addr, |
105 | union ib_gid *gid) | ||
104 | { | 106 | { |
105 | return (union ib_gid *) (dev_addr->dst_dev_addr + 4); | 107 | memcpy(gid, dev_addr->dst_dev_addr + 4, sizeof *gid); |
106 | } | 108 | } |
107 | 109 | ||
108 | static inline void ib_addr_set_dgid(struct rdma_dev_addr *dev_addr, | 110 | static inline void ib_addr_set_dgid(struct rdma_dev_addr *dev_addr, |
diff --git a/include/rdma/ib_fmr_pool.h b/include/rdma/ib_fmr_pool.h index 4ace54cd0cce..00dadbf94e1d 100644 --- a/include/rdma/ib_fmr_pool.h +++ b/include/rdma/ib_fmr_pool.h | |||
@@ -88,7 +88,7 @@ int ib_flush_fmr_pool(struct ib_fmr_pool *pool); | |||
88 | struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle, | 88 | struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle, |
89 | u64 *page_list, | 89 | u64 *page_list, |
90 | int list_len, | 90 | int list_len, |
91 | u64 *io_virtual_address); | 91 | u64 io_virtual_address); |
92 | 92 | ||
93 | int ib_fmr_pool_unmap(struct ib_pool_fmr *fmr); | 93 | int ib_fmr_pool_unmap(struct ib_pool_fmr *fmr); |
94 | 94 | ||
diff --git a/include/video/mbxfb.h b/include/video/mbxfb.h new file mode 100644 index 000000000000..3bde0f5cd55c --- /dev/null +++ b/include/video/mbxfb.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef __MBX_FB_H | ||
2 | #define __MBX_FB_H | ||
3 | |||
4 | struct mbxfb_val { | ||
5 | unsigned int defval; | ||
6 | unsigned int min; | ||
7 | unsigned int max; | ||
8 | }; | ||
9 | |||
10 | struct fb_info; | ||
11 | |||
12 | struct mbxfb_platform_data { | ||
13 | /* Screen info */ | ||
14 | struct mbxfb_val xres; | ||
15 | struct mbxfb_val yres; | ||
16 | struct mbxfb_val bpp; | ||
17 | |||
18 | /* Memory info */ | ||
19 | unsigned long memsize; /* if 0 use ODFB? */ | ||
20 | unsigned long timings1; | ||
21 | unsigned long timings2; | ||
22 | unsigned long timings3; | ||
23 | |||
24 | int (*probe)(struct fb_info *fb); | ||
25 | int (*remove)(struct fb_info *fb); | ||
26 | }; | ||
27 | |||
28 | #endif /* __MBX_FB_H */ | ||
diff --git a/init/Kconfig b/init/Kconfig index a5b073a103e7..a099fc6526d9 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -158,6 +158,30 @@ config BSD_PROCESS_ACCT_V3 | |||
158 | for processing it. A preliminary version of these tools is available | 158 | for processing it. A preliminary version of these tools is available |
159 | at <http://www.physik3.uni-rostock.de/tim/kernel/utils/acct/>. | 159 | at <http://www.physik3.uni-rostock.de/tim/kernel/utils/acct/>. |
160 | 160 | ||
161 | config TASKSTATS | ||
162 | bool "Export task/process statistics through netlink (EXPERIMENTAL)" | ||
163 | depends on NET | ||
164 | default n | ||
165 | help | ||
166 | Export selected statistics for tasks/processes through the | ||
167 | generic netlink interface. Unlike BSD process accounting, the | ||
168 | statistics are available during the lifetime of tasks/processes as | ||
169 | responses to commands. Like BSD accounting, they are sent to user | ||
170 | space on task exit. | ||
171 | |||
172 | Say N if unsure. | ||
173 | |||
174 | config TASK_DELAY_ACCT | ||
175 | bool "Enable per-task delay accounting (EXPERIMENTAL)" | ||
176 | depends on TASKSTATS | ||
177 | help | ||
178 | Collect information on time spent by a task waiting for system | ||
179 | resources like cpu, synchronous block I/O completion and swapping | ||
180 | in pages. Such statistics can help in setting a task's priorities | ||
181 | relative to other tasks for cpu, io, rss limits etc. | ||
182 | |||
183 | Say N if unsure. | ||
184 | |||
161 | config SYSCTL | 185 | config SYSCTL |
162 | bool "Sysctl support" if EMBEDDED | 186 | bool "Sysctl support" if EMBEDDED |
163 | default y | 187 | default y |
diff --git a/init/main.c b/init/main.c index 628b8e9e841a..8651a720a092 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -41,6 +41,8 @@ | |||
41 | #include <linux/cpu.h> | 41 | #include <linux/cpu.h> |
42 | #include <linux/cpuset.h> | 42 | #include <linux/cpuset.h> |
43 | #include <linux/efi.h> | 43 | #include <linux/efi.h> |
44 | #include <linux/taskstats_kern.h> | ||
45 | #include <linux/delayacct.h> | ||
44 | #include <linux/unistd.h> | 46 | #include <linux/unistd.h> |
45 | #include <linux/rmap.h> | 47 | #include <linux/rmap.h> |
46 | #include <linux/mempolicy.h> | 48 | #include <linux/mempolicy.h> |
@@ -574,6 +576,8 @@ asmlinkage void __init start_kernel(void) | |||
574 | proc_root_init(); | 576 | proc_root_init(); |
575 | #endif | 577 | #endif |
576 | cpuset_init(); | 578 | cpuset_init(); |
579 | taskstats_init_early(); | ||
580 | delayacct_init(); | ||
577 | 581 | ||
578 | check_bugs(); | 582 | check_bugs(); |
579 | 583 | ||
diff --git a/kernel/Makefile b/kernel/Makefile index 47dbcd570cd8..d62ec66c1af2 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -48,6 +48,8 @@ obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ | |||
48 | obj-$(CONFIG_SECCOMP) += seccomp.o | 48 | obj-$(CONFIG_SECCOMP) += seccomp.o |
49 | obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o | 49 | obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o |
50 | obj-$(CONFIG_RELAY) += relay.o | 50 | obj-$(CONFIG_RELAY) += relay.o |
51 | obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o | ||
52 | obj-$(CONFIG_TASKSTATS) += taskstats.o | ||
51 | 53 | ||
52 | ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) | 54 | ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) |
53 | # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is | 55 | # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is |
diff --git a/kernel/acct.c b/kernel/acct.c index f18e0b8df3e1..2a7c933651c7 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
@@ -488,7 +488,7 @@ static void do_acct_process(struct file *file) | |||
488 | old_encode_dev(tty_devnum(current->signal->tty)) : 0; | 488 | old_encode_dev(tty_devnum(current->signal->tty)) : 0; |
489 | read_unlock(&tasklist_lock); | 489 | read_unlock(&tasklist_lock); |
490 | 490 | ||
491 | spin_lock(¤t->sighand->siglock); | 491 | spin_lock_irq(¤t->sighand->siglock); |
492 | ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime))); | 492 | ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime))); |
493 | ac.ac_stime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_stime))); | 493 | ac.ac_stime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_stime))); |
494 | ac.ac_flag = pacct->ac_flag; | 494 | ac.ac_flag = pacct->ac_flag; |
@@ -496,7 +496,7 @@ static void do_acct_process(struct file *file) | |||
496 | ac.ac_minflt = encode_comp_t(pacct->ac_minflt); | 496 | ac.ac_minflt = encode_comp_t(pacct->ac_minflt); |
497 | ac.ac_majflt = encode_comp_t(pacct->ac_majflt); | 497 | ac.ac_majflt = encode_comp_t(pacct->ac_majflt); |
498 | ac.ac_exitcode = pacct->ac_exitcode; | 498 | ac.ac_exitcode = pacct->ac_exitcode; |
499 | spin_unlock(¤t->sighand->siglock); | 499 | spin_unlock_irq(¤t->sighand->siglock); |
500 | ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */ | 500 | ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */ |
501 | ac.ac_rw = encode_comp_t(ac.ac_io / 1024); | 501 | ac.ac_rw = encode_comp_t(ac.ac_io / 1024); |
502 | ac.ac_swaps = encode_comp_t(0); | 502 | ac.ac_swaps = encode_comp_t(0); |
diff --git a/kernel/delayacct.c b/kernel/delayacct.c new file mode 100644 index 000000000000..f05392d64267 --- /dev/null +++ b/kernel/delayacct.c | |||
@@ -0,0 +1,178 @@ | |||
1 | /* delayacct.c - per-task delay accounting | ||
2 | * | ||
3 | * Copyright (C) Shailabh Nagar, IBM Corp. 2006 | ||
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 as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it would be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
13 | * the GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/sched.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/time.h> | ||
19 | #include <linux/sysctl.h> | ||
20 | #include <linux/delayacct.h> | ||
21 | |||
22 | int delayacct_on __read_mostly; /* Delay accounting turned on/off */ | ||
23 | kmem_cache_t *delayacct_cache; | ||
24 | |||
25 | static int __init delayacct_setup_enable(char *str) | ||
26 | { | ||
27 | delayacct_on = 1; | ||
28 | return 1; | ||
29 | } | ||
30 | __setup("delayacct", delayacct_setup_enable); | ||
31 | |||
32 | void delayacct_init(void) | ||
33 | { | ||
34 | delayacct_cache = kmem_cache_create("delayacct_cache", | ||
35 | sizeof(struct task_delay_info), | ||
36 | 0, | ||
37 | SLAB_PANIC, | ||
38 | NULL, NULL); | ||
39 | delayacct_tsk_init(&init_task); | ||
40 | } | ||
41 | |||
42 | void __delayacct_tsk_init(struct task_struct *tsk) | ||
43 | { | ||
44 | spin_lock_init(&tsk->delays_lock); | ||
45 | /* No need to acquire tsk->delays_lock for allocation here unless | ||
46 | __delayacct_tsk_init called after tsk is attached to tasklist | ||
47 | */ | ||
48 | tsk->delays = kmem_cache_zalloc(delayacct_cache, SLAB_KERNEL); | ||
49 | if (tsk->delays) | ||
50 | spin_lock_init(&tsk->delays->lock); | ||
51 | } | ||
52 | |||
53 | void __delayacct_tsk_exit(struct task_struct *tsk) | ||
54 | { | ||
55 | struct task_delay_info *delays = tsk->delays; | ||
56 | spin_lock(&tsk->delays_lock); | ||
57 | tsk->delays = NULL; | ||
58 | spin_unlock(&tsk->delays_lock); | ||
59 | kmem_cache_free(delayacct_cache, delays); | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * Start accounting for a delay statistic using | ||
64 | * its starting timestamp (@start) | ||
65 | */ | ||
66 | |||
67 | static inline void delayacct_start(struct timespec *start) | ||
68 | { | ||
69 | do_posix_clock_monotonic_gettime(start); | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * Finish delay accounting for a statistic using | ||
74 | * its timestamps (@start, @end), accumalator (@total) and @count | ||
75 | */ | ||
76 | |||
77 | static void delayacct_end(struct timespec *start, struct timespec *end, | ||
78 | u64 *total, u32 *count) | ||
79 | { | ||
80 | struct timespec ts; | ||
81 | s64 ns; | ||
82 | |||
83 | do_posix_clock_monotonic_gettime(end); | ||
84 | ts = timespec_sub(*end, *start); | ||
85 | ns = timespec_to_ns(&ts); | ||
86 | if (ns < 0) | ||
87 | return; | ||
88 | |||
89 | spin_lock(¤t->delays->lock); | ||
90 | *total += ns; | ||
91 | (*count)++; | ||
92 | spin_unlock(¤t->delays->lock); | ||
93 | } | ||
94 | |||
95 | void __delayacct_blkio_start(void) | ||
96 | { | ||
97 | delayacct_start(¤t->delays->blkio_start); | ||
98 | } | ||
99 | |||
100 | void __delayacct_blkio_end(void) | ||
101 | { | ||
102 | if (current->delays->flags & DELAYACCT_PF_SWAPIN) | ||
103 | /* Swapin block I/O */ | ||
104 | delayacct_end(¤t->delays->blkio_start, | ||
105 | ¤t->delays->blkio_end, | ||
106 | ¤t->delays->swapin_delay, | ||
107 | ¤t->delays->swapin_count); | ||
108 | else /* Other block I/O */ | ||
109 | delayacct_end(¤t->delays->blkio_start, | ||
110 | ¤t->delays->blkio_end, | ||
111 | ¤t->delays->blkio_delay, | ||
112 | ¤t->delays->blkio_count); | ||
113 | } | ||
114 | |||
115 | int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) | ||
116 | { | ||
117 | s64 tmp; | ||
118 | struct timespec ts; | ||
119 | unsigned long t1,t2,t3; | ||
120 | |||
121 | spin_lock(&tsk->delays_lock); | ||
122 | |||
123 | /* Though tsk->delays accessed later, early exit avoids | ||
124 | * unnecessary returning of other data | ||
125 | */ | ||
126 | if (!tsk->delays) | ||
127 | goto done; | ||
128 | |||
129 | tmp = (s64)d->cpu_run_real_total; | ||
130 | cputime_to_timespec(tsk->utime + tsk->stime, &ts); | ||
131 | tmp += timespec_to_ns(&ts); | ||
132 | d->cpu_run_real_total = (tmp < (s64)d->cpu_run_real_total) ? 0 : tmp; | ||
133 | |||
134 | /* | ||
135 | * No locking available for sched_info (and too expensive to add one) | ||
136 | * Mitigate by taking snapshot of values | ||
137 | */ | ||
138 | t1 = tsk->sched_info.pcnt; | ||
139 | t2 = tsk->sched_info.run_delay; | ||
140 | t3 = tsk->sched_info.cpu_time; | ||
141 | |||
142 | d->cpu_count += t1; | ||
143 | |||
144 | jiffies_to_timespec(t2, &ts); | ||
145 | tmp = (s64)d->cpu_delay_total + timespec_to_ns(&ts); | ||
146 | d->cpu_delay_total = (tmp < (s64)d->cpu_delay_total) ? 0 : tmp; | ||
147 | |||
148 | tmp = (s64)d->cpu_run_virtual_total + (s64)jiffies_to_usecs(t3) * 1000; | ||
149 | d->cpu_run_virtual_total = | ||
150 | (tmp < (s64)d->cpu_run_virtual_total) ? 0 : tmp; | ||
151 | |||
152 | /* zero XXX_total, non-zero XXX_count implies XXX stat overflowed */ | ||
153 | |||
154 | spin_lock(&tsk->delays->lock); | ||
155 | tmp = d->blkio_delay_total + tsk->delays->blkio_delay; | ||
156 | d->blkio_delay_total = (tmp < d->blkio_delay_total) ? 0 : tmp; | ||
157 | tmp = d->swapin_delay_total + tsk->delays->swapin_delay; | ||
158 | d->swapin_delay_total = (tmp < d->swapin_delay_total) ? 0 : tmp; | ||
159 | d->blkio_count += tsk->delays->blkio_count; | ||
160 | d->swapin_count += tsk->delays->swapin_count; | ||
161 | spin_unlock(&tsk->delays->lock); | ||
162 | |||
163 | done: | ||
164 | spin_unlock(&tsk->delays_lock); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | __u64 __delayacct_blkio_ticks(struct task_struct *tsk) | ||
169 | { | ||
170 | __u64 ret; | ||
171 | |||
172 | spin_lock(&tsk->delays->lock); | ||
173 | ret = nsec_to_clock_t(tsk->delays->blkio_delay + | ||
174 | tsk->delays->swapin_delay); | ||
175 | spin_unlock(&tsk->delays->lock); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
diff --git a/kernel/exit.c b/kernel/exit.c index 6664c084783d..dba194a8d416 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <linux/mount.h> | 25 | #include <linux/mount.h> |
26 | #include <linux/proc_fs.h> | 26 | #include <linux/proc_fs.h> |
27 | #include <linux/mempolicy.h> | 27 | #include <linux/mempolicy.h> |
28 | #include <linux/taskstats_kern.h> | ||
29 | #include <linux/delayacct.h> | ||
28 | #include <linux/cpuset.h> | 30 | #include <linux/cpuset.h> |
29 | #include <linux/syscalls.h> | 31 | #include <linux/syscalls.h> |
30 | #include <linux/signal.h> | 32 | #include <linux/signal.h> |
@@ -843,7 +845,9 @@ static void exit_notify(struct task_struct *tsk) | |||
843 | fastcall NORET_TYPE void do_exit(long code) | 845 | fastcall NORET_TYPE void do_exit(long code) |
844 | { | 846 | { |
845 | struct task_struct *tsk = current; | 847 | struct task_struct *tsk = current; |
848 | struct taskstats *tidstats; | ||
846 | int group_dead; | 849 | int group_dead; |
850 | unsigned int mycpu; | ||
847 | 851 | ||
848 | profile_task_exit(tsk); | 852 | profile_task_exit(tsk); |
849 | 853 | ||
@@ -881,6 +885,8 @@ fastcall NORET_TYPE void do_exit(long code) | |||
881 | current->comm, current->pid, | 885 | current->comm, current->pid, |
882 | preempt_count()); | 886 | preempt_count()); |
883 | 887 | ||
888 | taskstats_exit_alloc(&tidstats, &mycpu); | ||
889 | |||
884 | acct_update_integrals(tsk); | 890 | acct_update_integrals(tsk); |
885 | if (tsk->mm) { | 891 | if (tsk->mm) { |
886 | update_hiwater_rss(tsk->mm); | 892 | update_hiwater_rss(tsk->mm); |
@@ -900,6 +906,10 @@ fastcall NORET_TYPE void do_exit(long code) | |||
900 | #endif | 906 | #endif |
901 | if (unlikely(tsk->audit_context)) | 907 | if (unlikely(tsk->audit_context)) |
902 | audit_free(tsk); | 908 | audit_free(tsk); |
909 | taskstats_exit_send(tsk, tidstats, group_dead, mycpu); | ||
910 | taskstats_exit_free(tidstats); | ||
911 | delayacct_tsk_exit(tsk); | ||
912 | |||
903 | exit_mm(tsk); | 913 | exit_mm(tsk); |
904 | 914 | ||
905 | if (group_dead) | 915 | if (group_dead) |
diff --git a/kernel/fork.c b/kernel/fork.c index 926e5a68ea9e..1b0f7b1e0881 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -43,6 +43,8 @@ | |||
43 | #include <linux/rmap.h> | 43 | #include <linux/rmap.h> |
44 | #include <linux/acct.h> | 44 | #include <linux/acct.h> |
45 | #include <linux/cn_proc.h> | 45 | #include <linux/cn_proc.h> |
46 | #include <linux/delayacct.h> | ||
47 | #include <linux/taskstats_kern.h> | ||
46 | 48 | ||
47 | #include <asm/pgtable.h> | 49 | #include <asm/pgtable.h> |
48 | #include <asm/pgalloc.h> | 50 | #include <asm/pgalloc.h> |
@@ -818,6 +820,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts | |||
818 | if (clone_flags & CLONE_THREAD) { | 820 | if (clone_flags & CLONE_THREAD) { |
819 | atomic_inc(¤t->signal->count); | 821 | atomic_inc(¤t->signal->count); |
820 | atomic_inc(¤t->signal->live); | 822 | atomic_inc(¤t->signal->live); |
823 | taskstats_tgid_alloc(current->signal); | ||
821 | return 0; | 824 | return 0; |
822 | } | 825 | } |
823 | sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL); | 826 | sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL); |
@@ -862,6 +865,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts | |||
862 | INIT_LIST_HEAD(&sig->cpu_timers[0]); | 865 | INIT_LIST_HEAD(&sig->cpu_timers[0]); |
863 | INIT_LIST_HEAD(&sig->cpu_timers[1]); | 866 | INIT_LIST_HEAD(&sig->cpu_timers[1]); |
864 | INIT_LIST_HEAD(&sig->cpu_timers[2]); | 867 | INIT_LIST_HEAD(&sig->cpu_timers[2]); |
868 | taskstats_tgid_init(sig); | ||
865 | 869 | ||
866 | task_lock(current->group_leader); | 870 | task_lock(current->group_leader); |
867 | memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim); | 871 | memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim); |
@@ -883,6 +887,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts | |||
883 | void __cleanup_signal(struct signal_struct *sig) | 887 | void __cleanup_signal(struct signal_struct *sig) |
884 | { | 888 | { |
885 | exit_thread_group_keys(sig); | 889 | exit_thread_group_keys(sig); |
890 | taskstats_tgid_free(sig); | ||
886 | kmem_cache_free(signal_cachep, sig); | 891 | kmem_cache_free(signal_cachep, sig); |
887 | } | 892 | } |
888 | 893 | ||
@@ -1000,6 +1005,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1000 | goto bad_fork_cleanup_put_domain; | 1005 | goto bad_fork_cleanup_put_domain; |
1001 | 1006 | ||
1002 | p->did_exec = 0; | 1007 | p->did_exec = 0; |
1008 | delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ | ||
1003 | copy_flags(clone_flags, p); | 1009 | copy_flags(clone_flags, p); |
1004 | p->pid = pid; | 1010 | p->pid = pid; |
1005 | retval = -EFAULT; | 1011 | retval = -EFAULT; |
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 39277dd6bf90..ab16a5a4cfe9 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c | |||
@@ -275,8 +275,8 @@ static void upcase_if_global(struct kallsym_iter *iter) | |||
275 | static int get_ksymbol_mod(struct kallsym_iter *iter) | 275 | static int get_ksymbol_mod(struct kallsym_iter *iter) |
276 | { | 276 | { |
277 | iter->owner = module_get_kallsym(iter->pos - kallsyms_num_syms, | 277 | iter->owner = module_get_kallsym(iter->pos - kallsyms_num_syms, |
278 | &iter->value, | 278 | &iter->value, &iter->type, |
279 | &iter->type, iter->name); | 279 | iter->name, sizeof(iter->name)); |
280 | if (iter->owner == NULL) | 280 | if (iter->owner == NULL) |
281 | return 0; | 281 | return 0; |
282 | 282 | ||
diff --git a/kernel/kthread.c b/kernel/kthread.c index 24be714b04c7..4f9c60ef95e8 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c | |||
@@ -216,23 +216,6 @@ EXPORT_SYMBOL(kthread_bind); | |||
216 | */ | 216 | */ |
217 | int kthread_stop(struct task_struct *k) | 217 | int kthread_stop(struct task_struct *k) |
218 | { | 218 | { |
219 | return kthread_stop_sem(k, NULL); | ||
220 | } | ||
221 | EXPORT_SYMBOL(kthread_stop); | ||
222 | |||
223 | /** | ||
224 | * kthread_stop_sem - stop a thread created by kthread_create(). | ||
225 | * @k: thread created by kthread_create(). | ||
226 | * @s: semaphore that @k waits on while idle. | ||
227 | * | ||
228 | * Does essentially the same thing as kthread_stop() above, but wakes | ||
229 | * @k by calling up(@s). | ||
230 | * | ||
231 | * Returns the result of threadfn(), or %-EINTR if wake_up_process() | ||
232 | * was never called. | ||
233 | */ | ||
234 | int kthread_stop_sem(struct task_struct *k, struct semaphore *s) | ||
235 | { | ||
236 | int ret; | 219 | int ret; |
237 | 220 | ||
238 | mutex_lock(&kthread_stop_lock); | 221 | mutex_lock(&kthread_stop_lock); |
@@ -246,10 +229,7 @@ int kthread_stop_sem(struct task_struct *k, struct semaphore *s) | |||
246 | 229 | ||
247 | /* Now set kthread_should_stop() to true, and wake it up. */ | 230 | /* Now set kthread_should_stop() to true, and wake it up. */ |
248 | kthread_stop_info.k = k; | 231 | kthread_stop_info.k = k; |
249 | if (s) | 232 | wake_up_process(k); |
250 | up(s); | ||
251 | else | ||
252 | wake_up_process(k); | ||
253 | put_task_struct(k); | 233 | put_task_struct(k); |
254 | 234 | ||
255 | /* Once it dies, reset stop ptr, gather result and we're done. */ | 235 | /* Once it dies, reset stop ptr, gather result and we're done. */ |
@@ -260,7 +240,7 @@ int kthread_stop_sem(struct task_struct *k, struct semaphore *s) | |||
260 | 240 | ||
261 | return ret; | 241 | return ret; |
262 | } | 242 | } |
263 | EXPORT_SYMBOL(kthread_stop_sem); | 243 | EXPORT_SYMBOL(kthread_stop); |
264 | 244 | ||
265 | static __init int helper_init(void) | 245 | static __init int helper_init(void) |
266 | { | 246 | { |
diff --git a/kernel/module.c b/kernel/module.c index 35e1b1f859d7..2a19cd47c046 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -2019,10 +2019,8 @@ const char *module_address_lookup(unsigned long addr, | |||
2019 | return NULL; | 2019 | return NULL; |
2020 | } | 2020 | } |
2021 | 2021 | ||
2022 | struct module *module_get_kallsym(unsigned int symnum, | 2022 | struct module *module_get_kallsym(unsigned int symnum, unsigned long *value, |
2023 | unsigned long *value, | 2023 | char *type, char *name, size_t namelen) |
2024 | char *type, | ||
2025 | char namebuf[128]) | ||
2026 | { | 2024 | { |
2027 | struct module *mod; | 2025 | struct module *mod; |
2028 | 2026 | ||
@@ -2031,9 +2029,8 @@ struct module *module_get_kallsym(unsigned int symnum, | |||
2031 | if (symnum < mod->num_symtab) { | 2029 | if (symnum < mod->num_symtab) { |
2032 | *value = mod->symtab[symnum].st_value; | 2030 | *value = mod->symtab[symnum].st_value; |
2033 | *type = mod->symtab[symnum].st_info; | 2031 | *type = mod->symtab[symnum].st_info; |
2034 | strncpy(namebuf, | 2032 | strlcpy(name, mod->strtab + mod->symtab[symnum].st_name, |
2035 | mod->strtab + mod->symtab[symnum].st_name, | 2033 | namelen); |
2036 | 127); | ||
2037 | mutex_unlock(&module_mutex); | 2034 | mutex_unlock(&module_mutex); |
2038 | return mod; | 2035 | return mod; |
2039 | } | 2036 | } |
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c index 494dac872a13..948bd8f643e2 100644 --- a/kernel/rtmutex-tester.c +++ b/kernel/rtmutex-tester.c | |||
@@ -275,6 +275,7 @@ static int test_func(void *data) | |||
275 | 275 | ||
276 | /* Wait for the next command to be executed */ | 276 | /* Wait for the next command to be executed */ |
277 | schedule(); | 277 | schedule(); |
278 | try_to_freeze(); | ||
278 | 279 | ||
279 | if (signal_pending(current)) | 280 | if (signal_pending(current)) |
280 | flush_signals(current); | 281 | flush_signals(current); |
diff --git a/kernel/sched.c b/kernel/sched.c index d714611f1691..b44b9a43b0fc 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/times.h> | 51 | #include <linux/times.h> |
52 | #include <linux/acct.h> | 52 | #include <linux/acct.h> |
53 | #include <linux/kprobes.h> | 53 | #include <linux/kprobes.h> |
54 | #include <linux/delayacct.h> | ||
54 | #include <asm/tlb.h> | 55 | #include <asm/tlb.h> |
55 | 56 | ||
56 | #include <asm/unistd.h> | 57 | #include <asm/unistd.h> |
@@ -501,9 +502,36 @@ struct file_operations proc_schedstat_operations = { | |||
501 | .release = single_release, | 502 | .release = single_release, |
502 | }; | 503 | }; |
503 | 504 | ||
505 | /* | ||
506 | * Expects runqueue lock to be held for atomicity of update | ||
507 | */ | ||
508 | static inline void | ||
509 | rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies) | ||
510 | { | ||
511 | if (rq) { | ||
512 | rq->rq_sched_info.run_delay += delta_jiffies; | ||
513 | rq->rq_sched_info.pcnt++; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | /* | ||
518 | * Expects runqueue lock to be held for atomicity of update | ||
519 | */ | ||
520 | static inline void | ||
521 | rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies) | ||
522 | { | ||
523 | if (rq) | ||
524 | rq->rq_sched_info.cpu_time += delta_jiffies; | ||
525 | } | ||
504 | # define schedstat_inc(rq, field) do { (rq)->field++; } while (0) | 526 | # define schedstat_inc(rq, field) do { (rq)->field++; } while (0) |
505 | # define schedstat_add(rq, field, amt) do { (rq)->field += (amt); } while (0) | 527 | # define schedstat_add(rq, field, amt) do { (rq)->field += (amt); } while (0) |
506 | #else /* !CONFIG_SCHEDSTATS */ | 528 | #else /* !CONFIG_SCHEDSTATS */ |
529 | static inline void | ||
530 | rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies) | ||
531 | {} | ||
532 | static inline void | ||
533 | rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies) | ||
534 | {} | ||
507 | # define schedstat_inc(rq, field) do { } while (0) | 535 | # define schedstat_inc(rq, field) do { } while (0) |
508 | # define schedstat_add(rq, field, amt) do { } while (0) | 536 | # define schedstat_add(rq, field, amt) do { } while (0) |
509 | #endif | 537 | #endif |
@@ -523,7 +551,7 @@ static inline struct rq *this_rq_lock(void) | |||
523 | return rq; | 551 | return rq; |
524 | } | 552 | } |
525 | 553 | ||
526 | #ifdef CONFIG_SCHEDSTATS | 554 | #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) |
527 | /* | 555 | /* |
528 | * Called when a process is dequeued from the active array and given | 556 | * Called when a process is dequeued from the active array and given |
529 | * the cpu. We should note that with the exception of interactive | 557 | * the cpu. We should note that with the exception of interactive |
@@ -551,21 +579,16 @@ static inline void sched_info_dequeued(struct task_struct *t) | |||
551 | */ | 579 | */ |
552 | static void sched_info_arrive(struct task_struct *t) | 580 | static void sched_info_arrive(struct task_struct *t) |
553 | { | 581 | { |
554 | unsigned long now = jiffies, diff = 0; | 582 | unsigned long now = jiffies, delta_jiffies = 0; |
555 | struct rq *rq = task_rq(t); | ||
556 | 583 | ||
557 | if (t->sched_info.last_queued) | 584 | if (t->sched_info.last_queued) |
558 | diff = now - t->sched_info.last_queued; | 585 | delta_jiffies = now - t->sched_info.last_queued; |
559 | sched_info_dequeued(t); | 586 | sched_info_dequeued(t); |
560 | t->sched_info.run_delay += diff; | 587 | t->sched_info.run_delay += delta_jiffies; |
561 | t->sched_info.last_arrival = now; | 588 | t->sched_info.last_arrival = now; |
562 | t->sched_info.pcnt++; | 589 | t->sched_info.pcnt++; |
563 | 590 | ||
564 | if (!rq) | 591 | rq_sched_info_arrive(task_rq(t), delta_jiffies); |
565 | return; | ||
566 | |||
567 | rq->rq_sched_info.run_delay += diff; | ||
568 | rq->rq_sched_info.pcnt++; | ||
569 | } | 592 | } |
570 | 593 | ||
571 | /* | 594 | /* |
@@ -585,8 +608,9 @@ static void sched_info_arrive(struct task_struct *t) | |||
585 | */ | 608 | */ |
586 | static inline void sched_info_queued(struct task_struct *t) | 609 | static inline void sched_info_queued(struct task_struct *t) |
587 | { | 610 | { |
588 | if (!t->sched_info.last_queued) | 611 | if (unlikely(sched_info_on())) |
589 | t->sched_info.last_queued = jiffies; | 612 | if (!t->sched_info.last_queued) |
613 | t->sched_info.last_queued = jiffies; | ||
590 | } | 614 | } |
591 | 615 | ||
592 | /* | 616 | /* |
@@ -595,13 +619,10 @@ static inline void sched_info_queued(struct task_struct *t) | |||
595 | */ | 619 | */ |
596 | static inline void sched_info_depart(struct task_struct *t) | 620 | static inline void sched_info_depart(struct task_struct *t) |
597 | { | 621 | { |
598 | struct rq *rq = task_rq(t); | 622 | unsigned long delta_jiffies = jiffies - t->sched_info.last_arrival; |
599 | unsigned long diff = jiffies - t->sched_info.last_arrival; | ||
600 | |||
601 | t->sched_info.cpu_time += diff; | ||
602 | 623 | ||
603 | if (rq) | 624 | t->sched_info.cpu_time += delta_jiffies; |
604 | rq->rq_sched_info.cpu_time += diff; | 625 | rq_sched_info_depart(task_rq(t), delta_jiffies); |
605 | } | 626 | } |
606 | 627 | ||
607 | /* | 628 | /* |
@@ -610,7 +631,7 @@ static inline void sched_info_depart(struct task_struct *t) | |||
610 | * the idle task.) We are only called when prev != next. | 631 | * the idle task.) We are only called when prev != next. |
611 | */ | 632 | */ |
612 | static inline void | 633 | static inline void |
613 | sched_info_switch(struct task_struct *prev, struct task_struct *next) | 634 | __sched_info_switch(struct task_struct *prev, struct task_struct *next) |
614 | { | 635 | { |
615 | struct rq *rq = task_rq(prev); | 636 | struct rq *rq = task_rq(prev); |
616 | 637 | ||
@@ -625,10 +646,16 @@ sched_info_switch(struct task_struct *prev, struct task_struct *next) | |||
625 | if (next != rq->idle) | 646 | if (next != rq->idle) |
626 | sched_info_arrive(next); | 647 | sched_info_arrive(next); |
627 | } | 648 | } |
649 | static inline void | ||
650 | sched_info_switch(struct task_struct *prev, struct task_struct *next) | ||
651 | { | ||
652 | if (unlikely(sched_info_on())) | ||
653 | __sched_info_switch(prev, next); | ||
654 | } | ||
628 | #else | 655 | #else |
629 | #define sched_info_queued(t) do { } while (0) | 656 | #define sched_info_queued(t) do { } while (0) |
630 | #define sched_info_switch(t, next) do { } while (0) | 657 | #define sched_info_switch(t, next) do { } while (0) |
631 | #endif /* CONFIG_SCHEDSTATS */ | 658 | #endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */ |
632 | 659 | ||
633 | /* | 660 | /* |
634 | * Adding/removing a task to/from a priority array: | 661 | * Adding/removing a task to/from a priority array: |
@@ -1530,8 +1557,9 @@ void fastcall sched_fork(struct task_struct *p, int clone_flags) | |||
1530 | 1557 | ||
1531 | INIT_LIST_HEAD(&p->run_list); | 1558 | INIT_LIST_HEAD(&p->run_list); |
1532 | p->array = NULL; | 1559 | p->array = NULL; |
1533 | #ifdef CONFIG_SCHEDSTATS | 1560 | #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) |
1534 | memset(&p->sched_info, 0, sizeof(p->sched_info)); | 1561 | if (unlikely(sched_info_on())) |
1562 | memset(&p->sched_info, 0, sizeof(p->sched_info)); | ||
1535 | #endif | 1563 | #endif |
1536 | #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW) | 1564 | #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW) |
1537 | p->oncpu = 0; | 1565 | p->oncpu = 0; |
@@ -1788,7 +1816,15 @@ context_switch(struct rq *rq, struct task_struct *prev, | |||
1788 | WARN_ON(rq->prev_mm); | 1816 | WARN_ON(rq->prev_mm); |
1789 | rq->prev_mm = oldmm; | 1817 | rq->prev_mm = oldmm; |
1790 | } | 1818 | } |
1819 | /* | ||
1820 | * Since the runqueue lock will be released by the next | ||
1821 | * task (which is an invalid locking op but in the case | ||
1822 | * of the scheduler it's an obvious special-case), so we | ||
1823 | * do an early lockdep release here: | ||
1824 | */ | ||
1825 | #ifndef __ARCH_WANT_UNLOCKED_CTXSW | ||
1791 | spin_release(&rq->lock.dep_map, 1, _THIS_IP_); | 1826 | spin_release(&rq->lock.dep_map, 1, _THIS_IP_); |
1827 | #endif | ||
1792 | 1828 | ||
1793 | /* Here we just switch the register state and the stack. */ | 1829 | /* Here we just switch the register state and the stack. */ |
1794 | switch_to(prev, next, prev); | 1830 | switch_to(prev, next, prev); |
@@ -4526,9 +4562,11 @@ void __sched io_schedule(void) | |||
4526 | { | 4562 | { |
4527 | struct rq *rq = &__raw_get_cpu_var(runqueues); | 4563 | struct rq *rq = &__raw_get_cpu_var(runqueues); |
4528 | 4564 | ||
4565 | delayacct_blkio_start(); | ||
4529 | atomic_inc(&rq->nr_iowait); | 4566 | atomic_inc(&rq->nr_iowait); |
4530 | schedule(); | 4567 | schedule(); |
4531 | atomic_dec(&rq->nr_iowait); | 4568 | atomic_dec(&rq->nr_iowait); |
4569 | delayacct_blkio_end(); | ||
4532 | } | 4570 | } |
4533 | EXPORT_SYMBOL(io_schedule); | 4571 | EXPORT_SYMBOL(io_schedule); |
4534 | 4572 | ||
@@ -4537,9 +4575,11 @@ long __sched io_schedule_timeout(long timeout) | |||
4537 | struct rq *rq = &__raw_get_cpu_var(runqueues); | 4575 | struct rq *rq = &__raw_get_cpu_var(runqueues); |
4538 | long ret; | 4576 | long ret; |
4539 | 4577 | ||
4578 | delayacct_blkio_start(); | ||
4540 | atomic_inc(&rq->nr_iowait); | 4579 | atomic_inc(&rq->nr_iowait); |
4541 | ret = schedule_timeout(timeout); | 4580 | ret = schedule_timeout(timeout); |
4542 | atomic_dec(&rq->nr_iowait); | 4581 | atomic_dec(&rq->nr_iowait); |
4582 | delayacct_blkio_end(); | ||
4543 | return ret; | 4583 | return ret; |
4544 | } | 4584 | } |
4545 | 4585 | ||
diff --git a/kernel/softirq.c b/kernel/softirq.c index fd12f2556f0d..0f08a84ae307 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -311,8 +311,6 @@ void open_softirq(int nr, void (*action)(struct softirq_action*), void *data) | |||
311 | softirq_vec[nr].action = action; | 311 | softirq_vec[nr].action = action; |
312 | } | 312 | } |
313 | 313 | ||
314 | EXPORT_UNUSED_SYMBOL(open_softirq); /* June 2006 */ | ||
315 | |||
316 | /* Tasklets */ | 314 | /* Tasklets */ |
317 | struct tasklet_head | 315 | struct tasklet_head |
318 | { | 316 | { |
diff --git a/kernel/taskstats.c b/kernel/taskstats.c new file mode 100644 index 000000000000..f45179ce028e --- /dev/null +++ b/kernel/taskstats.c | |||
@@ -0,0 +1,568 @@ | |||
1 | /* | ||
2 | * taskstats.c - Export per-task statistics to userland | ||
3 | * | ||
4 | * Copyright (C) Shailabh Nagar, IBM Corp. 2006 | ||
5 | * (C) Balbir Singh, IBM Corp. 2006 | ||
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 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/taskstats_kern.h> | ||
21 | #include <linux/delayacct.h> | ||
22 | #include <linux/cpumask.h> | ||
23 | #include <linux/percpu.h> | ||
24 | #include <net/genetlink.h> | ||
25 | #include <asm/atomic.h> | ||
26 | |||
27 | /* | ||
28 | * Maximum length of a cpumask that can be specified in | ||
29 | * the TASKSTATS_CMD_ATTR_REGISTER/DEREGISTER_CPUMASK attribute | ||
30 | */ | ||
31 | #define TASKSTATS_CPUMASK_MAXLEN (100+6*NR_CPUS) | ||
32 | |||
33 | static DEFINE_PER_CPU(__u32, taskstats_seqnum) = { 0 }; | ||
34 | static int family_registered; | ||
35 | kmem_cache_t *taskstats_cache; | ||
36 | |||
37 | static struct genl_family family = { | ||
38 | .id = GENL_ID_GENERATE, | ||
39 | .name = TASKSTATS_GENL_NAME, | ||
40 | .version = TASKSTATS_GENL_VERSION, | ||
41 | .maxattr = TASKSTATS_CMD_ATTR_MAX, | ||
42 | }; | ||
43 | |||
44 | static struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] | ||
45 | __read_mostly = { | ||
46 | [TASKSTATS_CMD_ATTR_PID] = { .type = NLA_U32 }, | ||
47 | [TASKSTATS_CMD_ATTR_TGID] = { .type = NLA_U32 }, | ||
48 | [TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING }, | ||
49 | [TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },}; | ||
50 | |||
51 | struct listener { | ||
52 | struct list_head list; | ||
53 | pid_t pid; | ||
54 | char valid; | ||
55 | }; | ||
56 | |||
57 | struct listener_list { | ||
58 | struct rw_semaphore sem; | ||
59 | struct list_head list; | ||
60 | }; | ||
61 | static DEFINE_PER_CPU(struct listener_list, listener_array); | ||
62 | |||
63 | enum actions { | ||
64 | REGISTER, | ||
65 | DEREGISTER, | ||
66 | CPU_DONT_CARE | ||
67 | }; | ||
68 | |||
69 | static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, | ||
70 | void **replyp, size_t size) | ||
71 | { | ||
72 | struct sk_buff *skb; | ||
73 | void *reply; | ||
74 | |||
75 | /* | ||
76 | * If new attributes are added, please revisit this allocation | ||
77 | */ | ||
78 | skb = nlmsg_new(size); | ||
79 | if (!skb) | ||
80 | return -ENOMEM; | ||
81 | |||
82 | if (!info) { | ||
83 | int seq = get_cpu_var(taskstats_seqnum)++; | ||
84 | put_cpu_var(taskstats_seqnum); | ||
85 | |||
86 | reply = genlmsg_put(skb, 0, seq, | ||
87 | family.id, 0, 0, | ||
88 | cmd, family.version); | ||
89 | } else | ||
90 | reply = genlmsg_put(skb, info->snd_pid, info->snd_seq, | ||
91 | family.id, 0, 0, | ||
92 | cmd, family.version); | ||
93 | if (reply == NULL) { | ||
94 | nlmsg_free(skb); | ||
95 | return -EINVAL; | ||
96 | } | ||
97 | |||
98 | *skbp = skb; | ||
99 | *replyp = reply; | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * Send taskstats data in @skb to listener with nl_pid @pid | ||
105 | */ | ||
106 | static int send_reply(struct sk_buff *skb, pid_t pid) | ||
107 | { | ||
108 | struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data); | ||
109 | void *reply = genlmsg_data(genlhdr); | ||
110 | int rc; | ||
111 | |||
112 | rc = genlmsg_end(skb, reply); | ||
113 | if (rc < 0) { | ||
114 | nlmsg_free(skb); | ||
115 | return rc; | ||
116 | } | ||
117 | |||
118 | return genlmsg_unicast(skb, pid); | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Send taskstats data in @skb to listeners registered for @cpu's exit data | ||
123 | */ | ||
124 | static int send_cpu_listeners(struct sk_buff *skb, unsigned int cpu) | ||
125 | { | ||
126 | struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data); | ||
127 | struct listener_list *listeners; | ||
128 | struct listener *s, *tmp; | ||
129 | struct sk_buff *skb_next, *skb_cur = skb; | ||
130 | void *reply = genlmsg_data(genlhdr); | ||
131 | int rc, ret, delcount = 0; | ||
132 | |||
133 | rc = genlmsg_end(skb, reply); | ||
134 | if (rc < 0) { | ||
135 | nlmsg_free(skb); | ||
136 | return rc; | ||
137 | } | ||
138 | |||
139 | rc = 0; | ||
140 | listeners = &per_cpu(listener_array, cpu); | ||
141 | down_read(&listeners->sem); | ||
142 | list_for_each_entry_safe(s, tmp, &listeners->list, list) { | ||
143 | skb_next = NULL; | ||
144 | if (!list_is_last(&s->list, &listeners->list)) { | ||
145 | skb_next = skb_clone(skb_cur, GFP_KERNEL); | ||
146 | if (!skb_next) { | ||
147 | nlmsg_free(skb_cur); | ||
148 | rc = -ENOMEM; | ||
149 | break; | ||
150 | } | ||
151 | } | ||
152 | ret = genlmsg_unicast(skb_cur, s->pid); | ||
153 | if (ret == -ECONNREFUSED) { | ||
154 | s->valid = 0; | ||
155 | delcount++; | ||
156 | rc = ret; | ||
157 | } | ||
158 | skb_cur = skb_next; | ||
159 | } | ||
160 | up_read(&listeners->sem); | ||
161 | |||
162 | if (!delcount) | ||
163 | return rc; | ||
164 | |||
165 | /* Delete invalidated entries */ | ||
166 | down_write(&listeners->sem); | ||
167 | list_for_each_entry_safe(s, tmp, &listeners->list, list) { | ||
168 | if (!s->valid) { | ||
169 | list_del(&s->list); | ||
170 | kfree(s); | ||
171 | } | ||
172 | } | ||
173 | up_write(&listeners->sem); | ||
174 | return rc; | ||
175 | } | ||
176 | |||
177 | static int fill_pid(pid_t pid, struct task_struct *pidtsk, | ||
178 | struct taskstats *stats) | ||
179 | { | ||
180 | int rc; | ||
181 | struct task_struct *tsk = pidtsk; | ||
182 | |||
183 | if (!pidtsk) { | ||
184 | read_lock(&tasklist_lock); | ||
185 | tsk = find_task_by_pid(pid); | ||
186 | if (!tsk) { | ||
187 | read_unlock(&tasklist_lock); | ||
188 | return -ESRCH; | ||
189 | } | ||
190 | get_task_struct(tsk); | ||
191 | read_unlock(&tasklist_lock); | ||
192 | } else | ||
193 | get_task_struct(tsk); | ||
194 | |||
195 | /* | ||
196 | * Each accounting subsystem adds calls to its functions to | ||
197 | * fill in relevant parts of struct taskstsats as follows | ||
198 | * | ||
199 | * rc = per-task-foo(stats, tsk); | ||
200 | * if (rc) | ||
201 | * goto err; | ||
202 | */ | ||
203 | |||
204 | rc = delayacct_add_tsk(stats, tsk); | ||
205 | stats->version = TASKSTATS_VERSION; | ||
206 | |||
207 | /* Define err: label here if needed */ | ||
208 | put_task_struct(tsk); | ||
209 | return rc; | ||
210 | |||
211 | } | ||
212 | |||
213 | static int fill_tgid(pid_t tgid, struct task_struct *tgidtsk, | ||
214 | struct taskstats *stats) | ||
215 | { | ||
216 | struct task_struct *tsk, *first; | ||
217 | unsigned long flags; | ||
218 | |||
219 | /* | ||
220 | * Add additional stats from live tasks except zombie thread group | ||
221 | * leaders who are already counted with the dead tasks | ||
222 | */ | ||
223 | first = tgidtsk; | ||
224 | if (!first) { | ||
225 | read_lock(&tasklist_lock); | ||
226 | first = find_task_by_pid(tgid); | ||
227 | if (!first) { | ||
228 | read_unlock(&tasklist_lock); | ||
229 | return -ESRCH; | ||
230 | } | ||
231 | get_task_struct(first); | ||
232 | read_unlock(&tasklist_lock); | ||
233 | } else | ||
234 | get_task_struct(first); | ||
235 | |||
236 | /* Start with stats from dead tasks */ | ||
237 | spin_lock_irqsave(&first->signal->stats_lock, flags); | ||
238 | if (first->signal->stats) | ||
239 | memcpy(stats, first->signal->stats, sizeof(*stats)); | ||
240 | spin_unlock_irqrestore(&first->signal->stats_lock, flags); | ||
241 | |||
242 | tsk = first; | ||
243 | read_lock(&tasklist_lock); | ||
244 | do { | ||
245 | if (tsk->exit_state == EXIT_ZOMBIE && thread_group_leader(tsk)) | ||
246 | continue; | ||
247 | /* | ||
248 | * Accounting subsystem can call its functions here to | ||
249 | * fill in relevant parts of struct taskstsats as follows | ||
250 | * | ||
251 | * per-task-foo(stats, tsk); | ||
252 | */ | ||
253 | delayacct_add_tsk(stats, tsk); | ||
254 | |||
255 | } while_each_thread(first, tsk); | ||
256 | read_unlock(&tasklist_lock); | ||
257 | stats->version = TASKSTATS_VERSION; | ||
258 | |||
259 | /* | ||
260 | * Accounting subsytems can also add calls here to modify | ||
261 | * fields of taskstats. | ||
262 | */ | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | |||
268 | static void fill_tgid_exit(struct task_struct *tsk) | ||
269 | { | ||
270 | unsigned long flags; | ||
271 | |||
272 | spin_lock_irqsave(&tsk->signal->stats_lock, flags); | ||
273 | if (!tsk->signal->stats) | ||
274 | goto ret; | ||
275 | |||
276 | /* | ||
277 | * Each accounting subsystem calls its functions here to | ||
278 | * accumalate its per-task stats for tsk, into the per-tgid structure | ||
279 | * | ||
280 | * per-task-foo(tsk->signal->stats, tsk); | ||
281 | */ | ||
282 | delayacct_add_tsk(tsk->signal->stats, tsk); | ||
283 | ret: | ||
284 | spin_unlock_irqrestore(&tsk->signal->stats_lock, flags); | ||
285 | return; | ||
286 | } | ||
287 | |||
288 | static int add_del_listener(pid_t pid, cpumask_t *maskp, int isadd) | ||
289 | { | ||
290 | struct listener_list *listeners; | ||
291 | struct listener *s, *tmp; | ||
292 | unsigned int cpu; | ||
293 | cpumask_t mask = *maskp; | ||
294 | |||
295 | if (!cpus_subset(mask, cpu_possible_map)) | ||
296 | return -EINVAL; | ||
297 | |||
298 | if (isadd == REGISTER) { | ||
299 | for_each_cpu_mask(cpu, mask) { | ||
300 | s = kmalloc_node(sizeof(struct listener), GFP_KERNEL, | ||
301 | cpu_to_node(cpu)); | ||
302 | if (!s) | ||
303 | goto cleanup; | ||
304 | s->pid = pid; | ||
305 | INIT_LIST_HEAD(&s->list); | ||
306 | s->valid = 1; | ||
307 | |||
308 | listeners = &per_cpu(listener_array, cpu); | ||
309 | down_write(&listeners->sem); | ||
310 | list_add(&s->list, &listeners->list); | ||
311 | up_write(&listeners->sem); | ||
312 | } | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | /* Deregister or cleanup */ | ||
317 | cleanup: | ||
318 | for_each_cpu_mask(cpu, mask) { | ||
319 | listeners = &per_cpu(listener_array, cpu); | ||
320 | down_write(&listeners->sem); | ||
321 | list_for_each_entry_safe(s, tmp, &listeners->list, list) { | ||
322 | if (s->pid == pid) { | ||
323 | list_del(&s->list); | ||
324 | kfree(s); | ||
325 | break; | ||
326 | } | ||
327 | } | ||
328 | up_write(&listeners->sem); | ||
329 | } | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | static int parse(struct nlattr *na, cpumask_t *mask) | ||
334 | { | ||
335 | char *data; | ||
336 | int len; | ||
337 | int ret; | ||
338 | |||
339 | if (na == NULL) | ||
340 | return 1; | ||
341 | len = nla_len(na); | ||
342 | if (len > TASKSTATS_CPUMASK_MAXLEN) | ||
343 | return -E2BIG; | ||
344 | if (len < 1) | ||
345 | return -EINVAL; | ||
346 | data = kmalloc(len, GFP_KERNEL); | ||
347 | if (!data) | ||
348 | return -ENOMEM; | ||
349 | nla_strlcpy(data, na, len); | ||
350 | ret = cpulist_parse(data, *mask); | ||
351 | kfree(data); | ||
352 | return ret; | ||
353 | } | ||
354 | |||
355 | static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) | ||
356 | { | ||
357 | int rc = 0; | ||
358 | struct sk_buff *rep_skb; | ||
359 | struct taskstats stats; | ||
360 | void *reply; | ||
361 | size_t size; | ||
362 | struct nlattr *na; | ||
363 | cpumask_t mask; | ||
364 | |||
365 | rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], &mask); | ||
366 | if (rc < 0) | ||
367 | return rc; | ||
368 | if (rc == 0) | ||
369 | return add_del_listener(info->snd_pid, &mask, REGISTER); | ||
370 | |||
371 | rc = parse(info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK], &mask); | ||
372 | if (rc < 0) | ||
373 | return rc; | ||
374 | if (rc == 0) | ||
375 | return add_del_listener(info->snd_pid, &mask, DEREGISTER); | ||
376 | |||
377 | /* | ||
378 | * Size includes space for nested attributes | ||
379 | */ | ||
380 | size = nla_total_size(sizeof(u32)) + | ||
381 | nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); | ||
382 | |||
383 | memset(&stats, 0, sizeof(stats)); | ||
384 | rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); | ||
385 | if (rc < 0) | ||
386 | return rc; | ||
387 | |||
388 | if (info->attrs[TASKSTATS_CMD_ATTR_PID]) { | ||
389 | u32 pid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_PID]); | ||
390 | rc = fill_pid(pid, NULL, &stats); | ||
391 | if (rc < 0) | ||
392 | goto err; | ||
393 | |||
394 | na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_PID); | ||
395 | NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_PID, pid); | ||
396 | NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, | ||
397 | stats); | ||
398 | } else if (info->attrs[TASKSTATS_CMD_ATTR_TGID]) { | ||
399 | u32 tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]); | ||
400 | rc = fill_tgid(tgid, NULL, &stats); | ||
401 | if (rc < 0) | ||
402 | goto err; | ||
403 | |||
404 | na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_TGID); | ||
405 | NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_TGID, tgid); | ||
406 | NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, | ||
407 | stats); | ||
408 | } else { | ||
409 | rc = -EINVAL; | ||
410 | goto err; | ||
411 | } | ||
412 | |||
413 | nla_nest_end(rep_skb, na); | ||
414 | |||
415 | return send_reply(rep_skb, info->snd_pid); | ||
416 | |||
417 | nla_put_failure: | ||
418 | return genlmsg_cancel(rep_skb, reply); | ||
419 | err: | ||
420 | nlmsg_free(rep_skb); | ||
421 | return rc; | ||
422 | } | ||
423 | |||
424 | void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu) | ||
425 | { | ||
426 | struct listener_list *listeners; | ||
427 | struct taskstats *tmp; | ||
428 | /* | ||
429 | * This is the cpu on which the task is exiting currently and will | ||
430 | * be the one for which the exit event is sent, even if the cpu | ||
431 | * on which this function is running changes later. | ||
432 | */ | ||
433 | *mycpu = raw_smp_processor_id(); | ||
434 | |||
435 | *ptidstats = NULL; | ||
436 | tmp = kmem_cache_zalloc(taskstats_cache, SLAB_KERNEL); | ||
437 | if (!tmp) | ||
438 | return; | ||
439 | |||
440 | listeners = &per_cpu(listener_array, *mycpu); | ||
441 | down_read(&listeners->sem); | ||
442 | if (!list_empty(&listeners->list)) { | ||
443 | *ptidstats = tmp; | ||
444 | tmp = NULL; | ||
445 | } | ||
446 | up_read(&listeners->sem); | ||
447 | kfree(tmp); | ||
448 | } | ||
449 | |||
450 | /* Send pid data out on exit */ | ||
451 | void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, | ||
452 | int group_dead, unsigned int mycpu) | ||
453 | { | ||
454 | int rc; | ||
455 | struct sk_buff *rep_skb; | ||
456 | void *reply; | ||
457 | size_t size; | ||
458 | int is_thread_group; | ||
459 | struct nlattr *na; | ||
460 | unsigned long flags; | ||
461 | |||
462 | if (!family_registered || !tidstats) | ||
463 | return; | ||
464 | |||
465 | spin_lock_irqsave(&tsk->signal->stats_lock, flags); | ||
466 | is_thread_group = tsk->signal->stats ? 1 : 0; | ||
467 | spin_unlock_irqrestore(&tsk->signal->stats_lock, flags); | ||
468 | |||
469 | rc = 0; | ||
470 | /* | ||
471 | * Size includes space for nested attributes | ||
472 | */ | ||
473 | size = nla_total_size(sizeof(u32)) + | ||
474 | nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); | ||
475 | |||
476 | if (is_thread_group) | ||
477 | size = 2 * size; /* PID + STATS + TGID + STATS */ | ||
478 | |||
479 | rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); | ||
480 | if (rc < 0) | ||
481 | goto ret; | ||
482 | |||
483 | rc = fill_pid(tsk->pid, tsk, tidstats); | ||
484 | if (rc < 0) | ||
485 | goto err_skb; | ||
486 | |||
487 | na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_PID); | ||
488 | NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_PID, (u32)tsk->pid); | ||
489 | NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, | ||
490 | *tidstats); | ||
491 | nla_nest_end(rep_skb, na); | ||
492 | |||
493 | if (!is_thread_group) | ||
494 | goto send; | ||
495 | |||
496 | /* | ||
497 | * tsk has/had a thread group so fill the tsk->signal->stats structure | ||
498 | * Doesn't matter if tsk is the leader or the last group member leaving | ||
499 | */ | ||
500 | |||
501 | fill_tgid_exit(tsk); | ||
502 | if (!group_dead) | ||
503 | goto send; | ||
504 | |||
505 | na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_TGID); | ||
506 | NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_TGID, (u32)tsk->tgid); | ||
507 | /* No locking needed for tsk->signal->stats since group is dead */ | ||
508 | NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, | ||
509 | *tsk->signal->stats); | ||
510 | nla_nest_end(rep_skb, na); | ||
511 | |||
512 | send: | ||
513 | send_cpu_listeners(rep_skb, mycpu); | ||
514 | return; | ||
515 | |||
516 | nla_put_failure: | ||
517 | genlmsg_cancel(rep_skb, reply); | ||
518 | goto ret; | ||
519 | err_skb: | ||
520 | nlmsg_free(rep_skb); | ||
521 | ret: | ||
522 | return; | ||
523 | } | ||
524 | |||
525 | static struct genl_ops taskstats_ops = { | ||
526 | .cmd = TASKSTATS_CMD_GET, | ||
527 | .doit = taskstats_user_cmd, | ||
528 | .policy = taskstats_cmd_get_policy, | ||
529 | }; | ||
530 | |||
531 | /* Needed early in initialization */ | ||
532 | void __init taskstats_init_early(void) | ||
533 | { | ||
534 | unsigned int i; | ||
535 | |||
536 | taskstats_cache = kmem_cache_create("taskstats_cache", | ||
537 | sizeof(struct taskstats), | ||
538 | 0, SLAB_PANIC, NULL, NULL); | ||
539 | for_each_possible_cpu(i) { | ||
540 | INIT_LIST_HEAD(&(per_cpu(listener_array, i).list)); | ||
541 | init_rwsem(&(per_cpu(listener_array, i).sem)); | ||
542 | } | ||
543 | } | ||
544 | |||
545 | static int __init taskstats_init(void) | ||
546 | { | ||
547 | int rc; | ||
548 | |||
549 | rc = genl_register_family(&family); | ||
550 | if (rc) | ||
551 | return rc; | ||
552 | |||
553 | rc = genl_register_ops(&family, &taskstats_ops); | ||
554 | if (rc < 0) | ||
555 | goto err; | ||
556 | |||
557 | family_registered = 1; | ||
558 | return 0; | ||
559 | err: | ||
560 | genl_unregister_family(&family); | ||
561 | return rc; | ||
562 | } | ||
563 | |||
564 | /* | ||
565 | * late initcall ensures initialization of statistics collection | ||
566 | * mechanisms precedes initialization of the taskstats interface | ||
567 | */ | ||
568 | late_initcall(taskstats_init); | ||
diff --git a/kernel/timer.c b/kernel/timer.c index 2a87430a58d4..05809c2e2fd6 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -374,6 +374,7 @@ int del_timer_sync(struct timer_list *timer) | |||
374 | int ret = try_to_del_timer_sync(timer); | 374 | int ret = try_to_del_timer_sync(timer); |
375 | if (ret >= 0) | 375 | if (ret >= 0) |
376 | return ret; | 376 | return ret; |
377 | cpu_relax(); | ||
377 | } | 378 | } |
378 | } | 379 | } |
379 | 380 | ||
@@ -968,6 +969,7 @@ void __init timekeeping_init(void) | |||
968 | } | 969 | } |
969 | 970 | ||
970 | 971 | ||
972 | static int timekeeping_suspended; | ||
971 | /* | 973 | /* |
972 | * timekeeping_resume - Resumes the generic timekeeping subsystem. | 974 | * timekeeping_resume - Resumes the generic timekeeping subsystem. |
973 | * @dev: unused | 975 | * @dev: unused |
@@ -983,6 +985,18 @@ static int timekeeping_resume(struct sys_device *dev) | |||
983 | write_seqlock_irqsave(&xtime_lock, flags); | 985 | write_seqlock_irqsave(&xtime_lock, flags); |
984 | /* restart the last cycle value */ | 986 | /* restart the last cycle value */ |
985 | clock->cycle_last = clocksource_read(clock); | 987 | clock->cycle_last = clocksource_read(clock); |
988 | clock->error = 0; | ||
989 | timekeeping_suspended = 0; | ||
990 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
991 | return 0; | ||
992 | } | ||
993 | |||
994 | static int timekeeping_suspend(struct sys_device *dev, pm_message_t state) | ||
995 | { | ||
996 | unsigned long flags; | ||
997 | |||
998 | write_seqlock_irqsave(&xtime_lock, flags); | ||
999 | timekeeping_suspended = 1; | ||
986 | write_sequnlock_irqrestore(&xtime_lock, flags); | 1000 | write_sequnlock_irqrestore(&xtime_lock, flags); |
987 | return 0; | 1001 | return 0; |
988 | } | 1002 | } |
@@ -990,6 +1004,7 @@ static int timekeeping_resume(struct sys_device *dev) | |||
990 | /* sysfs resume/suspend bits for timekeeping */ | 1004 | /* sysfs resume/suspend bits for timekeeping */ |
991 | static struct sysdev_class timekeeping_sysclass = { | 1005 | static struct sysdev_class timekeeping_sysclass = { |
992 | .resume = timekeeping_resume, | 1006 | .resume = timekeeping_resume, |
1007 | .suspend = timekeeping_suspend, | ||
993 | set_kset_name("timekeeping"), | 1008 | set_kset_name("timekeeping"), |
994 | }; | 1009 | }; |
995 | 1010 | ||
@@ -1100,13 +1115,16 @@ static void update_wall_time(void) | |||
1100 | { | 1115 | { |
1101 | cycle_t offset; | 1116 | cycle_t offset; |
1102 | 1117 | ||
1103 | clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift; | 1118 | /* Make sure we're fully resumed: */ |
1119 | if (unlikely(timekeeping_suspended)) | ||
1120 | return; | ||
1104 | 1121 | ||
1105 | #ifdef CONFIG_GENERIC_TIME | 1122 | #ifdef CONFIG_GENERIC_TIME |
1106 | offset = (clocksource_read(clock) - clock->cycle_last) & clock->mask; | 1123 | offset = (clocksource_read(clock) - clock->cycle_last) & clock->mask; |
1107 | #else | 1124 | #else |
1108 | offset = clock->cycle_interval; | 1125 | offset = clock->cycle_interval; |
1109 | #endif | 1126 | #endif |
1127 | clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift; | ||
1110 | 1128 | ||
1111 | /* normally this loop will run just once, however in the | 1129 | /* normally this loop will run just once, however in the |
1112 | * case of lost or late ticks, it will accumulate correctly. | 1130 | * case of lost or late ticks, it will accumulate correctly. |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index e5889b1a33ff..554ee688a9f8 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -158,7 +158,7 @@ config DEBUG_RWSEMS | |||
158 | 158 | ||
159 | config DEBUG_LOCK_ALLOC | 159 | config DEBUG_LOCK_ALLOC |
160 | bool "Lock debugging: detect incorrect freeing of live locks" | 160 | bool "Lock debugging: detect incorrect freeing of live locks" |
161 | depends on TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT | 161 | depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT |
162 | select DEBUG_SPINLOCK | 162 | select DEBUG_SPINLOCK |
163 | select DEBUG_MUTEXES | 163 | select DEBUG_MUTEXES |
164 | select DEBUG_RWSEMS | 164 | select DEBUG_RWSEMS |
@@ -173,7 +173,7 @@ config DEBUG_LOCK_ALLOC | |||
173 | 173 | ||
174 | config PROVE_LOCKING | 174 | config PROVE_LOCKING |
175 | bool "Lock debugging: prove locking correctness" | 175 | bool "Lock debugging: prove locking correctness" |
176 | depends on TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT | 176 | depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT |
177 | select LOCKDEP | 177 | select LOCKDEP |
178 | select DEBUG_SPINLOCK | 178 | select DEBUG_SPINLOCK |
179 | select DEBUG_MUTEXES | 179 | select DEBUG_MUTEXES |
@@ -216,7 +216,7 @@ config PROVE_LOCKING | |||
216 | 216 | ||
217 | config LOCKDEP | 217 | config LOCKDEP |
218 | bool | 218 | bool |
219 | depends on TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT | 219 | depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT |
220 | select STACKTRACE | 220 | select STACKTRACE |
221 | select FRAME_POINTER | 221 | select FRAME_POINTER |
222 | select KALLSYMS | 222 | select KALLSYMS |
@@ -224,13 +224,14 @@ config LOCKDEP | |||
224 | 224 | ||
225 | config DEBUG_LOCKDEP | 225 | config DEBUG_LOCKDEP |
226 | bool "Lock dependency engine debugging" | 226 | bool "Lock dependency engine debugging" |
227 | depends on LOCKDEP | 227 | depends on DEBUG_KERNEL && LOCKDEP |
228 | help | 228 | help |
229 | If you say Y here, the lock dependency engine will do | 229 | If you say Y here, the lock dependency engine will do |
230 | additional runtime checks to debug itself, at the price | 230 | additional runtime checks to debug itself, at the price |
231 | of more runtime overhead. | 231 | of more runtime overhead. |
232 | 232 | ||
233 | config TRACE_IRQFLAGS | 233 | config TRACE_IRQFLAGS |
234 | depends on DEBUG_KERNEL | ||
234 | bool | 235 | bool |
235 | default y | 236 | default y |
236 | depends on TRACE_IRQFLAGS_SUPPORT | 237 | depends on TRACE_IRQFLAGS_SUPPORT |
@@ -256,6 +257,7 @@ config DEBUG_LOCKING_API_SELFTESTS | |||
256 | 257 | ||
257 | config STACKTRACE | 258 | config STACKTRACE |
258 | bool | 259 | bool |
260 | depends on DEBUG_KERNEL | ||
259 | depends on STACKTRACE_SUPPORT | 261 | depends on STACKTRACE_SUPPORT |
260 | 262 | ||
261 | config DEBUG_KOBJECT | 263 | config DEBUG_KOBJECT |
@@ -38,14 +38,15 @@ static kmem_cache_t *idr_layer_cache; | |||
38 | static struct idr_layer *alloc_layer(struct idr *idp) | 38 | static struct idr_layer *alloc_layer(struct idr *idp) |
39 | { | 39 | { |
40 | struct idr_layer *p; | 40 | struct idr_layer *p; |
41 | unsigned long flags; | ||
41 | 42 | ||
42 | spin_lock(&idp->lock); | 43 | spin_lock_irqsave(&idp->lock, flags); |
43 | if ((p = idp->id_free)) { | 44 | if ((p = idp->id_free)) { |
44 | idp->id_free = p->ary[0]; | 45 | idp->id_free = p->ary[0]; |
45 | idp->id_free_cnt--; | 46 | idp->id_free_cnt--; |
46 | p->ary[0] = NULL; | 47 | p->ary[0] = NULL; |
47 | } | 48 | } |
48 | spin_unlock(&idp->lock); | 49 | spin_unlock_irqrestore(&idp->lock, flags); |
49 | return(p); | 50 | return(p); |
50 | } | 51 | } |
51 | 52 | ||
@@ -59,12 +60,14 @@ static void __free_layer(struct idr *idp, struct idr_layer *p) | |||
59 | 60 | ||
60 | static void free_layer(struct idr *idp, struct idr_layer *p) | 61 | static void free_layer(struct idr *idp, struct idr_layer *p) |
61 | { | 62 | { |
63 | unsigned long flags; | ||
64 | |||
62 | /* | 65 | /* |
63 | * Depends on the return element being zeroed. | 66 | * Depends on the return element being zeroed. |
64 | */ | 67 | */ |
65 | spin_lock(&idp->lock); | 68 | spin_lock_irqsave(&idp->lock, flags); |
66 | __free_layer(idp, p); | 69 | __free_layer(idp, p); |
67 | spin_unlock(&idp->lock); | 70 | spin_unlock_irqrestore(&idp->lock, flags); |
68 | } | 71 | } |
69 | 72 | ||
70 | /** | 73 | /** |
@@ -168,6 +171,7 @@ static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) | |||
168 | { | 171 | { |
169 | struct idr_layer *p, *new; | 172 | struct idr_layer *p, *new; |
170 | int layers, v, id; | 173 | int layers, v, id; |
174 | unsigned long flags; | ||
171 | 175 | ||
172 | id = starting_id; | 176 | id = starting_id; |
173 | build_up: | 177 | build_up: |
@@ -191,14 +195,14 @@ build_up: | |||
191 | * The allocation failed. If we built part of | 195 | * The allocation failed. If we built part of |
192 | * the structure tear it down. | 196 | * the structure tear it down. |
193 | */ | 197 | */ |
194 | spin_lock(&idp->lock); | 198 | spin_lock_irqsave(&idp->lock, flags); |
195 | for (new = p; p && p != idp->top; new = p) { | 199 | for (new = p; p && p != idp->top; new = p) { |
196 | p = p->ary[0]; | 200 | p = p->ary[0]; |
197 | new->ary[0] = NULL; | 201 | new->ary[0] = NULL; |
198 | new->bitmap = new->count = 0; | 202 | new->bitmap = new->count = 0; |
199 | __free_layer(idp, new); | 203 | __free_layer(idp, new); |
200 | } | 204 | } |
201 | spin_unlock(&idp->lock); | 205 | spin_unlock_irqrestore(&idp->lock, flags); |
202 | return -1; | 206 | return -1; |
203 | } | 207 | } |
204 | new->ary[0] = p; | 208 | new->ary[0] = p; |
diff --git a/mm/memory.c b/mm/memory.c index dc0d82cf2a1c..109e9866237e 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/pagemap.h> | 47 | #include <linux/pagemap.h> |
48 | #include <linux/rmap.h> | 48 | #include <linux/rmap.h> |
49 | #include <linux/module.h> | 49 | #include <linux/module.h> |
50 | #include <linux/delayacct.h> | ||
50 | #include <linux/init.h> | 51 | #include <linux/init.h> |
51 | 52 | ||
52 | #include <asm/pgalloc.h> | 53 | #include <asm/pgalloc.h> |
@@ -1549,9 +1550,9 @@ gotten: | |||
1549 | flush_cache_page(vma, address, pte_pfn(orig_pte)); | 1550 | flush_cache_page(vma, address, pte_pfn(orig_pte)); |
1550 | entry = mk_pte(new_page, vma->vm_page_prot); | 1551 | entry = mk_pte(new_page, vma->vm_page_prot); |
1551 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); | 1552 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); |
1553 | lazy_mmu_prot_update(entry); | ||
1552 | ptep_establish(vma, address, page_table, entry); | 1554 | ptep_establish(vma, address, page_table, entry); |
1553 | update_mmu_cache(vma, address, entry); | 1555 | update_mmu_cache(vma, address, entry); |
1554 | lazy_mmu_prot_update(entry); | ||
1555 | lru_cache_add_active(new_page); | 1556 | lru_cache_add_active(new_page); |
1556 | page_add_new_anon_rmap(new_page, vma, address); | 1557 | page_add_new_anon_rmap(new_page, vma, address); |
1557 | 1558 | ||
@@ -1934,6 +1935,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1934 | migration_entry_wait(mm, pmd, address); | 1935 | migration_entry_wait(mm, pmd, address); |
1935 | goto out; | 1936 | goto out; |
1936 | } | 1937 | } |
1938 | delayacct_set_flag(DELAYACCT_PF_SWAPIN); | ||
1937 | page = lookup_swap_cache(entry); | 1939 | page = lookup_swap_cache(entry); |
1938 | if (!page) { | 1940 | if (!page) { |
1939 | swapin_readahead(entry, address, vma); | 1941 | swapin_readahead(entry, address, vma); |
@@ -1946,6 +1948,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1946 | page_table = pte_offset_map_lock(mm, pmd, address, &ptl); | 1948 | page_table = pte_offset_map_lock(mm, pmd, address, &ptl); |
1947 | if (likely(pte_same(*page_table, orig_pte))) | 1949 | if (likely(pte_same(*page_table, orig_pte))) |
1948 | ret = VM_FAULT_OOM; | 1950 | ret = VM_FAULT_OOM; |
1951 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); | ||
1949 | goto unlock; | 1952 | goto unlock; |
1950 | } | 1953 | } |
1951 | 1954 | ||
@@ -1955,6 +1958,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1955 | grab_swap_token(); | 1958 | grab_swap_token(); |
1956 | } | 1959 | } |
1957 | 1960 | ||
1961 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); | ||
1958 | mark_page_accessed(page); | 1962 | mark_page_accessed(page); |
1959 | lock_page(page); | 1963 | lock_page(page); |
1960 | 1964 | ||
diff --git a/mm/nommu.c b/mm/nommu.c index 5151c44a8257..c576df71e3bb 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -1070,6 +1070,7 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, | |||
1070 | vma->vm_start = vma->vm_pgoff << PAGE_SHIFT; | 1070 | vma->vm_start = vma->vm_pgoff << PAGE_SHIFT; |
1071 | return 0; | 1071 | return 0; |
1072 | } | 1072 | } |
1073 | EXPORT_SYMBOL(remap_pfn_range); | ||
1073 | 1074 | ||
1074 | void swap_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) | 1075 | void swap_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) |
1075 | { | 1076 | { |
@@ -1090,6 +1091,7 @@ void unmap_mapping_range(struct address_space *mapping, | |||
1090 | int even_cows) | 1091 | int even_cows) |
1091 | { | 1092 | { |
1092 | } | 1093 | } |
1094 | EXPORT_SYMBOL(unmap_mapping_range); | ||
1093 | 1095 | ||
1094 | /* | 1096 | /* |
1095 | * Check that a process has enough memory to allocate a new virtual | 1097 | * Check that a process has enough memory to allocate a new virtual |
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 7b450798b458..266162d2ba28 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -340,7 +340,7 @@ void __vunmap(void *addr, int deallocate_pages) | |||
340 | __free_page(area->pages[i]); | 340 | __free_page(area->pages[i]); |
341 | } | 341 | } |
342 | 342 | ||
343 | if (area->nr_pages > PAGE_SIZE/sizeof(struct page *)) | 343 | if (area->flags & VM_VPAGES) |
344 | vfree(area->pages); | 344 | vfree(area->pages); |
345 | else | 345 | else |
346 | kfree(area->pages); | 346 | kfree(area->pages); |
@@ -427,9 +427,10 @@ void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, | |||
427 | 427 | ||
428 | area->nr_pages = nr_pages; | 428 | area->nr_pages = nr_pages; |
429 | /* Please note that the recursion is strictly bounded. */ | 429 | /* Please note that the recursion is strictly bounded. */ |
430 | if (array_size > PAGE_SIZE) | 430 | if (array_size > PAGE_SIZE) { |
431 | pages = __vmalloc_node(array_size, gfp_mask, PAGE_KERNEL, node); | 431 | pages = __vmalloc_node(array_size, gfp_mask, PAGE_KERNEL, node); |
432 | else | 432 | area->flags |= VM_VPAGES; |
433 | } else | ||
433 | pages = kmalloc_node(array_size, (gfp_mask & ~__GFP_HIGHMEM), node); | 434 | pages = kmalloc_node(array_size, (gfp_mask & ~__GFP_HIGHMEM), node); |
434 | area->pages = pages; | 435 | area->pages = pages; |
435 | if (!area->pages) { | 436 | if (!area->pages) { |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 44f6a181a754..476aa3978504 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -257,11 +257,11 @@ nodata: | |||
257 | } | 257 | } |
258 | 258 | ||
259 | 259 | ||
260 | static void skb_drop_fraglist(struct sk_buff *skb) | 260 | static void skb_drop_list(struct sk_buff **listp) |
261 | { | 261 | { |
262 | struct sk_buff *list = skb_shinfo(skb)->frag_list; | 262 | struct sk_buff *list = *listp; |
263 | 263 | ||
264 | skb_shinfo(skb)->frag_list = NULL; | 264 | *listp = NULL; |
265 | 265 | ||
266 | do { | 266 | do { |
267 | struct sk_buff *this = list; | 267 | struct sk_buff *this = list; |
@@ -270,6 +270,11 @@ static void skb_drop_fraglist(struct sk_buff *skb) | |||
270 | } while (list); | 270 | } while (list); |
271 | } | 271 | } |
272 | 272 | ||
273 | static inline void skb_drop_fraglist(struct sk_buff *skb) | ||
274 | { | ||
275 | skb_drop_list(&skb_shinfo(skb)->frag_list); | ||
276 | } | ||
277 | |||
273 | static void skb_clone_fraglist(struct sk_buff *skb) | 278 | static void skb_clone_fraglist(struct sk_buff *skb) |
274 | { | 279 | { |
275 | struct sk_buff *list; | 280 | struct sk_buff *list; |
@@ -830,41 +835,75 @@ free_skb: | |||
830 | 835 | ||
831 | int ___pskb_trim(struct sk_buff *skb, unsigned int len) | 836 | int ___pskb_trim(struct sk_buff *skb, unsigned int len) |
832 | { | 837 | { |
838 | struct sk_buff **fragp; | ||
839 | struct sk_buff *frag; | ||
833 | int offset = skb_headlen(skb); | 840 | int offset = skb_headlen(skb); |
834 | int nfrags = skb_shinfo(skb)->nr_frags; | 841 | int nfrags = skb_shinfo(skb)->nr_frags; |
835 | int i; | 842 | int i; |
843 | int err; | ||
844 | |||
845 | if (skb_cloned(skb) && | ||
846 | unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))) | ||
847 | return err; | ||
836 | 848 | ||
837 | for (i = 0; i < nfrags; i++) { | 849 | for (i = 0; i < nfrags; i++) { |
838 | int end = offset + skb_shinfo(skb)->frags[i].size; | 850 | int end = offset + skb_shinfo(skb)->frags[i].size; |
839 | if (end > len) { | 851 | |
840 | if (skb_cloned(skb)) { | 852 | if (end < len) { |
841 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | 853 | offset = end; |
842 | return -ENOMEM; | 854 | continue; |
843 | } | ||
844 | if (len <= offset) { | ||
845 | put_page(skb_shinfo(skb)->frags[i].page); | ||
846 | skb_shinfo(skb)->nr_frags--; | ||
847 | } else { | ||
848 | skb_shinfo(skb)->frags[i].size = len - offset; | ||
849 | } | ||
850 | } | 855 | } |
851 | offset = end; | 856 | |
857 | if (len > offset) | ||
858 | skb_shinfo(skb)->frags[i++].size = len - offset; | ||
859 | |||
860 | skb_shinfo(skb)->nr_frags = i; | ||
861 | |||
862 | for (; i < nfrags; i++) | ||
863 | put_page(skb_shinfo(skb)->frags[i].page); | ||
864 | |||
865 | if (skb_shinfo(skb)->frag_list) | ||
866 | skb_drop_fraglist(skb); | ||
867 | break; | ||
852 | } | 868 | } |
853 | 869 | ||
854 | if (offset < len) { | 870 | for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp); |
871 | fragp = &frag->next) { | ||
872 | int end = offset + frag->len; | ||
873 | |||
874 | if (skb_shared(frag)) { | ||
875 | struct sk_buff *nfrag; | ||
876 | |||
877 | nfrag = skb_clone(frag, GFP_ATOMIC); | ||
878 | if (unlikely(!nfrag)) | ||
879 | return -ENOMEM; | ||
880 | |||
881 | nfrag->next = frag->next; | ||
882 | frag = nfrag; | ||
883 | *fragp = frag; | ||
884 | } | ||
885 | |||
886 | if (end < len) { | ||
887 | offset = end; | ||
888 | continue; | ||
889 | } | ||
890 | |||
891 | if (end > len && | ||
892 | unlikely((err = pskb_trim(frag, len - offset)))) | ||
893 | return err; | ||
894 | |||
895 | if (frag->next) | ||
896 | skb_drop_list(&frag->next); | ||
897 | break; | ||
898 | } | ||
899 | |||
900 | if (len > skb_headlen(skb)) { | ||
855 | skb->data_len -= skb->len - len; | 901 | skb->data_len -= skb->len - len; |
856 | skb->len = len; | 902 | skb->len = len; |
857 | } else { | 903 | } else { |
858 | if (len <= skb_headlen(skb)) { | 904 | skb->len = len; |
859 | skb->len = len; | 905 | skb->data_len = 0; |
860 | skb->data_len = 0; | 906 | skb->tail = skb->data + len; |
861 | skb->tail = skb->data + len; | ||
862 | if (skb_shinfo(skb)->frag_list && !skb_cloned(skb)) | ||
863 | skb_drop_fraglist(skb); | ||
864 | } else { | ||
865 | skb->data_len -= skb->len - len; | ||
866 | skb->len = len; | ||
867 | } | ||
868 | } | 907 | } |
869 | 908 | ||
870 | return 0; | 909 | return 0; |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index e1a7dba2fa8a..184c78ca79e6 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -428,6 +428,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, | |||
428 | goto drop; | 428 | goto drop; |
429 | } | 429 | } |
430 | 430 | ||
431 | /* Remove any debris in the socket control block */ | ||
432 | memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); | ||
433 | |||
431 | return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL, | 434 | return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL, |
432 | ip_rcv_finish); | 435 | ip_rcv_finish); |
433 | 436 | ||
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 34afe41fa2f3..cd0a973b1128 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -196,7 +196,7 @@ struct htb_class | |||
196 | struct qdisc_rate_table *rate; /* rate table of the class itself */ | 196 | struct qdisc_rate_table *rate; /* rate table of the class itself */ |
197 | struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */ | 197 | struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */ |
198 | long buffer,cbuffer; /* token bucket depth/rate */ | 198 | long buffer,cbuffer; /* token bucket depth/rate */ |
199 | long mbuffer; /* max wait time */ | 199 | psched_tdiff_t mbuffer; /* max wait time */ |
200 | long tokens,ctokens; /* current number of tokens */ | 200 | long tokens,ctokens; /* current number of tokens */ |
201 | psched_time_t t_c; /* checkpoint time */ | 201 | psched_time_t t_c; /* checkpoint time */ |
202 | }; | 202 | }; |
@@ -1601,7 +1601,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1601 | /* set class to be in HTB_CAN_SEND state */ | 1601 | /* set class to be in HTB_CAN_SEND state */ |
1602 | cl->tokens = hopt->buffer; | 1602 | cl->tokens = hopt->buffer; |
1603 | cl->ctokens = hopt->cbuffer; | 1603 | cl->ctokens = hopt->cbuffer; |
1604 | cl->mbuffer = 60000000; /* 1min */ | 1604 | cl->mbuffer = PSCHED_JIFFIE2US(HZ*60) /* 1min */ |
1605 | PSCHED_GET_TIME(cl->t_c); | 1605 | PSCHED_GET_TIME(cl->t_c); |
1606 | cl->cmode = HTB_CAN_SEND; | 1606 | cl->cmode = HTB_CAN_SEND; |
1607 | 1607 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2e8b4dfcbc74..a91c961ba38b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -523,12 +523,16 @@ static int try_context_mount(struct super_block *sb, void *data) | |||
523 | goto out_free; | 523 | goto out_free; |
524 | } | 524 | } |
525 | 525 | ||
526 | rc = may_context_mount_sb_relabel(sid, sbsec, tsec); | 526 | if (!fscontext) { |
527 | if (rc) | 527 | rc = may_context_mount_sb_relabel(sid, sbsec, tsec); |
528 | goto out_free; | 528 | if (rc) |
529 | 529 | goto out_free; | |
530 | if (!fscontext) | ||
531 | sbsec->sid = sid; | 530 | sbsec->sid = sid; |
531 | } else { | ||
532 | rc = may_context_mount_inode_relabel(sid, sbsec, tsec); | ||
533 | if (rc) | ||
534 | goto out_free; | ||
535 | } | ||
532 | sbsec->mntpoint_sid = sid; | 536 | sbsec->mntpoint_sid = sid; |
533 | 537 | ||
534 | sbsec->behavior = SECURITY_FS_USE_MNTPOINT; | 538 | sbsec->behavior = SECURITY_FS_USE_MNTPOINT; |