Commit 820f1886 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Martin K. Petersen

scsi: aacraid: use timespec64 instead of timeval

aacraid passes the current time to the firmware in one of two ways,
either as year/month/day/... or as 32-bit unsigned seconds.

The first one is broken on 32-bit architectures as it cannot go past
year 2038. Using timespec64 here makes it behave properly on both 32-bit
and 64-bit architectures, and avoids relying on signed integer overflow
to pass times into the second interface.

The interface used in aac_send_hosttime() however is still problematic
in year 2106 when 32-bit seconds overflow. Hopefully we don't have to
worry about aacraid by that time.
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Reviewed-by: default avatarDave Carroll <david.carroll@microsemi.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 335f83b9
...@@ -2383,19 +2383,19 @@ static int aac_send_wellness_command(struct aac_dev *dev, char *wellness_str, ...@@ -2383,19 +2383,19 @@ static int aac_send_wellness_command(struct aac_dev *dev, char *wellness_str,
goto out; goto out;
} }
int aac_send_safw_hostttime(struct aac_dev *dev, struct timeval *now) int aac_send_safw_hostttime(struct aac_dev *dev, struct timespec64 *now)
{ {
struct tm cur_tm; struct tm cur_tm;
char wellness_str[] = "<HW>TD\010\0\0\0\0\0\0\0\0\0DW\0\0ZZ"; char wellness_str[] = "<HW>TD\010\0\0\0\0\0\0\0\0\0DW\0\0ZZ";
u32 datasize = sizeof(wellness_str); u32 datasize = sizeof(wellness_str);
unsigned long local_time; time64_t local_time;
int ret = -ENODEV; int ret = -ENODEV;
if (!dev->sa_firmware) if (!dev->sa_firmware)
goto out; goto out;
local_time = (u32)(now->tv_sec - (sys_tz.tz_minuteswest * 60)); local_time = (now->tv_sec - (sys_tz.tz_minuteswest * 60));
time_to_tm(local_time, 0, &cur_tm); time64_to_tm(local_time, 0, &cur_tm);
cur_tm.tm_mon += 1; cur_tm.tm_mon += 1;
cur_tm.tm_year += 1900; cur_tm.tm_year += 1900;
wellness_str[8] = bin2bcd(cur_tm.tm_hour); wellness_str[8] = bin2bcd(cur_tm.tm_hour);
...@@ -2412,7 +2412,7 @@ int aac_send_safw_hostttime(struct aac_dev *dev, struct timeval *now) ...@@ -2412,7 +2412,7 @@ int aac_send_safw_hostttime(struct aac_dev *dev, struct timeval *now)
return ret; return ret;
} }
int aac_send_hosttime(struct aac_dev *dev, struct timeval *now) int aac_send_hosttime(struct aac_dev *dev, struct timespec64 *now)
{ {
int ret = -ENOMEM; int ret = -ENOMEM;
struct fib *fibptr; struct fib *fibptr;
...@@ -2424,7 +2424,7 @@ int aac_send_hosttime(struct aac_dev *dev, struct timeval *now) ...@@ -2424,7 +2424,7 @@ int aac_send_hosttime(struct aac_dev *dev, struct timeval *now)
aac_fib_init(fibptr); aac_fib_init(fibptr);
info = (__le32 *)fib_data(fibptr); info = (__le32 *)fib_data(fibptr);
*info = cpu_to_le32(now->tv_sec); *info = cpu_to_le32(now->tv_sec); /* overflow in y2106 */
ret = aac_fib_send(SendHostTime, fibptr, sizeof(*info), FsaNormal, ret = aac_fib_send(SendHostTime, fibptr, sizeof(*info), FsaNormal,
1, 1, NULL, NULL); 1, 1, NULL, NULL);
...@@ -2496,7 +2496,7 @@ int aac_command_thread(void *data) ...@@ -2496,7 +2496,7 @@ int aac_command_thread(void *data)
} }
if (!time_before(next_check_jiffies,next_jiffies) if (!time_before(next_check_jiffies,next_jiffies)
&& ((difference = next_jiffies - jiffies) <= 0)) { && ((difference = next_jiffies - jiffies) <= 0)) {
struct timeval now; struct timespec64 now;
int ret; int ret;
/* Don't even try to talk to adapter if its sick */ /* Don't even try to talk to adapter if its sick */
...@@ -2506,15 +2506,15 @@ int aac_command_thread(void *data) ...@@ -2506,15 +2506,15 @@ int aac_command_thread(void *data)
next_check_jiffies = jiffies next_check_jiffies = jiffies
+ ((long)(unsigned)check_interval) + ((long)(unsigned)check_interval)
* HZ; * HZ;
do_gettimeofday(&now); ktime_get_real_ts64(&now);
/* Synchronize our watches */ /* Synchronize our watches */
if (((1000000 - (1000000 / HZ)) > now.tv_usec) if (((NSEC_PER_SEC - (NSEC_PER_SEC / HZ)) > now.tv_nsec)
&& (now.tv_usec > (1000000 / HZ))) && (now.tv_nsec > (NSEC_PER_SEC / HZ)))
difference = (((1000000 - now.tv_usec) * HZ) difference = (((NSEC_PER_SEC - now.tv_nsec) * HZ)
+ 500000) / 1000000; + NSEC_PER_SEC / 2) / NSEC_PER_SEC;
else { else {
if (now.tv_usec > 500000) if (now.tv_nsec > NSEC_PER_SEC / 2)
++now.tv_sec; ++now.tv_sec;
if (dev->sa_firmware) if (dev->sa_firmware)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment