]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
scsi: aacraid: use timespec64 instead of timeval
authorArnd Bergmann <arnd@arndb.de>
Tue, 7 Nov 2017 10:46:05 +0000 (11:46 +0100)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 8 Nov 2017 23:08:01 +0000 (18:08 -0500)
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: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Dave Carroll <david.carroll@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/aacraid/commsup.c

index dfe8e70f8d9968d8b3f2e251bc1639f8d26f562f..525a652dab48e9923af67ce6e884154855df308c 100644 (file)
@@ -2383,19 +2383,19 @@ static int aac_send_wellness_command(struct aac_dev *dev, char *wellness_str,
        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;
        char wellness_str[] = "<HW>TD\010\0\0\0\0\0\0\0\0\0DW\0\0ZZ";
        u32 datasize = sizeof(wellness_str);
-       unsigned long local_time;
+       time64_t local_time;
        int ret = -ENODEV;
 
        if (!dev->sa_firmware)
                goto out;
 
-       local_time = (u32)(now->tv_sec - (sys_tz.tz_minuteswest * 60));
-       time_to_tm(local_time, 0, &cur_tm);
+       local_time = (now->tv_sec - (sys_tz.tz_minuteswest * 60));
+       time64_to_tm(local_time, 0, &cur_tm);
        cur_tm.tm_mon += 1;
        cur_tm.tm_year += 1900;
        wellness_str[8] = bin2bcd(cur_tm.tm_hour);
@@ -2412,7 +2412,7 @@ int aac_send_safw_hostttime(struct aac_dev *dev, struct timeval *now)
        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;
        struct fib *fibptr;
@@ -2424,7 +2424,7 @@ int aac_send_hosttime(struct aac_dev *dev, struct timeval *now)
 
        aac_fib_init(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,
                                        1, 1, NULL, NULL);
 
@@ -2496,7 +2496,7 @@ int aac_command_thread(void *data)
                }
                if (!time_before(next_check_jiffies,next_jiffies)
                 && ((difference = next_jiffies - jiffies) <= 0)) {
-                       struct timeval now;
+                       struct timespec64 now;
                        int ret;
 
                        /* Don't even try to talk to adapter if its sick */
@@ -2506,15 +2506,15 @@ int aac_command_thread(void *data)
                        next_check_jiffies = jiffies
                                           + ((long)(unsigned)check_interval)
                                           * HZ;
-                       do_gettimeofday(&now);
+                       ktime_get_real_ts64(&now);
 
                        /* Synchronize our watches */
-                       if (((1000000 - (1000000 / HZ)) > now.tv_usec)
-                        && (now.tv_usec > (1000000 / HZ)))
-                               difference = (((1000000 - now.tv_usec) * HZ)
-                                 + 500000) / 1000000;
+                       if (((NSEC_PER_SEC - (NSEC_PER_SEC / HZ)) > now.tv_nsec)
+                        && (now.tv_nsec > (NSEC_PER_SEC / HZ)))
+                               difference = (((NSEC_PER_SEC - now.tv_nsec) * HZ)
+                                 + NSEC_PER_SEC / 2) / NSEC_PER_SEC;
                        else {
-                               if (now.tv_usec > 500000)
+                               if (now.tv_nsec > NSEC_PER_SEC / 2)
                                        ++now.tv_sec;
 
                                if (dev->sa_firmware)