diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-22 19:23:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-22 19:23:04 -0400 |
commit | e53897e2fb48526a62116ef8e72d7441d5ee8752 (patch) | |
tree | ecbcf922d84829386fbf72244357bb2b38b36f7e | |
parent | 3fd07d3bf0077dcc0f5a33d2eb1938ea050da8da (diff) | |
parent | 4881e2cd25d2d9cf9fca263caff3a0ce732d7d6b (diff) |
Merge branch 'release' of master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6
-rw-r--r-- | arch/ia64/hp/sim/simscsi.c | 29 | ||||
-rw-r--r-- | arch/ia64/kernel/mca_asm.S | 96 | ||||
-rw-r--r-- | arch/ia64/kernel/mca_drv.c | 21 | ||||
-rw-r--r-- | include/asm-ia64/mca.h | 5 |
4 files changed, 128 insertions, 23 deletions
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c index 56405dbfd739..a18983a3c934 100644 --- a/arch/ia64/hp/sim/simscsi.c +++ b/arch/ia64/hp/sim/simscsi.c | |||
@@ -233,6 +233,23 @@ simscsi_readwrite10 (struct scsi_cmnd *sc, int mode) | |||
233 | simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512); | 233 | simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512); |
234 | } | 234 | } |
235 | 235 | ||
236 | static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len) | ||
237 | { | ||
238 | |||
239 | int scatterlen = sc->use_sg; | ||
240 | struct scatterlist *slp; | ||
241 | |||
242 | if (scatterlen == 0) | ||
243 | memcpy(sc->request_buffer, buf, len); | ||
244 | else for (slp = (struct scatterlist *)sc->buffer; scatterlen-- > 0 && len > 0; slp++) { | ||
245 | unsigned thislen = min(len, slp->length); | ||
246 | |||
247 | memcpy(page_address(slp->page) + slp->offset, buf, thislen); | ||
248 | slp++; | ||
249 | len -= thislen; | ||
250 | } | ||
251 | } | ||
252 | |||
236 | static int | 253 | static int |
237 | simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | 254 | simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) |
238 | { | 255 | { |
@@ -240,6 +257,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
240 | char fname[MAX_ROOT_LEN+16]; | 257 | char fname[MAX_ROOT_LEN+16]; |
241 | size_t disk_size; | 258 | size_t disk_size; |
242 | char *buf; | 259 | char *buf; |
260 | char localbuf[36]; | ||
243 | #if DEBUG_SIMSCSI | 261 | #if DEBUG_SIMSCSI |
244 | register long sp asm ("sp"); | 262 | register long sp asm ("sp"); |
245 | 263 | ||
@@ -263,7 +281,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
263 | /* disk doesn't exist... */ | 281 | /* disk doesn't exist... */ |
264 | break; | 282 | break; |
265 | } | 283 | } |
266 | buf = sc->request_buffer; | 284 | buf = localbuf; |
267 | buf[0] = 0; /* magnetic disk */ | 285 | buf[0] = 0; /* magnetic disk */ |
268 | buf[1] = 0; /* not a removable medium */ | 286 | buf[1] = 0; /* not a removable medium */ |
269 | buf[2] = 2; /* SCSI-2 compliant device */ | 287 | buf[2] = 2; /* SCSI-2 compliant device */ |
@@ -273,6 +291,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
273 | buf[6] = 0; /* reserved */ | 291 | buf[6] = 0; /* reserved */ |
274 | buf[7] = 0; /* various flags */ | 292 | buf[7] = 0; /* various flags */ |
275 | memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28); | 293 | memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28); |
294 | simscsi_fillresult(sc, buf, 36); | ||
276 | sc->result = GOOD; | 295 | sc->result = GOOD; |
277 | break; | 296 | break; |
278 | 297 | ||
@@ -304,16 +323,13 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
304 | simscsi_readwrite10(sc, SSC_WRITE); | 323 | simscsi_readwrite10(sc, SSC_WRITE); |
305 | break; | 324 | break; |
306 | 325 | ||
307 | |||
308 | case READ_CAPACITY: | 326 | case READ_CAPACITY: |
309 | if (desc[target_id] < 0 || sc->request_bufflen < 8) { | 327 | if (desc[target_id] < 0 || sc->request_bufflen < 8) { |
310 | break; | 328 | break; |
311 | } | 329 | } |
312 | buf = sc->request_buffer; | 330 | buf = localbuf; |
313 | |||
314 | disk_size = simscsi_get_disk_size(desc[target_id]); | 331 | disk_size = simscsi_get_disk_size(desc[target_id]); |
315 | 332 | ||
316 | /* pretend to be a 1GB disk (partition table contains real stuff): */ | ||
317 | buf[0] = (disk_size >> 24) & 0xff; | 333 | buf[0] = (disk_size >> 24) & 0xff; |
318 | buf[1] = (disk_size >> 16) & 0xff; | 334 | buf[1] = (disk_size >> 16) & 0xff; |
319 | buf[2] = (disk_size >> 8) & 0xff; | 335 | buf[2] = (disk_size >> 8) & 0xff; |
@@ -323,13 +339,14 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
323 | buf[5] = 0; | 339 | buf[5] = 0; |
324 | buf[6] = 2; | 340 | buf[6] = 2; |
325 | buf[7] = 0; | 341 | buf[7] = 0; |
342 | simscsi_fillresult(sc, buf, 8); | ||
326 | sc->result = GOOD; | 343 | sc->result = GOOD; |
327 | break; | 344 | break; |
328 | 345 | ||
329 | case MODE_SENSE: | 346 | case MODE_SENSE: |
330 | case MODE_SENSE_10: | 347 | case MODE_SENSE_10: |
331 | /* sd.c uses this to determine whether disk does write-caching. */ | 348 | /* sd.c uses this to determine whether disk does write-caching. */ |
332 | memset(sc->request_buffer, 0, 128); | 349 | simscsi_fillresult(sc, (char *)empty_zero_page, sc->request_bufflen); |
333 | sc->result = GOOD; | 350 | sc->result = GOOD; |
334 | break; | 351 | break; |
335 | 352 | ||
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index 499a065f4e60..db32fc1d3935 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S | |||
@@ -489,24 +489,27 @@ ia64_state_save: | |||
489 | ;; | 489 | ;; |
490 | st8 [temp1]=r17,16 // pal_min_state | 490 | st8 [temp1]=r17,16 // pal_min_state |
491 | st8 [temp2]=r6,16 // prev_IA64_KR_CURRENT | 491 | st8 [temp2]=r6,16 // prev_IA64_KR_CURRENT |
492 | mov r6=IA64_KR(CURRENT_STACK) | ||
493 | ;; | ||
494 | st8 [temp1]=r6,16 // prev_IA64_KR_CURRENT_STACK | ||
495 | st8 [temp2]=r0,16 // prev_task, starts off as NULL | ||
492 | mov r6=cr.ifa | 496 | mov r6=cr.ifa |
493 | ;; | 497 | ;; |
494 | st8 [temp1]=r0,16 // prev_task, starts off as NULL | 498 | st8 [temp1]=r12,16 // cr.isr |
495 | st8 [temp2]=r12,16 // cr.isr | 499 | st8 [temp2]=r6,16 // cr.ifa |
496 | mov r12=cr.itir | 500 | mov r12=cr.itir |
497 | ;; | 501 | ;; |
498 | st8 [temp1]=r6,16 // cr.ifa | 502 | st8 [temp1]=r12,16 // cr.itir |
499 | st8 [temp2]=r12,16 // cr.itir | 503 | st8 [temp2]=r11,16 // cr.iipa |
500 | mov r12=cr.iim | 504 | mov r12=cr.iim |
501 | ;; | 505 | ;; |
502 | st8 [temp1]=r11,16 // cr.iipa | 506 | st8 [temp1]=r12,16 // cr.iim |
503 | st8 [temp2]=r12,16 // cr.iim | ||
504 | mov r6=cr.iha | ||
505 | (p1) mov r12=IA64_MCA_COLD_BOOT | 507 | (p1) mov r12=IA64_MCA_COLD_BOOT |
506 | (p2) mov r12=IA64_INIT_WARM_BOOT | 508 | (p2) mov r12=IA64_INIT_WARM_BOOT |
509 | mov r6=cr.iha | ||
507 | ;; | 510 | ;; |
508 | st8 [temp1]=r6,16 // cr.iha | 511 | st8 [temp2]=r6,16 // cr.iha |
509 | st8 [temp2]=r12 // os_status, default is cold boot | 512 | st8 [temp1]=r12 // os_status, default is cold boot |
510 | mov r6=IA64_MCA_SAME_CONTEXT | 513 | mov r6=IA64_MCA_SAME_CONTEXT |
511 | ;; | 514 | ;; |
512 | st8 [temp1]=r6 // context, default is same context | 515 | st8 [temp1]=r6 // context, default is same context |
@@ -823,9 +826,12 @@ ia64_state_restore: | |||
823 | ld8 r12=[temp1],16 // sal_ra | 826 | ld8 r12=[temp1],16 // sal_ra |
824 | ld8 r9=[temp2],16 // sal_gp | 827 | ld8 r9=[temp2],16 // sal_gp |
825 | ;; | 828 | ;; |
826 | ld8 r22=[temp1],24 // pal_min_state, virtual. skip prev_task | 829 | ld8 r22=[temp1],16 // pal_min_state, virtual |
827 | ld8 r21=[temp2],16 // prev_IA64_KR_CURRENT | 830 | ld8 r21=[temp2],16 // prev_IA64_KR_CURRENT |
828 | ;; | 831 | ;; |
832 | ld8 r16=[temp1],16 // prev_IA64_KR_CURRENT_STACK | ||
833 | ld8 r20=[temp2],16 // prev_task | ||
834 | ;; | ||
829 | ld8 temp3=[temp1],16 // cr.isr | 835 | ld8 temp3=[temp1],16 // cr.isr |
830 | ld8 temp4=[temp2],16 // cr.ifa | 836 | ld8 temp4=[temp2],16 // cr.ifa |
831 | ;; | 837 | ;; |
@@ -846,6 +852,45 @@ ia64_state_restore: | |||
846 | ld8 r8=[temp1] // os_status | 852 | ld8 r8=[temp1] // os_status |
847 | ld8 r10=[temp2] // context | 853 | ld8 r10=[temp2] // context |
848 | 854 | ||
855 | /* Wire IA64_TR_CURRENT_STACK to the stack that we are resuming to. To | ||
856 | * avoid any dependencies on the algorithm in ia64_switch_to(), just | ||
857 | * purge any existing CURRENT_STACK mapping and insert the new one. | ||
858 | * | ||
859 | * r16 contains prev_IA64_KR_CURRENT_STACK, r21 contains | ||
860 | * prev_IA64_KR_CURRENT, these values may have been changed by the C | ||
861 | * code. Do not use r8, r9, r10, r22, they contain values ready for | ||
862 | * the return to SAL. | ||
863 | */ | ||
864 | |||
865 | mov r15=IA64_KR(CURRENT_STACK) // physical granule mapped by IA64_TR_CURRENT_STACK | ||
866 | ;; | ||
867 | shl r15=r15,IA64_GRANULE_SHIFT | ||
868 | ;; | ||
869 | dep r15=-1,r15,61,3 // virtual granule | ||
870 | mov r18=IA64_GRANULE_SHIFT<<2 // for cr.itir.ps | ||
871 | ;; | ||
872 | ptr.d r15,r18 | ||
873 | ;; | ||
874 | srlz.d | ||
875 | |||
876 | extr.u r19=r21,61,3 // r21 = prev_IA64_KR_CURRENT | ||
877 | shl r20=r16,IA64_GRANULE_SHIFT // r16 = prev_IA64_KR_CURRENT_STACK | ||
878 | movl r21=PAGE_KERNEL // page properties | ||
879 | ;; | ||
880 | mov IA64_KR(CURRENT_STACK)=r16 | ||
881 | cmp.ne p6,p0=RGN_KERNEL,r19 // new stack is in the kernel region? | ||
882 | or r21=r20,r21 // construct PA | page properties | ||
883 | (p6) br.spnt 1f // the dreaded cpu 0 idle task in region 5:( | ||
884 | ;; | ||
885 | mov cr.itir=r18 | ||
886 | mov cr.ifa=r21 | ||
887 | mov r20=IA64_TR_CURRENT_STACK | ||
888 | ;; | ||
889 | itr.d dtr[r20]=r21 | ||
890 | ;; | ||
891 | srlz.d | ||
892 | 1: | ||
893 | |||
849 | br.sptk b0 | 894 | br.sptk b0 |
850 | 895 | ||
851 | //EndStub////////////////////////////////////////////////////////////////////// | 896 | //EndStub////////////////////////////////////////////////////////////////////// |
@@ -982,6 +1027,7 @@ ia64_set_kernel_registers: | |||
982 | add temp4=temp4, temp1 // &struct ia64_sal_os_state.os_gp | 1027 | add temp4=temp4, temp1 // &struct ia64_sal_os_state.os_gp |
983 | add r12=temp1, temp3 // kernel stack pointer on MCA/INIT stack | 1028 | add r12=temp1, temp3 // kernel stack pointer on MCA/INIT stack |
984 | add r13=temp1, r3 // set current to start of MCA/INIT stack | 1029 | add r13=temp1, r3 // set current to start of MCA/INIT stack |
1030 | add r20=temp1, r3 // physical start of MCA/INIT stack | ||
985 | ;; | 1031 | ;; |
986 | ld8 r1=[temp4] // OS GP from SAL OS state | 1032 | ld8 r1=[temp4] // OS GP from SAL OS state |
987 | ;; | 1033 | ;; |
@@ -991,7 +1037,35 @@ ia64_set_kernel_registers: | |||
991 | ;; | 1037 | ;; |
992 | mov IA64_KR(CURRENT)=r13 | 1038 | mov IA64_KR(CURRENT)=r13 |
993 | 1039 | ||
994 | // FIXME: do I need to wire IA64_KR_CURRENT_STACK and IA64_TR_CURRENT_STACK? | 1040 | /* Wire IA64_TR_CURRENT_STACK to the MCA/INIT handler stack. To avoid |
1041 | * any dependencies on the algorithm in ia64_switch_to(), just purge | ||
1042 | * any existing CURRENT_STACK mapping and insert the new one. | ||
1043 | */ | ||
1044 | |||
1045 | mov r16=IA64_KR(CURRENT_STACK) // physical granule mapped by IA64_TR_CURRENT_STACK | ||
1046 | ;; | ||
1047 | shl r16=r16,IA64_GRANULE_SHIFT | ||
1048 | ;; | ||
1049 | dep r16=-1,r16,61,3 // virtual granule | ||
1050 | mov r18=IA64_GRANULE_SHIFT<<2 // for cr.itir.ps | ||
1051 | ;; | ||
1052 | ptr.d r16,r18 | ||
1053 | ;; | ||
1054 | srlz.d | ||
1055 | |||
1056 | shr.u r16=r20,IA64_GRANULE_SHIFT // r20 = physical start of MCA/INIT stack | ||
1057 | movl r21=PAGE_KERNEL // page properties | ||
1058 | ;; | ||
1059 | mov IA64_KR(CURRENT_STACK)=r16 | ||
1060 | or r21=r20,r21 // construct PA | page properties | ||
1061 | ;; | ||
1062 | mov cr.itir=r18 | ||
1063 | mov cr.ifa=r13 | ||
1064 | mov r20=IA64_TR_CURRENT_STACK | ||
1065 | ;; | ||
1066 | itr.d dtr[r20]=r21 | ||
1067 | ;; | ||
1068 | srlz.d | ||
995 | 1069 | ||
996 | br.sptk b0 | 1070 | br.sptk b0 |
997 | 1071 | ||
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index 80f83d6cdbfc..f081c60ab206 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c | |||
@@ -56,8 +56,9 @@ static struct page *page_isolate[MAX_PAGE_ISOLATE]; | |||
56 | static int num_page_isolate = 0; | 56 | static int num_page_isolate = 0; |
57 | 57 | ||
58 | typedef enum { | 58 | typedef enum { |
59 | ISOLATE_NG = 0, | 59 | ISOLATE_NG, |
60 | ISOLATE_OK = 1 | 60 | ISOLATE_OK, |
61 | ISOLATE_NONE | ||
61 | } isolate_status_t; | 62 | } isolate_status_t; |
62 | 63 | ||
63 | /* | 64 | /* |
@@ -74,7 +75,7 @@ static struct { | |||
74 | * @paddr: poisoned memory location | 75 | * @paddr: poisoned memory location |
75 | * | 76 | * |
76 | * Return value: | 77 | * Return value: |
77 | * ISOLATE_OK / ISOLATE_NG | 78 | * one of isolate_status_t, ISOLATE_OK/NG/NONE. |
78 | */ | 79 | */ |
79 | 80 | ||
80 | static isolate_status_t | 81 | static isolate_status_t |
@@ -85,7 +86,10 @@ mca_page_isolate(unsigned long paddr) | |||
85 | 86 | ||
86 | /* whether physical address is valid or not */ | 87 | /* whether physical address is valid or not */ |
87 | if (!ia64_phys_addr_valid(paddr)) | 88 | if (!ia64_phys_addr_valid(paddr)) |
88 | return ISOLATE_NG; | 89 | return ISOLATE_NONE; |
90 | |||
91 | if (!pfn_valid(paddr)) | ||
92 | return ISOLATE_NONE; | ||
89 | 93 | ||
90 | /* convert physical address to physical page number */ | 94 | /* convert physical address to physical page number */ |
91 | p = pfn_to_page(paddr>>PAGE_SHIFT); | 95 | p = pfn_to_page(paddr>>PAGE_SHIFT); |
@@ -122,10 +126,15 @@ mca_handler_bh(unsigned long paddr) | |||
122 | current->pid, current->comm); | 126 | current->pid, current->comm); |
123 | 127 | ||
124 | spin_lock(&mca_bh_lock); | 128 | spin_lock(&mca_bh_lock); |
125 | if (mca_page_isolate(paddr) == ISOLATE_OK) { | 129 | switch (mca_page_isolate(paddr)) { |
130 | case ISOLATE_OK: | ||
126 | printk(KERN_DEBUG "Page isolation: ( %lx ) success.\n", paddr); | 131 | printk(KERN_DEBUG "Page isolation: ( %lx ) success.\n", paddr); |
127 | } else { | 132 | break; |
133 | case ISOLATE_NG: | ||
128 | printk(KERN_DEBUG "Page isolation: ( %lx ) failure.\n", paddr); | 134 | printk(KERN_DEBUG "Page isolation: ( %lx ) failure.\n", paddr); |
135 | break; | ||
136 | default: | ||
137 | break; | ||
129 | } | 138 | } |
130 | spin_unlock(&mca_bh_lock); | 139 | spin_unlock(&mca_bh_lock); |
131 | 140 | ||
diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h index 97a28b8b2ddd..c7d9c9ed38ba 100644 --- a/include/asm-ia64/mca.h +++ b/include/asm-ia64/mca.h | |||
@@ -80,7 +80,12 @@ struct ia64_sal_os_state { | |||
80 | u64 sal_ra; /* Return address in SAL, physical */ | 80 | u64 sal_ra; /* Return address in SAL, physical */ |
81 | u64 sal_gp; /* GP of the SAL - physical */ | 81 | u64 sal_gp; /* GP of the SAL - physical */ |
82 | pal_min_state_area_t *pal_min_state; /* from R17. physical in asm, virtual in C */ | 82 | pal_min_state_area_t *pal_min_state; /* from R17. physical in asm, virtual in C */ |
83 | /* Previous values of IA64_KR(CURRENT) and IA64_KR(CURRENT_STACK). | ||
84 | * Note: if the MCA/INIT recovery code wants to resume to a new context | ||
85 | * then it must change these values to reflect the new kernel stack. | ||
86 | */ | ||
83 | u64 prev_IA64_KR_CURRENT; /* previous value of IA64_KR(CURRENT) */ | 87 | u64 prev_IA64_KR_CURRENT; /* previous value of IA64_KR(CURRENT) */ |
88 | u64 prev_IA64_KR_CURRENT_STACK; | ||
84 | struct task_struct *prev_task; /* previous task, NULL if it is not useful */ | 89 | struct task_struct *prev_task; /* previous task, NULL if it is not useful */ |
85 | /* Some interrupt registers are not saved in minstate, pt_regs or | 90 | /* Some interrupt registers are not saved in minstate, pt_regs or |
86 | * switch_stack. Because MCA/INIT can occur when interrupts are | 91 | * switch_stack. Because MCA/INIT can occur when interrupts are |