aboutsummaryrefslogtreecommitdiffstats
path: root/kernel-patch/twa-time.patch
blob: 79c6290bbdbadb3105d7926f7271b7280b54e9cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
Sync 3ware time at boot to system rtc

diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index cd4129f..28952c6 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -91,6 +91,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/time.h>
+#include <linux/rtc.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <asm/io.h>
@@ -462,6 +464,93 @@ out:
 	return retval;
 } /* End twa_aen_severity_lookup() */
 
+static void twa_time(u8 *buf)
+{
+	struct timeval utc;
+	u64 local_time;
+	struct rtc_time tm;
+	u16 year;
+
+	do_gettimeofday(&utc);
+	local_time = (u64)(utc.tv_sec - (sys_tz.tz_minuteswest * 60));
+
+	rtc_time64_to_tm(local_time, &tm);
+
+	
+	buf[0] = 0x00; /* Unknown  always reads 0 */
+	buf[1] = tm.tm_sec;
+	buf[2] = tm.tm_min;
+	buf[3] = tm.tm_hour;
+	
+	buf[4] = tm.tm_mday;
+	buf[5] = tm.tm_mon + 1;
+
+	year = cpu_to_le16(tm.tm_year + 1900);
+	memcpy(&buf[6], &year, sizeof(year));
+}
+
+static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int table_id, int parameter_id, int parameter_size_bytes);
+
+
+static void twa_print_date_time(TW_Device_Extension *tw_dev, int request_id)
+{
+	u8 *buf=twa_get_param(tw_dev,1,TW_TIMEKEEP_TABLE,0x4,0x8);
+	u16 year;
+
+	if (!buf) {
+		printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: Can't read controller date and time\n",
+				tw_dev->host->host_no);
+		return;
+	}
+
+	memcpy(&year, &buf[6], sizeof(year));
+
+	year = le16_to_cpu(year);
+
+	printk(KERN_WARNING "3w-9xxx: scsi%d: controller time %02d-%02d-%04d %02d:%02d:%02d\n",
+			tw_dev->host->host_no,
+			(int) buf[4],
+			(int) buf[5],
+			(int) year,
+			(int) buf[3],
+			(int) buf[2],
+			(int) buf[1]);
+}
+
+/* This function will sync firmware time with the host time */
+static void twa_aen_sync_date_time(TW_Device_Extension *tw_dev, int request_id)
+{
+	TW_Command_Full *full_command_packet;
+	TW_Command *command_packet;
+	TW_Param_Apache *param;
+	/* Fill out the command packet */
+	full_command_packet = tw_dev->command_packet_virt[request_id];
+	memset(full_command_packet, 0, sizeof(TW_Command_Full));
+	command_packet = &full_command_packet->command.oldcommand;
+	command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM);
+	command_packet->request_id = request_id;
+	command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
+	command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE);
+	command_packet->size = TW_COMMAND_SIZE;
+	command_packet->byte6_offset.parameter_count = cpu_to_le16(1);
+
+	/* Setup the param */
+	param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
+	memset(param, 0, TW_SECTOR_SIZE);
+	param->table_id = cpu_to_le16(TW_TIMEKEEP_TABLE | 0x8000); /* Controller time keep table */
+	param->parameter_id = cpu_to_le16(0x4); /* SchedulerTime */
+	param->parameter_size_bytes = cpu_to_le16(8);
+
+	twa_time(param->data);
+
+	/* Mark internal command */
+	tw_dev->srb[request_id] = NULL;
+
+	/* Now post the command */
+	twa_post_command_packet(tw_dev, request_id, 1);
+} /* End twa_aen_sync_date_time() */
+
+
 /* This function will sync firmware time with the host time */
 static void twa_aen_sync_time(TW_Device_Extension *tw_dev, int request_id)
 {
@@ -2121,6 +2210,21 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
 	       le32_to_cpu(*(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE,
 				     TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH)));
 
+	twa_print_date_time(tw_dev, 0);
+
+	/* Set clock */
+	twa_aen_sync_date_time(tw_dev, 0);
+
+	/* Poll for completion */
+	if (twa_poll_response(tw_dev, 0, 30))
+		printk(KERN_WARNING "3w-9xxx: scsi%d: no response to set time\n",
+				host->host_no);
+	else 
+		printk(KERN_WARNING "3w-9xxx: scsi%d: setting clock\n",
+				host->host_no);
+
+	twa_print_date_time(tw_dev, 0);
+
 	/* Try to enable MSI */
 	if (use_msi && (pdev->device != PCI_DEVICE_ID_3WARE_9000) &&
 	    !pci_enable_msi(pdev))