#include <linux/kthread.h>
 #include <linux/interrupt.h>
 #include <linux/semaphore.h>
+#include <linux/bcd.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
        spin_unlock_irqrestore(t_lock, flags);
 }
 
+static int aac_send_wellness_command(struct aac_dev *dev, char *wellness_str,
+                                                       u32 datasize)
+{
+       struct aac_srb *srbcmd;
+       struct sgmap64 *sg64;
+       dma_addr_t addr;
+       char *dma_buf;
+       struct fib *fibptr;
+       int ret = -ENOMEM;
+       u32 vbus, vid;
+
+       fibptr = aac_fib_alloc(dev);
+       if (!fibptr)
+               goto out;
+
+       dma_buf = pci_alloc_consistent(dev->pdev, datasize, &addr);
+       if (!dma_buf)
+               goto fib_free_out;
+
+       aac_fib_init(fibptr);
+
+       vbus = (u32)le16_to_cpu(dev->supplement_adapter_info.VirtDeviceBus);
+       vid = (u32)le16_to_cpu(dev->supplement_adapter_info.VirtDeviceTarget);
+
+       srbcmd = (struct aac_srb *)fib_data(fibptr);
+
+       srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
+       srbcmd->channel = cpu_to_le32(vbus);
+       srbcmd->id = cpu_to_le32(vid);
+       srbcmd->lun = 0;
+       srbcmd->flags = cpu_to_le32(SRB_DataOut);
+       srbcmd->timeout = cpu_to_le32(10);
+       srbcmd->retry_limit = 0;
+       srbcmd->cdb_size = cpu_to_le32(12);
+       srbcmd->count = cpu_to_le32(datasize);
+
+       memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
+       srbcmd->cdb[0] = BMIC_OUT;
+       srbcmd->cdb[6] = WRITE_HOST_WELLNESS;
+       memcpy(dma_buf, (char *)wellness_str, datasize);
+
+       sg64 = (struct sgmap64 *)&srbcmd->sg;
+       sg64->count = cpu_to_le32(1);
+       sg64->sg[0].addr[1] = cpu_to_le32((u32)(((addr) >> 16) >> 16));
+       sg64->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
+       sg64->sg[0].count = cpu_to_le32(datasize);
+
+       ret = aac_fib_send(ScsiPortCommand64, fibptr, sizeof(struct aac_srb),
+                               FsaNormal, 1, 1, NULL, NULL);
+
+       pci_free_consistent(dev->pdev, datasize, (void *)dma_buf, addr);
+
+       /*
+        * Do not set XferState to zero unless
+        * receives a response from F/W
+        */
+       if (ret >= 0)
+               aac_fib_complete(fibptr);
+
+       /*
+        * FIB should be freed only after
+        * getting the response from the F/W
+        */
+       if (ret != -ERESTARTSYS)
+               goto fib_free_out;
+
+out:
+       return ret;
+fib_free_out:
+       aac_fib_free(fibptr);
+       goto out;
+}
+
+int aac_send_safw_hostttime(struct aac_dev *dev, struct timeval *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;
+       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);
+       cur_tm.tm_mon += 1;
+       cur_tm.tm_year += 1900;
+       wellness_str[8] = bin2bcd(cur_tm.tm_hour);
+       wellness_str[9] = bin2bcd(cur_tm.tm_min);
+       wellness_str[10] = bin2bcd(cur_tm.tm_sec);
+       wellness_str[12] = bin2bcd(cur_tm.tm_mon);
+       wellness_str[13] = bin2bcd(cur_tm.tm_mday);
+       wellness_str[14] = bin2bcd(cur_tm.tm_year / 100);
+       wellness_str[15] = bin2bcd(cur_tm.tm_year % 100);
+
+       ret = aac_send_wellness_command(dev, wellness_str, datasize);
+
+out:
+       return ret;
+}
+
+int aac_send_hosttime(struct aac_dev *dev, struct timeval *now)
+{
+       int ret = -ENOMEM;
+       struct fib *fibptr;
+       __le32 *info;
+
+       fibptr = aac_fib_alloc(dev);
+       if (!fibptr)
+               goto out;
+
+       aac_fib_init(fibptr);
+       info = (__le32 *)fib_data(fibptr);
+       *info = cpu_to_le32(now->tv_sec);
+       ret = aac_fib_send(SendHostTime, fibptr, sizeof(*info), FsaNormal,
+                                       1, 1, NULL, NULL);
+
+       /*
+        * Do not set XferState to zero unless
+        * receives a response from F/W
+        */
+       if (ret >= 0)
+               aac_fib_complete(fibptr);
+
+       /*
+        * FIB should be freed only after
+        * getting the response from the F/W
+        */
+       if (ret != -ERESTARTSYS)
+               aac_fib_free(fibptr);
+
+out:
+       return ret;
+}
+
 /**
  *     aac_command_thread      -       command processing thread
  *     @dev: Adapter to monitor
 
                        /* Don't even try to talk to adapter if its sick */
                        ret = aac_check_health(dev);
-                       if (!ret && !dev->queues)
+                       if (!dev->queues)
                                break;
                        next_check_jiffies = jiffies
                                           + ((long)(unsigned)check_interval)
                                difference = (((1000000 - now.tv_usec) * HZ)
                                  + 500000) / 1000000;
                        else if (ret == 0) {
-                               struct fib *fibptr;
-
-                               if ((fibptr = aac_fib_alloc(dev))) {
-                                       int status;
-                                       __le32 *info;
-
-                                       aac_fib_init(fibptr);
-
-                                       info = (__le32 *) fib_data(fibptr);
-                                       if (now.tv_usec > 500000)
-                                               ++now.tv_sec;
-
-                                       *info = cpu_to_le32(now.tv_sec);
-
-                                       status = aac_fib_send(SendHostTime,
-                                               fibptr,
-                                               sizeof(*info),
-                                               FsaNormal,
-                                               1, 1,
-                                               NULL,
-                                               NULL);
-                                       /* Do not set XferState to zero unless
-                                        * receives a response from F/W */
-                                       if (status >= 0)
-                                               aac_fib_complete(fibptr);
-                                       /* FIB should be freed only after
-                                        * getting the response from the F/W */
-                                       if (status != -ERESTARTSYS)
-                                               aac_fib_free(fibptr);
-                               }
+
+                               if (now.tv_usec > 500000)
+                                       ++now.tv_sec;
+
+                               if (dev->sa_firmware)
+                                       ret =
+                                       aac_send_safw_hostttime(dev, &now);
+                               else
+                                       ret = aac_send_hosttime(dev, &now);
+
                                difference = (long)(unsigned)update_interval*HZ;
                        } else {
                                /* retry shortly */