0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #include <linux/firmware.h>
0041 #include <linux/slab.h>
0042 #include "pm8001_sas.h"
0043 #include "pm8001_ctl.h"
0044 #include "pm8001_chips.h"
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev,
0057 struct device_attribute *attr, char *buf)
0058 {
0059 struct Scsi_Host *shost = class_to_shost(cdev);
0060 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0061 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0062
0063 if (pm8001_ha->chip_id == chip_8001) {
0064 return snprintf(buf, PAGE_SIZE, "%d\n",
0065 pm8001_ha->main_cfg_tbl.pm8001_tbl.interface_rev);
0066 } else {
0067 return snprintf(buf, PAGE_SIZE, "%d\n",
0068 pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev);
0069 }
0070 }
0071 static
0072 DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL);
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 static ssize_t controller_fatal_error_show(struct device *cdev,
0083 struct device_attribute *attr, char *buf)
0084 {
0085 struct Scsi_Host *shost = class_to_shost(cdev);
0086 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0087 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0088
0089 return snprintf(buf, PAGE_SIZE, "%d\n",
0090 pm8001_ha->controller_fatal_error);
0091 }
0092 static DEVICE_ATTR_RO(controller_fatal_error);
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102 static ssize_t pm8001_ctl_fw_version_show(struct device *cdev,
0103 struct device_attribute *attr, char *buf)
0104 {
0105 struct Scsi_Host *shost = class_to_shost(cdev);
0106 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0107 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0108
0109 if (pm8001_ha->chip_id == chip_8001) {
0110 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
0111 (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 24),
0112 (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 16),
0113 (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 8),
0114 (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev));
0115 } else {
0116 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
0117 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 24),
0118 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 16),
0119 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 8),
0120 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev));
0121 }
0122 }
0123 static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL);
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 static ssize_t pm8001_ctl_ila_version_show(struct device *cdev,
0134 struct device_attribute *attr, char *buf)
0135 {
0136 struct Scsi_Host *shost = class_to_shost(cdev);
0137 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0138 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0139
0140 if (pm8001_ha->chip_id != chip_8001) {
0141 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
0142 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 24),
0143 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 16),
0144 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 8),
0145 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version));
0146 }
0147 return 0;
0148 }
0149 static DEVICE_ATTR(ila_version, 0444, pm8001_ctl_ila_version_show, NULL);
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 static ssize_t pm8001_ctl_inactive_fw_version_show(struct device *cdev,
0160 struct device_attribute *attr, char *buf)
0161 {
0162 struct Scsi_Host *shost = class_to_shost(cdev);
0163 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0164 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0165
0166 if (pm8001_ha->chip_id != chip_8001) {
0167 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
0168 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 24),
0169 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 16),
0170 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 8),
0171 (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version));
0172 }
0173 return 0;
0174 }
0175 static
0176 DEVICE_ATTR(inc_fw_ver, 0444, pm8001_ctl_inactive_fw_version_show, NULL);
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186 static ssize_t pm8001_ctl_max_out_io_show(struct device *cdev,
0187 struct device_attribute *attr, char *buf)
0188 {
0189 struct Scsi_Host *shost = class_to_shost(cdev);
0190 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0191 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0192
0193 if (pm8001_ha->chip_id == chip_8001) {
0194 return snprintf(buf, PAGE_SIZE, "%d\n",
0195 pm8001_ha->main_cfg_tbl.pm8001_tbl.max_out_io);
0196 } else {
0197 return snprintf(buf, PAGE_SIZE, "%d\n",
0198 pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io);
0199 }
0200 }
0201 static DEVICE_ATTR(max_out_io, S_IRUGO, pm8001_ctl_max_out_io_show, NULL);
0202
0203
0204
0205
0206
0207
0208
0209
0210 static ssize_t pm8001_ctl_max_devices_show(struct device *cdev,
0211 struct device_attribute *attr, char *buf)
0212 {
0213 struct Scsi_Host *shost = class_to_shost(cdev);
0214 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0215 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0216
0217 if (pm8001_ha->chip_id == chip_8001) {
0218 return snprintf(buf, PAGE_SIZE, "%04d\n",
0219 (u16)(pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl >> 16)
0220 );
0221 } else {
0222 return snprintf(buf, PAGE_SIZE, "%04d\n",
0223 (u16)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl >> 16)
0224 );
0225 }
0226 }
0227 static DEVICE_ATTR(max_devices, S_IRUGO, pm8001_ctl_max_devices_show, NULL);
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237 static ssize_t pm8001_ctl_max_sg_list_show(struct device *cdev,
0238 struct device_attribute *attr, char *buf)
0239 {
0240 struct Scsi_Host *shost = class_to_shost(cdev);
0241 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0242 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0243
0244 if (pm8001_ha->chip_id == chip_8001) {
0245 return snprintf(buf, PAGE_SIZE, "%04d\n",
0246 pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl & 0x0000FFFF
0247 );
0248 } else {
0249 return snprintf(buf, PAGE_SIZE, "%04d\n",
0250 pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl & 0x0000FFFF
0251 );
0252 }
0253 }
0254 static DEVICE_ATTR(max_sg_list, S_IRUGO, pm8001_ctl_max_sg_list_show, NULL);
0255
0256 #define SAS_1_0 0x1
0257 #define SAS_1_1 0x2
0258 #define SAS_2_0 0x4
0259
0260 static ssize_t
0261 show_sas_spec_support_status(unsigned int mode, char *buf)
0262 {
0263 ssize_t len = 0;
0264
0265 if (mode & SAS_1_1)
0266 len = sprintf(buf, "%s", "SAS1.1");
0267 if (mode & SAS_2_0)
0268 len += sprintf(buf + len, "%s%s", len ? ", " : "", "SAS2.0");
0269 len += sprintf(buf + len, "\n");
0270
0271 return len;
0272 }
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282 static ssize_t pm8001_ctl_sas_spec_support_show(struct device *cdev,
0283 struct device_attribute *attr, char *buf)
0284 {
0285 unsigned int mode;
0286 struct Scsi_Host *shost = class_to_shost(cdev);
0287 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0288 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0289
0290 if (pm8001_ha->chip_id == chip_8001)
0291 mode = (pm8001_ha->main_cfg_tbl.pm8001_tbl.ctrl_cap_flag &
0292 0xfe000000)>>25;
0293 else
0294
0295 mode = (pm8001_ha->main_cfg_tbl.pm80xx_tbl.ctrl_cap_flag &
0296 0xfe000000)>>25;
0297 return show_sas_spec_support_status(mode, buf);
0298 }
0299 static DEVICE_ATTR(sas_spec_support, S_IRUGO,
0300 pm8001_ctl_sas_spec_support_show, NULL);
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312 static ssize_t pm8001_ctl_host_sas_address_show(struct device *cdev,
0313 struct device_attribute *attr, char *buf)
0314 {
0315 struct Scsi_Host *shost = class_to_shost(cdev);
0316 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0317 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0318 return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
0319 be64_to_cpu(*(__be64 *)pm8001_ha->sas_addr));
0320 }
0321 static DEVICE_ATTR(host_sas_address, S_IRUGO,
0322 pm8001_ctl_host_sas_address_show, NULL);
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332 static ssize_t pm8001_ctl_logging_level_show(struct device *cdev,
0333 struct device_attribute *attr, char *buf)
0334 {
0335 struct Scsi_Host *shost = class_to_shost(cdev);
0336 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0337 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0338
0339 return snprintf(buf, PAGE_SIZE, "%08xh\n", pm8001_ha->logging_level);
0340 }
0341
0342 static ssize_t pm8001_ctl_logging_level_store(struct device *cdev,
0343 struct device_attribute *attr, const char *buf, size_t count)
0344 {
0345 struct Scsi_Host *shost = class_to_shost(cdev);
0346 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0347 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0348 int val = 0;
0349
0350 if (sscanf(buf, "%x", &val) != 1)
0351 return -EINVAL;
0352
0353 pm8001_ha->logging_level = val;
0354 return strlen(buf);
0355 }
0356
0357 static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR,
0358 pm8001_ctl_logging_level_show, pm8001_ctl_logging_level_store);
0359
0360
0361
0362
0363
0364
0365
0366
0367 static ssize_t pm8001_ctl_aap_log_show(struct device *cdev,
0368 struct device_attribute *attr, char *buf)
0369 {
0370 struct Scsi_Host *shost = class_to_shost(cdev);
0371 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0372 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0373 u8 *ptr = (u8 *)pm8001_ha->memoryMap.region[AAP1].virt_ptr;
0374 int i;
0375
0376 char *str = buf;
0377 int max = 2;
0378 for (i = 0; i < max; i++) {
0379 str += sprintf(str, "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x"
0380 "0x%08x 0x%08x\n",
0381 pm8001_ctl_aap1_memmap(ptr, i, 0),
0382 pm8001_ctl_aap1_memmap(ptr, i, 4),
0383 pm8001_ctl_aap1_memmap(ptr, i, 8),
0384 pm8001_ctl_aap1_memmap(ptr, i, 12),
0385 pm8001_ctl_aap1_memmap(ptr, i, 16),
0386 pm8001_ctl_aap1_memmap(ptr, i, 20),
0387 pm8001_ctl_aap1_memmap(ptr, i, 24),
0388 pm8001_ctl_aap1_memmap(ptr, i, 28));
0389 }
0390
0391 return str - buf;
0392 }
0393 static DEVICE_ATTR(aap_log, S_IRUGO, pm8001_ctl_aap_log_show, NULL);
0394
0395
0396
0397
0398
0399
0400
0401
0402 static ssize_t pm8001_ctl_ib_queue_log_show(struct device *cdev,
0403 struct device_attribute *attr, char *buf)
0404 {
0405 struct Scsi_Host *shost = class_to_shost(cdev);
0406 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0407 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0408 int offset;
0409 char *str = buf;
0410 int start = 0;
0411 u32 ib_offset = pm8001_ha->ib_offset;
0412 u32 queue_size = pm8001_ha->max_q_num * PM8001_MPI_QUEUE * 128;
0413 #define IB_MEMMAP(c) \
0414 (*(u32 *)((u8 *)pm8001_ha-> \
0415 memoryMap.region[ib_offset].virt_ptr + \
0416 pm8001_ha->evtlog_ib_offset + (c)))
0417
0418 for (offset = 0; offset < IB_OB_READ_TIMES; offset++) {
0419 str += sprintf(str, "0x%08x\n", IB_MEMMAP(start));
0420 start = start + 4;
0421 }
0422 pm8001_ha->evtlog_ib_offset += SYSFS_OFFSET;
0423 if (((pm8001_ha->evtlog_ib_offset) % queue_size) == 0)
0424 pm8001_ha->evtlog_ib_offset = 0;
0425
0426 return str - buf;
0427 }
0428
0429 static DEVICE_ATTR(ib_log, S_IRUGO, pm8001_ctl_ib_queue_log_show, NULL);
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439 static ssize_t pm8001_ctl_ob_queue_log_show(struct device *cdev,
0440 struct device_attribute *attr, char *buf)
0441 {
0442 struct Scsi_Host *shost = class_to_shost(cdev);
0443 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0444 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0445 int offset;
0446 char *str = buf;
0447 int start = 0;
0448 u32 ob_offset = pm8001_ha->ob_offset;
0449 u32 queue_size = pm8001_ha->max_q_num * PM8001_MPI_QUEUE * 128;
0450 #define OB_MEMMAP(c) \
0451 (*(u32 *)((u8 *)pm8001_ha-> \
0452 memoryMap.region[ob_offset].virt_ptr + \
0453 pm8001_ha->evtlog_ob_offset + (c)))
0454
0455 for (offset = 0; offset < IB_OB_READ_TIMES; offset++) {
0456 str += sprintf(str, "0x%08x\n", OB_MEMMAP(start));
0457 start = start + 4;
0458 }
0459 pm8001_ha->evtlog_ob_offset += SYSFS_OFFSET;
0460 if (((pm8001_ha->evtlog_ob_offset) % queue_size) == 0)
0461 pm8001_ha->evtlog_ob_offset = 0;
0462
0463 return str - buf;
0464 }
0465 static DEVICE_ATTR(ob_log, S_IRUGO, pm8001_ctl_ob_queue_log_show, NULL);
0466
0467
0468
0469
0470
0471
0472
0473
0474 static ssize_t pm8001_ctl_bios_version_show(struct device *cdev,
0475 struct device_attribute *attr, char *buf)
0476 {
0477 struct Scsi_Host *shost = class_to_shost(cdev);
0478 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0479 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0480 char *str = buf;
0481 int bios_index;
0482 DECLARE_COMPLETION_ONSTACK(completion);
0483 struct pm8001_ioctl_payload payload;
0484
0485 pm8001_ha->nvmd_completion = &completion;
0486 payload.minor_function = 7;
0487 payload.offset = 0;
0488 payload.rd_length = 4096;
0489 payload.func_specific = kzalloc(4096, GFP_KERNEL);
0490 if (!payload.func_specific)
0491 return -ENOMEM;
0492 if (PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload)) {
0493 kfree(payload.func_specific);
0494 return -ENOMEM;
0495 }
0496 wait_for_completion(&completion);
0497 for (bios_index = BIOSOFFSET; bios_index < BIOS_OFFSET_LIMIT;
0498 bios_index++)
0499 str += sprintf(str, "%c",
0500 *(payload.func_specific+bios_index));
0501 kfree(payload.func_specific);
0502 return str - buf;
0503 }
0504 static DEVICE_ATTR(bios_version, S_IRUGO, pm8001_ctl_bios_version_show, NULL);
0505
0506
0507
0508
0509
0510
0511
0512
0513 static ssize_t event_log_size_show(struct device *cdev,
0514 struct device_attribute *attr, char *buf)
0515 {
0516 struct Scsi_Host *shost = class_to_shost(cdev);
0517 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0518 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0519
0520 return snprintf(buf, PAGE_SIZE, "%d\n",
0521 pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size);
0522 }
0523 static DEVICE_ATTR_RO(event_log_size);
0524
0525
0526
0527
0528
0529
0530
0531
0532 static ssize_t pm8001_ctl_iop_log_show(struct device *cdev,
0533 struct device_attribute *attr, char *buf)
0534 {
0535 struct Scsi_Host *shost = class_to_shost(cdev);
0536 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0537 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0538 char *str = buf;
0539 u32 read_size =
0540 pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size / 1024;
0541 static u32 start, end, count;
0542 u32 max_read_times = 32;
0543 u32 max_count = (read_size * 1024) / (max_read_times * 4);
0544 u32 *temp = (u32 *)pm8001_ha->memoryMap.region[IOP].virt_ptr;
0545
0546 if ((count % max_count) == 0) {
0547 start = 0;
0548 end = max_read_times;
0549 count = 0;
0550 } else {
0551 start = end;
0552 end = end + max_read_times;
0553 }
0554
0555 for (; start < end; start++)
0556 str += sprintf(str, "%08x ", *(temp+start));
0557 count++;
0558 return str - buf;
0559 }
0560 static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL);
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571 static ssize_t pm8001_ctl_fatal_log_show(struct device *cdev,
0572 struct device_attribute *attr, char *buf)
0573 {
0574 ssize_t count;
0575
0576 count = pm80xx_get_fatal_dump(cdev, attr, buf);
0577 return count;
0578 }
0579
0580 static DEVICE_ATTR(fatal_log, S_IRUGO, pm8001_ctl_fatal_log_show, NULL);
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590 static ssize_t non_fatal_log_show(struct device *cdev,
0591 struct device_attribute *attr, char *buf)
0592 {
0593 u32 count;
0594
0595 count = pm80xx_get_non_fatal_dump(cdev, attr, buf);
0596 return count;
0597 }
0598 static DEVICE_ATTR_RO(non_fatal_log);
0599
0600 static ssize_t non_fatal_count_show(struct device *cdev,
0601 struct device_attribute *attr, char *buf)
0602 {
0603 struct Scsi_Host *shost = class_to_shost(cdev);
0604 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0605 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0606
0607 return snprintf(buf, PAGE_SIZE, "%08x",
0608 pm8001_ha->non_fatal_count);
0609 }
0610
0611 static ssize_t non_fatal_count_store(struct device *cdev,
0612 struct device_attribute *attr, const char *buf, size_t count)
0613 {
0614 struct Scsi_Host *shost = class_to_shost(cdev);
0615 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0616 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0617 int val = 0;
0618
0619 if (kstrtoint(buf, 16, &val) != 0)
0620 return -EINVAL;
0621
0622 pm8001_ha->non_fatal_count = val;
0623 return strlen(buf);
0624 }
0625 static DEVICE_ATTR_RW(non_fatal_count);
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635 static ssize_t pm8001_ctl_gsm_log_show(struct device *cdev,
0636 struct device_attribute *attr, char *buf)
0637 {
0638 ssize_t count;
0639
0640 count = pm8001_get_gsm_dump(cdev, SYSFS_OFFSET, buf);
0641 return count;
0642 }
0643
0644 static DEVICE_ATTR(gsm_log, S_IRUGO, pm8001_ctl_gsm_log_show, NULL);
0645
0646 #define FLASH_CMD_NONE 0x00
0647 #define FLASH_CMD_UPDATE 0x01
0648 #define FLASH_CMD_SET_NVMD 0x02
0649
0650 struct flash_command {
0651 u8 command[8];
0652 int code;
0653 };
0654
0655 static const struct flash_command flash_command_table[] = {
0656 {"set_nvmd", FLASH_CMD_SET_NVMD},
0657 {"update", FLASH_CMD_UPDATE},
0658 {"", FLASH_CMD_NONE}
0659 };
0660
0661 struct error_fw {
0662 char *reason;
0663 int err_code;
0664 };
0665
0666 static const struct error_fw flash_error_table[] = {
0667 {"Failed to open fw image file", FAIL_OPEN_BIOS_FILE},
0668 {"image header mismatch", FLASH_UPDATE_HDR_ERR},
0669 {"image offset mismatch", FLASH_UPDATE_OFFSET_ERR},
0670 {"image CRC Error", FLASH_UPDATE_CRC_ERR},
0671 {"image length Error.", FLASH_UPDATE_LENGTH_ERR},
0672 {"Failed to program flash chip", FLASH_UPDATE_HW_ERR},
0673 {"Flash chip not supported.", FLASH_UPDATE_DNLD_NOT_SUPPORTED},
0674 {"Flash update disabled.", FLASH_UPDATE_DISABLED},
0675 {"Flash in progress", FLASH_IN_PROGRESS},
0676 {"Image file size Error", FAIL_FILE_SIZE},
0677 {"Input parameter error", FAIL_PARAMETERS},
0678 {"Out of memory", FAIL_OUT_MEMORY},
0679 {"OK", 0}
0680 };
0681
0682 static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha)
0683 {
0684 struct pm8001_ioctl_payload *payload;
0685 DECLARE_COMPLETION_ONSTACK(completion);
0686 u8 *ioctlbuffer;
0687 u32 ret;
0688 u32 length = 1024 * 5 + sizeof(*payload) - 1;
0689
0690 if (pm8001_ha->fw_image->size > 4096) {
0691 pm8001_ha->fw_status = FAIL_FILE_SIZE;
0692 return -EFAULT;
0693 }
0694
0695 ioctlbuffer = kzalloc(length, GFP_KERNEL);
0696 if (!ioctlbuffer) {
0697 pm8001_ha->fw_status = FAIL_OUT_MEMORY;
0698 return -ENOMEM;
0699 }
0700 payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
0701 memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
0702 pm8001_ha->fw_image->size);
0703 payload->wr_length = pm8001_ha->fw_image->size;
0704 payload->id = 0;
0705 payload->minor_function = 0x1;
0706 pm8001_ha->nvmd_completion = &completion;
0707 ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload);
0708 if (ret) {
0709 pm8001_ha->fw_status = FAIL_OUT_MEMORY;
0710 goto out;
0711 }
0712 wait_for_completion(&completion);
0713 out:
0714 kfree(ioctlbuffer);
0715 return ret;
0716 }
0717
0718 static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)
0719 {
0720 struct pm8001_ioctl_payload *payload;
0721 DECLARE_COMPLETION_ONSTACK(completion);
0722 u8 *ioctlbuffer;
0723 struct fw_control_info *fwControl;
0724 __be32 partitionSizeTmp;
0725 u32 partitionSize;
0726 u32 loopNumber, loopcount;
0727 struct pm8001_fw_image_header *image_hdr;
0728 u32 sizeRead = 0;
0729 u32 ret = 0;
0730 u32 length = 1024 * 16 + sizeof(*payload) - 1;
0731 u32 fc_len;
0732 u8 *read_buf;
0733
0734 if (pm8001_ha->fw_image->size < 28) {
0735 pm8001_ha->fw_status = FAIL_FILE_SIZE;
0736 return -EFAULT;
0737 }
0738 ioctlbuffer = kzalloc(length, GFP_KERNEL);
0739 if (!ioctlbuffer) {
0740 pm8001_ha->fw_status = FAIL_OUT_MEMORY;
0741 return -ENOMEM;
0742 }
0743 image_hdr = (struct pm8001_fw_image_header *)pm8001_ha->fw_image->data;
0744 while (sizeRead < pm8001_ha->fw_image->size) {
0745 partitionSizeTmp =
0746 *(__be32 *)((u8 *)&image_hdr->image_length + sizeRead);
0747 partitionSize = be32_to_cpu(partitionSizeTmp);
0748 loopcount = DIV_ROUND_UP(partitionSize + HEADER_LEN,
0749 IOCTL_BUF_SIZE);
0750 for (loopNumber = 0; loopNumber < loopcount; loopNumber++) {
0751 payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
0752 payload->wr_length = 1024*16;
0753 payload->id = 0;
0754 fwControl =
0755 (struct fw_control_info *)&payload->func_specific;
0756 fwControl->len = IOCTL_BUF_SIZE;
0757 fwControl->size = partitionSize + HEADER_LEN;
0758 fwControl->retcode = 0;
0759 fwControl->offset = loopNumber * IOCTL_BUF_SIZE;
0760
0761
0762
0763
0764
0765
0766 read_buf = (u8 *)pm8001_ha->fw_image->data + sizeRead;
0767 fc_len = (partitionSize + HEADER_LEN) % IOCTL_BUF_SIZE;
0768
0769 if (loopcount - loopNumber == 1 && fc_len) {
0770 fwControl->len = fc_len;
0771 memcpy((u8 *)fwControl->buffer, read_buf, fc_len);
0772 sizeRead += fc_len;
0773 } else {
0774 memcpy((u8 *)fwControl->buffer, read_buf, IOCTL_BUF_SIZE);
0775 sizeRead += IOCTL_BUF_SIZE;
0776 }
0777
0778 pm8001_ha->nvmd_completion = &completion;
0779 ret = PM8001_CHIP_DISP->fw_flash_update_req(pm8001_ha, payload);
0780 if (ret) {
0781 pm8001_ha->fw_status = FAIL_OUT_MEMORY;
0782 goto out;
0783 }
0784 wait_for_completion(&completion);
0785 if (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS) {
0786 pm8001_ha->fw_status = fwControl->retcode;
0787 ret = -EFAULT;
0788 goto out;
0789 }
0790 }
0791 }
0792 out:
0793 kfree(ioctlbuffer);
0794 return ret;
0795 }
0796 static ssize_t pm8001_store_update_fw(struct device *cdev,
0797 struct device_attribute *attr,
0798 const char *buf, size_t count)
0799 {
0800 struct Scsi_Host *shost = class_to_shost(cdev);
0801 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0802 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0803 char *cmd_ptr, *filename_ptr;
0804 int res, i;
0805 int flash_command = FLASH_CMD_NONE;
0806 int ret;
0807
0808 if (!capable(CAP_SYS_ADMIN))
0809 return -EACCES;
0810
0811
0812
0813 if (pm8001_ha->fw_status == FLASH_IN_PROGRESS)
0814 return -EINPROGRESS;
0815 pm8001_ha->fw_status = FLASH_IN_PROGRESS;
0816
0817 cmd_ptr = kcalloc(count, 2, GFP_KERNEL);
0818 if (!cmd_ptr) {
0819 pm8001_ha->fw_status = FAIL_OUT_MEMORY;
0820 return -ENOMEM;
0821 }
0822
0823 filename_ptr = cmd_ptr + count;
0824 res = sscanf(buf, "%s %s", cmd_ptr, filename_ptr);
0825 if (res != 2) {
0826 pm8001_ha->fw_status = FAIL_PARAMETERS;
0827 ret = -EINVAL;
0828 goto out;
0829 }
0830
0831 for (i = 0; flash_command_table[i].code != FLASH_CMD_NONE; i++) {
0832 if (!memcmp(flash_command_table[i].command,
0833 cmd_ptr, strlen(cmd_ptr))) {
0834 flash_command = flash_command_table[i].code;
0835 break;
0836 }
0837 }
0838 if (flash_command == FLASH_CMD_NONE) {
0839 pm8001_ha->fw_status = FAIL_PARAMETERS;
0840 ret = -EINVAL;
0841 goto out;
0842 }
0843
0844 ret = request_firmware(&pm8001_ha->fw_image,
0845 filename_ptr,
0846 pm8001_ha->dev);
0847
0848 if (ret) {
0849 pm8001_dbg(pm8001_ha, FAIL,
0850 "Failed to load firmware image file %s, error %d\n",
0851 filename_ptr, ret);
0852 pm8001_ha->fw_status = FAIL_OPEN_BIOS_FILE;
0853 goto out;
0854 }
0855
0856 if (FLASH_CMD_UPDATE == flash_command)
0857 ret = pm8001_update_flash(pm8001_ha);
0858 else
0859 ret = pm8001_set_nvmd(pm8001_ha);
0860
0861 release_firmware(pm8001_ha->fw_image);
0862 out:
0863 kfree(cmd_ptr);
0864
0865 if (ret)
0866 return ret;
0867
0868 pm8001_ha->fw_status = FLASH_OK;
0869 return count;
0870 }
0871
0872 static ssize_t pm8001_show_update_fw(struct device *cdev,
0873 struct device_attribute *attr, char *buf)
0874 {
0875 int i;
0876 struct Scsi_Host *shost = class_to_shost(cdev);
0877 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0878 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0879
0880 for (i = 0; flash_error_table[i].err_code != 0; i++) {
0881 if (flash_error_table[i].err_code == pm8001_ha->fw_status)
0882 break;
0883 }
0884 if (pm8001_ha->fw_status != FLASH_IN_PROGRESS)
0885 pm8001_ha->fw_status = FLASH_OK;
0886
0887 return snprintf(buf, PAGE_SIZE, "status=%x %s\n",
0888 flash_error_table[i].err_code,
0889 flash_error_table[i].reason);
0890 }
0891 static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP,
0892 pm8001_show_update_fw, pm8001_store_update_fw);
0893
0894 static const char *const mpiStateText[] = {
0895 "MPI is not initialized",
0896 "MPI is successfully initialized",
0897 "MPI termination is in progress",
0898 "MPI initialization failed with error in [31:16]"
0899 };
0900
0901
0902
0903
0904
0905
0906
0907
0908
0909 static ssize_t ctl_mpi_state_show(struct device *cdev,
0910 struct device_attribute *attr, char *buf)
0911 {
0912 struct Scsi_Host *shost = class_to_shost(cdev);
0913 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0914 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0915 unsigned int mpidw0;
0916
0917 mpidw0 = pm8001_mr32(pm8001_ha->general_stat_tbl_addr, 0);
0918 return sysfs_emit(buf, "%s\n", mpiStateText[mpidw0 & 0x0003]);
0919 }
0920 static DEVICE_ATTR_RO(ctl_mpi_state);
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930 static ssize_t ctl_hmi_error_show(struct device *cdev,
0931 struct device_attribute *attr, char *buf)
0932 {
0933 struct Scsi_Host *shost = class_to_shost(cdev);
0934 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0935 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0936 unsigned int mpidw0;
0937
0938 mpidw0 = pm8001_mr32(pm8001_ha->general_stat_tbl_addr, 0);
0939 return sysfs_emit(buf, "0x%08x\n", (mpidw0 >> 16));
0940 }
0941 static DEVICE_ATTR_RO(ctl_hmi_error);
0942
0943
0944
0945
0946
0947
0948
0949
0950
0951 static ssize_t ctl_raae_count_show(struct device *cdev,
0952 struct device_attribute *attr, char *buf)
0953 {
0954 struct Scsi_Host *shost = class_to_shost(cdev);
0955 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0956 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0957 unsigned int raaecnt;
0958
0959 raaecnt = pm8001_mr32(pm8001_ha->general_stat_tbl_addr, 12);
0960 return sysfs_emit(buf, "0x%08x\n", raaecnt);
0961 }
0962 static DEVICE_ATTR_RO(ctl_raae_count);
0963
0964
0965
0966
0967
0968
0969
0970
0971
0972 static ssize_t ctl_iop0_count_show(struct device *cdev,
0973 struct device_attribute *attr, char *buf)
0974 {
0975 struct Scsi_Host *shost = class_to_shost(cdev);
0976 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0977 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0978 unsigned int iop0cnt;
0979
0980 iop0cnt = pm8001_mr32(pm8001_ha->general_stat_tbl_addr, 16);
0981 return sysfs_emit(buf, "0x%08x\n", iop0cnt);
0982 }
0983 static DEVICE_ATTR_RO(ctl_iop0_count);
0984
0985
0986
0987
0988
0989
0990
0991
0992
0993 static ssize_t ctl_iop1_count_show(struct device *cdev,
0994 struct device_attribute *attr, char *buf)
0995 {
0996 struct Scsi_Host *shost = class_to_shost(cdev);
0997 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
0998 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
0999 unsigned int iop1cnt;
1000
1001 iop1cnt = pm8001_mr32(pm8001_ha->general_stat_tbl_addr, 20);
1002 return sysfs_emit(buf, "0x%08x\n", iop1cnt);
1003
1004 }
1005 static DEVICE_ATTR_RO(ctl_iop1_count);
1006
1007 static struct attribute *pm8001_host_attrs[] = {
1008 &dev_attr_interface_rev.attr,
1009 &dev_attr_controller_fatal_error.attr,
1010 &dev_attr_fw_version.attr,
1011 &dev_attr_update_fw.attr,
1012 &dev_attr_aap_log.attr,
1013 &dev_attr_iop_log.attr,
1014 &dev_attr_fatal_log.attr,
1015 &dev_attr_non_fatal_log.attr,
1016 &dev_attr_non_fatal_count.attr,
1017 &dev_attr_gsm_log.attr,
1018 &dev_attr_max_out_io.attr,
1019 &dev_attr_max_devices.attr,
1020 &dev_attr_max_sg_list.attr,
1021 &dev_attr_sas_spec_support.attr,
1022 &dev_attr_logging_level.attr,
1023 &dev_attr_event_log_size.attr,
1024 &dev_attr_host_sas_address.attr,
1025 &dev_attr_bios_version.attr,
1026 &dev_attr_ib_log.attr,
1027 &dev_attr_ob_log.attr,
1028 &dev_attr_ila_version.attr,
1029 &dev_attr_inc_fw_ver.attr,
1030 &dev_attr_ctl_mpi_state.attr,
1031 &dev_attr_ctl_hmi_error.attr,
1032 &dev_attr_ctl_raae_count.attr,
1033 &dev_attr_ctl_iop0_count.attr,
1034 &dev_attr_ctl_iop1_count.attr,
1035 NULL,
1036 };
1037
1038 static const struct attribute_group pm8001_host_attr_group = {
1039 .attrs = pm8001_host_attrs
1040 };
1041
1042 const struct attribute_group *pm8001_host_groups[] = {
1043 &pm8001_host_attr_group,
1044 NULL
1045 };