Skip to content

Commit

Permalink
[IA64] SAL to OS callbacks cannot call sleeping
Browse files Browse the repository at this point in the history
When SAL calls back into the OS, the OS code is running with preempt
disabled so it cannot call sleeping functions.

Signed-off-by: Keith Owens <kaos@sgi.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
  • Loading branch information
Keith Owens authored and Tony Luck committed May 3, 2005
1 parent b1b901c commit 32709d8
Showing 1 changed file with 21 additions and 13 deletions.
34 changes: 21 additions & 13 deletions arch/ia64/sn/kernel/mca.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ static u64 *sn_oemdata_size, sn_oemdata_bufsize;
* This function is the callback routine that SAL calls to log error
* info for platform errors. buf is appended to sn_oemdata, resizing as
* required.
* Note: this is a SAL to OS callback, running under the same rules as the SAL
* code. SAL calls are run with preempt disabled so this routine must not
* sleep. vmalloc can sleep so print_hook cannot resize the output buffer
* itself, instead it must set the required size and return to let the caller
* resize the buffer then redrive the SAL call.
*/
static int print_hook(const char *fmt, ...)
{
Expand All @@ -47,18 +52,8 @@ static int print_hook(const char *fmt, ...)
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
len = strlen(buf);
while (*sn_oemdata_size + len + 1 > sn_oemdata_bufsize) {
u8 *newbuf = vmalloc(sn_oemdata_bufsize += 1000);
if (!newbuf) {
printk(KERN_ERR "%s: unable to extend sn_oemdata\n",
__FUNCTION__);
return 0;
}
memcpy(newbuf, *sn_oemdata, *sn_oemdata_size);
vfree(*sn_oemdata);
*sn_oemdata = newbuf;
}
memcpy(*sn_oemdata + *sn_oemdata_size, buf, len + 1);
if (*sn_oemdata_size + len <= sn_oemdata_bufsize)
memcpy(*sn_oemdata + *sn_oemdata_size, buf, len);
*sn_oemdata_size += len;
return 0;
}
Expand Down Expand Up @@ -98,7 +93,20 @@ sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata,
sn_oemdata = oemdata;
sn_oemdata_size = oemdata_size;
sn_oemdata_bufsize = 0;
ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);
*sn_oemdata_size = PAGE_SIZE; /* first guess at how much data will be generated */
while (*sn_oemdata_size > sn_oemdata_bufsize) {
u8 *newbuf = vmalloc(*sn_oemdata_size);
if (!newbuf) {
printk(KERN_ERR "%s: unable to extend sn_oemdata\n",
__FUNCTION__);
return 1;
}
vfree(*sn_oemdata);
*sn_oemdata = newbuf;
sn_oemdata_bufsize = *sn_oemdata_size;
*sn_oemdata_size = 0;
ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);
}
up(&sn_oemdata_mutex);
return 0;
}
Expand Down

0 comments on commit 32709d8

Please sign in to comment.