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#include <linux/firmware.h>
41#include <linux/slab.h>
42#include "pm8001_sas.h"
43#include "pm8001_ctl.h"
44#include "pm8001_chips.h"
45
46
47
48
49
50
51
52
53
54
55
56static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev,
57 struct device_attribute *attr, char *buf)
58{
59 struct Scsi_Host *shost = class_to_shost(cdev);
60 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
61 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
62
63 if (pm8001_ha->chip_id == chip_8001) {
64 return snprintf(buf, PAGE_SIZE, "%d\n",
65 pm8001_ha->main_cfg_tbl.pm8001_tbl.interface_rev);
66 } else {
67 return snprintf(buf, PAGE_SIZE, "%d\n",
68 pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev);
69 }
70}
71static
72DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL);
73
74
75
76
77
78
79
80
81
82static ssize_t controller_fatal_error_show(struct device *cdev,
83 struct device_attribute *attr, char *buf)
84{
85 struct Scsi_Host *shost = class_to_shost(cdev);
86 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
87 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
88
89 return snprintf(buf, PAGE_SIZE, "%d\n",
90 pm8001_ha->controller_fatal_error);
91}
92static DEVICE_ATTR_RO(controller_fatal_error);
93
94
95
96
97
98
99
100
101
102static ssize_t pm8001_ctl_fw_version_show(struct device *cdev,
103 struct device_attribute *attr, char *buf)
104{
105 struct Scsi_Host *shost = class_to_shost(cdev);
106 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
107 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
108
109 if (pm8001_ha->chip_id == chip_8001) {
110 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
111 (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 24),
112 (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 16),
113 (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 8),
114 (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev));
115 } else {
116 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
117 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 24),
118 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 16),
119 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 8),
120 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev));
121 }
122}
123static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL);
124
125
126
127
128
129
130
131
132
133static ssize_t pm8001_ctl_ila_version_show(struct device *cdev,
134 struct device_attribute *attr, char *buf)
135{
136 struct Scsi_Host *shost = class_to_shost(cdev);
137 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
138 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
139
140 if (pm8001_ha->chip_id != chip_8001) {
141 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
142 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 24),
143 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 16),
144 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 8),
145 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version));
146 }
147 return 0;
148}
149static DEVICE_ATTR(ila_version, 0444, pm8001_ctl_ila_version_show, NULL);
150
151
152
153
154
155
156
157
158
159static ssize_t pm8001_ctl_inactive_fw_version_show(struct device *cdev,
160 struct device_attribute *attr, char *buf)
161{
162 struct Scsi_Host *shost = class_to_shost(cdev);
163 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
164 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
165
166 if (pm8001_ha->chip_id != chip_8001) {
167 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
168 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 24),
169 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 16),
170 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 8),
171 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version));
172 }
173 return 0;
174}
175static
176DEVICE_ATTR(inc_fw_ver, 0444, pm8001_ctl_inactive_fw_version_show, NULL);
177
178
179
180
181
182
183
184
185
186static ssize_t pm8001_ctl_max_out_io_show(struct device *cdev,
187 struct device_attribute *attr, char *buf)
188{
189 struct Scsi_Host *shost = class_to_shost(cdev);
190 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
191 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
192
193 if (pm8001_ha->chip_id == chip_8001) {
194 return snprintf(buf, PAGE_SIZE, "%d\n",
195 pm8001_ha->main_cfg_tbl.pm8001_tbl.max_out_io);
196 } else {
197 return snprintf(buf, PAGE_SIZE, "%d\n",
198 pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io);
199 }
200}
201static DEVICE_ATTR(max_out_io, S_IRUGO, pm8001_ctl_max_out_io_show, NULL);
202
203
204
205
206
207
208
209
210static ssize_t pm8001_ctl_max_devices_show(struct device *cdev,
211 struct device_attribute *attr, char *buf)
212{
213 struct Scsi_Host *shost = class_to_shost(cdev);
214 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
215 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
216
217 if (pm8001_ha->chip_id == chip_8001) {
218 return snprintf(buf, PAGE_SIZE, "%04d\n",
219 (u16)(pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl >> 16)
220 );
221 } else {
222 return snprintf(buf, PAGE_SIZE, "%04d\n",
223 (u16)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl >> 16)
224 );
225 }
226}
227static DEVICE_ATTR(max_devices, S_IRUGO, pm8001_ctl_max_devices_show, NULL);
228
229
230
231
232
233
234
235
236
237static ssize_t pm8001_ctl_max_sg_list_show(struct device *cdev,
238 struct device_attribute *attr, char *buf)
239{
240 struct Scsi_Host *shost = class_to_shost(cdev);
241 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
242 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
243
244 if (pm8001_ha->chip_id == chip_8001) {
245 return snprintf(buf, PAGE_SIZE, "%04d\n",
246 pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl & 0x0000FFFF
247 );
248 } else {
249 return snprintf(buf, PAGE_SIZE, "%04d\n",
250 pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl & 0x0000FFFF
251 );
252 }
253}
254static DEVICE_ATTR(max_sg_list, S_IRUGO, pm8001_ctl_max_sg_list_show, NULL);
255
256#define SAS_1_0 0x1
257#define SAS_1_1 0x2
258#define SAS_2_0 0x4
259
260static ssize_t
261show_sas_spec_support_status(unsigned int mode, char *buf)
262{
263 ssize_t len = 0;
264
265 if (mode & SAS_1_1)
266 len = sprintf(buf, "%s", "SAS1.1");
267 if (mode & SAS_2_0)
268 len += sprintf(buf + len, "%s%s", len ? ", " : "", "SAS2.0");
269 len += sprintf(buf + len, "\n");
270
271 return len;
272}
273
274
275
276
277
278
279
280
281
282static ssize_t pm8001_ctl_sas_spec_support_show(struct device *cdev,
283 struct device_attribute *attr, char *buf)
284{
285 unsigned int mode;
286 struct Scsi_Host *shost = class_to_shost(cdev);
287 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
288 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
289
290 if (pm8001_ha->chip_id == chip_8001)
291 mode = (pm8001_ha->main_cfg_tbl.pm8001_tbl.ctrl_cap_flag &
292 0xfe000000)>>25;
293 else
294
295 mode = (pm8001_ha->main_cfg_tbl.pm80xx_tbl.ctrl_cap_flag &
296 0xfe000000)>>25;
297 return show_sas_spec_support_status(mode, buf);
298}
299static DEVICE_ATTR(sas_spec_support, S_IRUGO,
300 pm8001_ctl_sas_spec_support_show, NULL);
301
302
303
304
305
306
307
308
309
310
311
312static ssize_t pm8001_ctl_host_sas_address_show(struct device *cdev,
313 struct device_attribute *attr, char *buf)
314{
315 struct Scsi_Host *shost = class_to_shost(cdev);
316 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
317 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
318 return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
319 be64_to_cpu(*(__be64 *)pm8001_ha->sas_addr));
320}
321static DEVICE_ATTR(host_sas_address, S_IRUGO,
322 pm8001_ctl_host_sas_address_show, NULL);
323
324
325
326
327
328
329
330
331
332static ssize_t pm8001_ctl_logging_level_show(struct device *cdev,
333 struct device_attribute *attr, char *buf)
334{
335 struct Scsi_Host *shost = class_to_shost(cdev);
336 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
337 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
338
339 return snprintf(buf, PAGE_SIZE, "%08xh\n", pm8001_ha->logging_level);
340}
341
342static ssize_t pm8001_ctl_logging_level_store(struct device *cdev,
343 struct device_attribute *attr, const char *buf, size_t count)
344{
345 struct Scsi_Host *shost = class_to_shost(cdev);
346 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
347 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
348 int val = 0;
349
350 if (sscanf(buf, "%x", &val) != 1)
351 return -EINVAL;
352
353 pm8001_ha->logging_level = val;
354 return strlen(buf);
355}
356
357static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR,
358 pm8001_ctl_logging_level_show, pm8001_ctl_logging_level_store);
359
360
361
362
363
364
365
366
367static ssize_t pm8001_ctl_aap_log_show(struct device *cdev,
368 struct device_attribute *attr, char *buf)
369{
370 struct Scsi_Host *shost = class_to_shost(cdev);
371 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
372 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
373 u8 *ptr = (u8 *)pm8001_ha->memoryMap.region[AAP1].virt_ptr;
374 int i;
375
376 char *str = buf;
377 int max = 2;
378 for (i = 0; i < max; i++) {
379 str += sprintf(str, "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x"
380 "0x%08x 0x%08x\n",
381 pm8001_ctl_aap1_memmap(ptr, i, 0),
382 pm8001_ctl_aap1_memmap(ptr, i, 4),
383 pm8001_ctl_aap1_memmap(ptr, i, 8),
384 pm8001_ctl_aap1_memmap(ptr, i, 12),
385 pm8001_ctl_aap1_memmap(ptr, i, 16),
386 pm8001_ctl_aap1_memmap(ptr, i, 20),
387 pm8001_ctl_aap1_memmap(ptr, i, 24),
388 pm8001_ctl_aap1_memmap(ptr, i, 28));
389 }
390
391 return str - buf;
392}
393static DEVICE_ATTR(aap_log, S_IRUGO, pm8001_ctl_aap_log_show, NULL);
394
395
396
397
398
399
400
401
402static ssize_t pm8001_ctl_ib_queue_log_show(struct device *cdev,
403 struct device_attribute *attr, char *buf)
404{
405 struct Scsi_Host *shost = class_to_shost(cdev);
406 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
407 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
408 int offset;
409 char *str = buf;
410 int start = 0;
411 u32 ib_offset = pm8001_ha->ib_offset;
412 u32 queue_size = pm8001_ha->max_q_num * PM8001_MPI_QUEUE * 128;
413#define IB_MEMMAP(c) \
414 (*(u32 *)((u8 *)pm8001_ha-> \
415 memoryMap.region[ib_offset].virt_ptr + \
416 pm8001_ha->evtlog_ib_offset + (c)))
417
418 for (offset = 0; offset < IB_OB_READ_TIMES; offset++) {
419 str += sprintf(str, "0x%08x\n", IB_MEMMAP(start));
420 start = start + 4;
421 }
422 pm8001_ha->evtlog_ib_offset += SYSFS_OFFSET;
423 if (((pm8001_ha->evtlog_ib_offset) % queue_size) == 0)
424 pm8001_ha->evtlog_ib_offset = 0;
425
426 return str - buf;
427}
428
429static DEVICE_ATTR(ib_log, S_IRUGO, pm8001_ctl_ib_queue_log_show, NULL);
430
431
432
433
434
435
436
437
438
439static ssize_t pm8001_ctl_ob_queue_log_show(struct device *cdev,
440 struct device_attribute *attr, char *buf)
441{
442 struct Scsi_Host *shost = class_to_shost(cdev);
443 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
444 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
445 int offset;
446 char *str = buf;
447 int start = 0;
448 u32 ob_offset = pm8001_ha->ob_offset;
449 u32 queue_size = pm8001_ha->max_q_num * PM8001_MPI_QUEUE * 128;
450#define OB_MEMMAP(c) \
451 (*(u32 *)((u8 *)pm8001_ha-> \
452 memoryMap.region[ob_offset].virt_ptr + \
453 pm8001_ha->evtlog_ob_offset + (c)))
454
455 for (offset = 0; offset < IB_OB_READ_TIMES; offset++) {
456 str += sprintf(str, "0x%08x\n", OB_MEMMAP(start));
457 start = start + 4;
458 }
459 pm8001_ha->evtlog_ob_offset += SYSFS_OFFSET;
460 if (((pm8001_ha->evtlog_ob_offset) % queue_size) == 0)
461 pm8001_ha->evtlog_ob_offset = 0;
462
463 return str - buf;
464}
465static DEVICE_ATTR(ob_log, S_IRUGO, pm8001_ctl_ob_queue_log_show, NULL);
466
467
468
469
470
471
472
473
474static ssize_t pm8001_ctl_bios_version_show(struct device *cdev,
475 struct device_attribute *attr, char *buf)
476{
477 struct Scsi_Host *shost = class_to_shost(cdev);
478 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
479 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
480 char *str = buf;
481 int bios_index;
482 DECLARE_COMPLETION_ONSTACK(completion);
483 struct pm8001_ioctl_payload payload;
484
485 pm8001_ha->nvmd_completion = &completion;
486 payload.minor_function = 7;
487 payload.offset = 0;
488 payload.rd_length = 4096;
489 payload.func_specific = kzalloc(4096, GFP_KERNEL);
490 if (!payload.func_specific)
491 return -ENOMEM;
492 if (PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload)) {
493 kfree(payload.func_specific);
494 return -ENOMEM;
495 }
496 wait_for_completion(&completion);
497 for (bios_index = BIOSOFFSET; bios_index < BIOS_OFFSET_LIMIT;
498 bios_index++)
499 str += sprintf(str, "%c",
500 *(payload.func_specific+bios_index));
501 kfree(payload.func_specific);
502 return str - buf;
503}
504static DEVICE_ATTR(bios_version, S_IRUGO, pm8001_ctl_bios_version_show, NULL);
505
506
507
508
509
510
511
512
513static ssize_t event_log_size_show(struct device *cdev,
514 struct device_attribute *attr, char *buf)
515{
516 struct Scsi_Host *shost = class_to_shost(cdev);
517 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
518 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
519
520 return snprintf(buf, PAGE_SIZE, "%d\n",
521 pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size);
522}
523static DEVICE_ATTR_RO(event_log_size);
524
525
526
527
528
529
530
531
532static ssize_t pm8001_ctl_iop_log_show(struct device *cdev,
533 struct device_attribute *attr, char *buf)
534{
535 struct Scsi_Host *shost = class_to_shost(cdev);
536 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
537 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
538 char *str = buf;
539 u32 read_size =
540 pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size / 1024;
541 static u32 start, end, count;
542 u32 max_read_times = 32;
543 u32 max_count = (read_size * 1024) / (max_read_times * 4);
544 u32 *temp = (u32 *)pm8001_ha->memoryMap.region[IOP].virt_ptr;
545
546 if ((count % max_count) == 0) {
547 start = 0;
548 end = max_read_times;
549 count = 0;
550 } else {
551 start = end;
552 end = end + max_read_times;
553 }
554
555 for (; start < end; start++)
556 str += sprintf(str, "%08x ", *(temp+start));
557 count++;
558 return str - buf;
559}
560static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL);
561
562
563
564
565
566
567
568
569
570
571static ssize_t pm8001_ctl_fatal_log_show(struct device *cdev,
572 struct device_attribute *attr, char *buf)
573{
574 ssize_t count;
575
576 count = pm80xx_get_fatal_dump(cdev, attr, buf);
577 return count;
578}
579
580static DEVICE_ATTR(fatal_log, S_IRUGO, pm8001_ctl_fatal_log_show, NULL);
581
582
583
584
585
586
587
588
589
590static ssize_t non_fatal_log_show(struct device *cdev,
591 struct device_attribute *attr, char *buf)
592{
593 u32 count;
594
595 count = pm80xx_get_non_fatal_dump(cdev, attr, buf);
596 return count;
597}
598static DEVICE_ATTR_RO(non_fatal_log);
599
600static ssize_t non_fatal_count_show(struct device *cdev,
601 struct device_attribute *attr, char *buf)
602{
603 struct Scsi_Host *shost = class_to_shost(cdev);
604 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
605 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
606
607 return snprintf(buf, PAGE_SIZE, "%08x",
608 pm8001_ha->non_fatal_count);
609}
610
611static ssize_t non_fatal_count_store(struct device *cdev,
612 struct device_attribute *attr, const char *buf, size_t count)
613{
614 struct Scsi_Host *shost = class_to_shost(cdev);
615 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
616 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
617 int val = 0;
618
619 if (kstrtoint(buf, 16, &val) != 0)
620 return -EINVAL;
621
622 pm8001_ha->non_fatal_count = val;
623 return strlen(buf);
624}
625static DEVICE_ATTR_RW(non_fatal_count);
626
627
628
629
630
631
632
633
634
635static ssize_t pm8001_ctl_gsm_log_show(struct device *cdev,
636 struct device_attribute *attr, char *buf)
637{
638 ssize_t count;
639
640 count = pm8001_get_gsm_dump(cdev, SYSFS_OFFSET, buf);
641 return count;
642}
643
644static DEVICE_ATTR(gsm_log, S_IRUGO, pm8001_ctl_gsm_log_show, NULL);
645
646#define FLASH_CMD_NONE 0x00
647#define FLASH_CMD_UPDATE 0x01
648#define FLASH_CMD_SET_NVMD 0x02
649
650struct flash_command {
651 u8 command[8];
652 int code;
653};
654
655static const struct flash_command flash_command_table[] = {
656 {"set_nvmd", FLASH_CMD_SET_NVMD},
657 {"update", FLASH_CMD_UPDATE},
658 {"", FLASH_CMD_NONE}
659};
660
661struct error_fw {
662 char *reason;
663 int err_code;
664};
665
666static const struct error_fw flash_error_table[] = {
667 {"Failed to open fw image file", FAIL_OPEN_BIOS_FILE},
668 {"image header mismatch", FLASH_UPDATE_HDR_ERR},
669 {"image offset mismatch", FLASH_UPDATE_OFFSET_ERR},
670 {"image CRC Error", FLASH_UPDATE_CRC_ERR},
671 {"image length Error.", FLASH_UPDATE_LENGTH_ERR},
672 {"Failed to program flash chip", FLASH_UPDATE_HW_ERR},
673 {"Flash chip not supported.", FLASH_UPDATE_DNLD_NOT_SUPPORTED},
674 {"Flash update disabled.", FLASH_UPDATE_DISABLED},
675 {"Flash in progress", FLASH_IN_PROGRESS},
676 {"Image file size Error", FAIL_FILE_SIZE},
677 {"Input parameter error", FAIL_PARAMETERS},
678 {"Out of memory", FAIL_OUT_MEMORY},
679 {"OK", 0}
680};
681
682static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha)
683{
684 struct pm8001_ioctl_payload *payload;
685 DECLARE_COMPLETION_ONSTACK(completion);
686 u8 *ioctlbuffer;
687 u32 ret;
688 u32 length = 1024 * 5 + sizeof(*payload) - 1;
689
690 if (pm8001_ha->fw_image->size > 4096) {
691 pm8001_ha->fw_status = FAIL_FILE_SIZE;
692 return -EFAULT;
693 }
694
695 ioctlbuffer = kzalloc(length, GFP_KERNEL);
696 if (!ioctlbuffer) {
697 pm8001_ha->fw_status = FAIL_OUT_MEMORY;
698 return -ENOMEM;
699 }
700 payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
701 memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
702 pm8001_ha->fw_image->size);
703 payload->wr_length = pm8001_ha->fw_image->size;
704 payload->id = 0;
705 payload->minor_function = 0x1;
706 pm8001_ha->nvmd_completion = &completion;
707 ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload);
708 if (ret) {
709 pm8001_ha->fw_status = FAIL_OUT_MEMORY;
710 goto out;
711 }
712 wait_for_completion(&completion);
713out:
714 kfree(ioctlbuffer);
715 return ret;
716}
717
718static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)
719{
720 struct pm8001_ioctl_payload *payload;
721 DECLARE_COMPLETION_ONSTACK(completion);
722 u8 *ioctlbuffer;
723 struct fw_control_info *fwControl;
724 u32 partitionSize, partitionSizeTmp;
725 u32 loopNumber, loopcount;
726 struct pm8001_fw_image_header *image_hdr;
727 u32 sizeRead = 0;
728 u32 ret = 0;
729 u32 length = 1024 * 16 + sizeof(*payload) - 1;
730
731 if (pm8001_ha->fw_image->size < 28) {
732 pm8001_ha->fw_status = FAIL_FILE_SIZE;
733 return -EFAULT;
734 }
735 ioctlbuffer = kzalloc(length, GFP_KERNEL);
736 if (!ioctlbuffer) {
737 pm8001_ha->fw_status = FAIL_OUT_MEMORY;
738 return -ENOMEM;
739 }
740 image_hdr = (struct pm8001_fw_image_header *)pm8001_ha->fw_image->data;
741 while (sizeRead < pm8001_ha->fw_image->size) {
742 partitionSizeTmp =
743 *(u32 *)((u8 *)&image_hdr->image_length + sizeRead);
744 partitionSize = be32_to_cpu(partitionSizeTmp);
745 loopcount = DIV_ROUND_UP(partitionSize + HEADER_LEN,
746 IOCTL_BUF_SIZE);
747 for (loopNumber = 0; loopNumber < loopcount; loopNumber++) {
748 payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
749 payload->wr_length = 1024*16;
750 payload->id = 0;
751 fwControl =
752 (struct fw_control_info *)&payload->func_specific;
753 fwControl->len = IOCTL_BUF_SIZE;
754 fwControl->size = partitionSize + HEADER_LEN;
755 fwControl->retcode = 0;
756 fwControl->offset = loopNumber * IOCTL_BUF_SIZE;
757
758
759
760 if (((loopcount-loopNumber) == 1) &&
761 ((partitionSize + HEADER_LEN) % IOCTL_BUF_SIZE)) {
762 fwControl->len =
763 (partitionSize + HEADER_LEN) % IOCTL_BUF_SIZE;
764 memcpy((u8 *)fwControl->buffer,
765 (u8 *)pm8001_ha->fw_image->data + sizeRead,
766 (partitionSize + HEADER_LEN) % IOCTL_BUF_SIZE);
767 sizeRead +=
768 (partitionSize + HEADER_LEN) % IOCTL_BUF_SIZE;
769 } else {
770 memcpy((u8 *)fwControl->buffer,
771 (u8 *)pm8001_ha->fw_image->data + sizeRead,
772 IOCTL_BUF_SIZE);
773 sizeRead += IOCTL_BUF_SIZE;
774 }
775
776 pm8001_ha->nvmd_completion = &completion;
777 ret = PM8001_CHIP_DISP->fw_flash_update_req(pm8001_ha, payload);
778 if (ret) {
779 pm8001_ha->fw_status = FAIL_OUT_MEMORY;
780 goto out;
781 }
782 wait_for_completion(&completion);
783 if (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS) {
784 pm8001_ha->fw_status = fwControl->retcode;
785 ret = -EFAULT;
786 goto out;
787 }
788 }
789 }
790out:
791 kfree(ioctlbuffer);
792 return ret;
793}
794static ssize_t pm8001_store_update_fw(struct device *cdev,
795 struct device_attribute *attr,
796 const char *buf, size_t count)
797{
798 struct Scsi_Host *shost = class_to_shost(cdev);
799 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
800 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
801 char *cmd_ptr, *filename_ptr;
802 int res, i;
803 int flash_command = FLASH_CMD_NONE;
804 int ret;
805
806 if (!capable(CAP_SYS_ADMIN))
807 return -EACCES;
808
809
810
811 if (pm8001_ha->fw_status == FLASH_IN_PROGRESS)
812 return -EINPROGRESS;
813 pm8001_ha->fw_status = FLASH_IN_PROGRESS;
814
815 cmd_ptr = kcalloc(count, 2, GFP_KERNEL);
816 if (!cmd_ptr) {
817 pm8001_ha->fw_status = FAIL_OUT_MEMORY;
818 return -ENOMEM;
819 }
820
821 filename_ptr = cmd_ptr + count;
822 res = sscanf(buf, "%s %s", cmd_ptr, filename_ptr);
823 if (res != 2) {
824 pm8001_ha->fw_status = FAIL_PARAMETERS;
825 ret = -EINVAL;
826 goto out;
827 }
828
829 for (i = 0; flash_command_table[i].code != FLASH_CMD_NONE; i++) {
830 if (!memcmp(flash_command_table[i].command,
831 cmd_ptr, strlen(cmd_ptr))) {
832 flash_command = flash_command_table[i].code;
833 break;
834 }
835 }
836 if (flash_command == FLASH_CMD_NONE) {
837 pm8001_ha->fw_status = FAIL_PARAMETERS;
838 ret = -EINVAL;
839 goto out;
840 }
841
842 ret = request_firmware(&pm8001_ha->fw_image,
843 filename_ptr,
844 pm8001_ha->dev);
845
846 if (ret) {
847 pm8001_dbg(pm8001_ha, FAIL,
848 "Failed to load firmware image file %s, error %d\n",
849 filename_ptr, ret);
850 pm8001_ha->fw_status = FAIL_OPEN_BIOS_FILE;
851 goto out;
852 }
853
854 if (FLASH_CMD_UPDATE == flash_command)
855 ret = pm8001_update_flash(pm8001_ha);
856 else
857 ret = pm8001_set_nvmd(pm8001_ha);
858
859 release_firmware(pm8001_ha->fw_image);
860out:
861 kfree(cmd_ptr);
862
863 if (ret)
864 return ret;
865
866 pm8001_ha->fw_status = FLASH_OK;
867 return count;
868}
869
870static ssize_t pm8001_show_update_fw(struct device *cdev,
871 struct device_attribute *attr, char *buf)
872{
873 int i;
874 struct Scsi_Host *shost = class_to_shost(cdev);
875 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
876 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
877
878 for (i = 0; flash_error_table[i].err_code != 0; i++) {
879 if (flash_error_table[i].err_code == pm8001_ha->fw_status)
880 break;
881 }
882 if (pm8001_ha->fw_status != FLASH_IN_PROGRESS)
883 pm8001_ha->fw_status = FLASH_OK;
884
885 return snprintf(buf, PAGE_SIZE, "status=%x %s\n",
886 flash_error_table[i].err_code,
887 flash_error_table[i].reason);
888}
889static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP,
890 pm8001_show_update_fw, pm8001_store_update_fw);
891
892
893
894
895
896
897
898
899
900static const char *const mpiStateText[] = {
901 "MPI is not initialized",
902 "MPI is successfully initialized",
903 "MPI termination is in progress",
904 "MPI initialization failed with error in [31:16]"
905};
906
907static ssize_t ctl_mpi_state_show(struct device *cdev,
908 struct device_attribute *attr, char *buf)
909{
910 struct Scsi_Host *shost = class_to_shost(cdev);
911 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
912 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
913 unsigned int mpidw0;
914
915 mpidw0 = pm8001_mr32(pm8001_ha->general_stat_tbl_addr, 0);
916 return sysfs_emit(buf, "%s\n", mpiStateText[mpidw0 & 0x0003]);
917}
918static DEVICE_ATTR_RO(ctl_mpi_state);
919
920
921
922
923
924
925
926
927
928static ssize_t ctl_hmi_error_show(struct device *cdev,
929 struct device_attribute *attr, char *buf)
930{
931 struct Scsi_Host *shost = class_to_shost(cdev);
932 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
933 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
934 unsigned int mpidw0;
935
936 mpidw0 = pm8001_mr32(pm8001_ha->general_stat_tbl_addr, 0);
937 return sysfs_emit(buf, "0x%08x\n", (mpidw0 >> 16));
938}
939static DEVICE_ATTR_RO(ctl_hmi_error);
940
941
942
943
944
945
946
947
948
949static ssize_t ctl_raae_count_show(struct device *cdev,
950 struct device_attribute *attr, char *buf)
951{
952 struct Scsi_Host *shost = class_to_shost(cdev);
953 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
954 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
955 unsigned int raaecnt;
956
957 raaecnt = pm8001_mr32(pm8001_ha->general_stat_tbl_addr, 12);
958 return sysfs_emit(buf, "0x%08x\n", raaecnt);
959}
960static DEVICE_ATTR_RO(ctl_raae_count);
961
962
963
964
965
966
967
968
969
970static ssize_t ctl_iop0_count_show(struct device *cdev,
971 struct device_attribute *attr, char *buf)
972{
973 struct Scsi_Host *shost = class_to_shost(cdev);
974 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
975 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
976 unsigned int iop0cnt;
977
978 iop0cnt = pm8001_mr32(pm8001_ha->general_stat_tbl_addr, 16);
979 return sysfs_emit(buf, "0x%08x\n", iop0cnt);
980}
981static DEVICE_ATTR_RO(ctl_iop0_count);
982
983
984
985
986
987
988
989
990
991static ssize_t ctl_iop1_count_show(struct device *cdev,
992 struct device_attribute *attr, char *buf)
993{
994 struct Scsi_Host *shost = class_to_shost(cdev);
995 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
996 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
997 unsigned int iop1cnt;
998
999 iop1cnt = pm8001_mr32(pm8001_ha->general_stat_tbl_addr, 20);
1000 return sysfs_emit(buf, "0x%08x\n", iop1cnt);
1001
1002}
1003static DEVICE_ATTR_RO(ctl_iop1_count);
1004
1005static struct attribute *pm8001_host_attrs[] = {
1006 &dev_attr_interface_rev.attr,
1007 &dev_attr_controller_fatal_error.attr,
1008 &dev_attr_fw_version.attr,
1009 &dev_attr_update_fw.attr,
1010 &dev_attr_aap_log.attr,
1011 &dev_attr_iop_log.attr,
1012 &dev_attr_fatal_log.attr,
1013 &dev_attr_non_fatal_log.attr,
1014 &dev_attr_non_fatal_count.attr,
1015 &dev_attr_gsm_log.attr,
1016 &dev_attr_max_out_io.attr,
1017 &dev_attr_max_devices.attr,
1018 &dev_attr_max_sg_list.attr,
1019 &dev_attr_sas_spec_support.attr,
1020 &dev_attr_logging_level.attr,
1021 &dev_attr_event_log_size.attr,
1022 &dev_attr_host_sas_address.attr,
1023 &dev_attr_bios_version.attr,
1024 &dev_attr_ib_log.attr,
1025 &dev_attr_ob_log.attr,
1026 &dev_attr_ila_version.attr,
1027 &dev_attr_inc_fw_ver.attr,
1028 &dev_attr_ctl_mpi_state.attr,
1029 &dev_attr_ctl_hmi_error.attr,
1030 &dev_attr_ctl_raae_count.attr,
1031 &dev_attr_ctl_iop0_count.attr,
1032 &dev_attr_ctl_iop1_count.attr,
1033 NULL,
1034};
1035
1036static const struct attribute_group pm8001_host_attr_group = {
1037 .attrs = pm8001_host_attrs
1038};
1039
1040const struct attribute_group *pm8001_host_groups[] = {
1041 &pm8001_host_attr_group,
1042 NULL
1043};
1044