1 /* 2 * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver 3 * 4 * Copyright (c) 2008-2009 USI Co., Ltd. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions, and the following disclaimer, 12 * without modification. 13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 14 * substantially similar to the "NO WARRANTY" disclaimer below 15 * ("Disclaimer") and any redistribution must be conditioned upon 16 * including a substantially similar Disclaimer requirement for further 17 * binary redistribution. 18 * 3. Neither the names of the above-listed copyright holders nor the names 19 * of any contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * Alternatively, this software may be distributed under the terms of the 23 * GNU General Public License ("GPL") version 2 as published by the Free 24 * Software Foundation. 25 * 26 * NO WARRANTY 27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGES. 38 * 39 */ 40 #include <linux/firmware.h> 41 #include "pm8001_sas.h" 42 #include "pm8001_ctl.h" 43 44 /* scsi host attributes */ 45 46 /** 47 * pm8001_ctl_mpi_interface_rev_show - MPI interface revision number 48 * @cdev: pointer to embedded class device 49 * @buf: the buffer returned 50 * 51 * A sysfs 'read-only' shost attribute. 52 */ 53 static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev, 54 struct device_attribute *attr, char *buf) 55 { 56 struct Scsi_Host *shost = class_to_shost(cdev); 57 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 58 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 59 60 return snprintf(buf, PAGE_SIZE, "%d\n", 61 pm8001_ha->main_cfg_tbl.interface_rev); 62 } 63 static 64 DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL); 65 66 /** 67 * pm8001_ctl_fw_version_show - firmware version 68 * @cdev: pointer to embedded class device 69 * @buf: the buffer returned 70 * 71 * A sysfs 'read-only' shost attribute. 72 */ 73 static ssize_t pm8001_ctl_fw_version_show(struct device *cdev, 74 struct device_attribute *attr, char *buf) 75 { 76 struct Scsi_Host *shost = class_to_shost(cdev); 77 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 78 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 79 80 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", 81 (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 24), 82 (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 16), 83 (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 8), 84 (u8)(pm8001_ha->main_cfg_tbl.firmware_rev)); 85 } 86 static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL); 87 /** 88 * pm8001_ctl_max_out_io_show - max outstanding io supported 89 * @cdev: pointer to embedded class device 90 * @buf: the buffer returned 91 * 92 * A sysfs 'read-only' shost attribute. 93 */ 94 static ssize_t pm8001_ctl_max_out_io_show(struct device *cdev, 95 struct device_attribute *attr, char *buf) 96 { 97 struct Scsi_Host *shost = class_to_shost(cdev); 98 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 99 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 100 101 return snprintf(buf, PAGE_SIZE, "%d\n", 102 pm8001_ha->main_cfg_tbl.max_out_io); 103 } 104 static DEVICE_ATTR(max_out_io, S_IRUGO, pm8001_ctl_max_out_io_show, NULL); 105 /** 106 * pm8001_ctl_max_devices_show - max devices support 107 * @cdev: pointer to embedded class device 108 * @buf: the buffer returned 109 * 110 * A sysfs 'read-only' shost attribute. 111 */ 112 static ssize_t pm8001_ctl_max_devices_show(struct device *cdev, 113 struct device_attribute *attr, char *buf) 114 { 115 struct Scsi_Host *shost = class_to_shost(cdev); 116 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 117 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 118 119 return snprintf(buf, PAGE_SIZE, "%04d\n", 120 (u16)(pm8001_ha->main_cfg_tbl.max_sgl >> 16)); 121 } 122 static DEVICE_ATTR(max_devices, S_IRUGO, pm8001_ctl_max_devices_show, NULL); 123 /** 124 * pm8001_ctl_max_sg_list_show - max sg list supported iff not 0.0 for no 125 * hardware limitation 126 * @cdev: pointer to embedded class device 127 * @buf: the buffer returned 128 * 129 * A sysfs 'read-only' shost attribute. 130 */ 131 static ssize_t pm8001_ctl_max_sg_list_show(struct device *cdev, 132 struct device_attribute *attr, char *buf) 133 { 134 struct Scsi_Host *shost = class_to_shost(cdev); 135 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 136 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 137 138 return snprintf(buf, PAGE_SIZE, "%04d\n", 139 pm8001_ha->main_cfg_tbl.max_sgl & 0x0000FFFF); 140 } 141 static DEVICE_ATTR(max_sg_list, S_IRUGO, pm8001_ctl_max_sg_list_show, NULL); 142 143 #define SAS_1_0 0x1 144 #define SAS_1_1 0x2 145 #define SAS_2_0 0x4 146 147 static ssize_t 148 show_sas_spec_support_status(unsigned int mode, char *buf) 149 { 150 ssize_t len = 0; 151 152 if (mode & SAS_1_1) 153 len = sprintf(buf, "%s", "SAS1.1"); 154 if (mode & SAS_2_0) 155 len += sprintf(buf + len, "%s%s", len ? ", " : "", "SAS2.0"); 156 len += sprintf(buf + len, "\n"); 157 158 return len; 159 } 160 161 /** 162 * pm8001_ctl_sas_spec_support_show - sas spec supported 163 * @cdev: pointer to embedded class device 164 * @buf: the buffer returned 165 * 166 * A sysfs 'read-only' shost attribute. 167 */ 168 static ssize_t pm8001_ctl_sas_spec_support_show(struct device *cdev, 169 struct device_attribute *attr, char *buf) 170 { 171 unsigned int mode; 172 struct Scsi_Host *shost = class_to_shost(cdev); 173 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 174 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 175 mode = (pm8001_ha->main_cfg_tbl.ctrl_cap_flag & 0xfe000000)>>25; 176 return show_sas_spec_support_status(mode, buf); 177 } 178 static DEVICE_ATTR(sas_spec_support, S_IRUGO, 179 pm8001_ctl_sas_spec_support_show, NULL); 180 181 /** 182 * pm8001_ctl_sas_address_show - sas address 183 * @cdev: pointer to embedded class device 184 * @buf: the buffer returned 185 * 186 * This is the controller sas address 187 * 188 * A sysfs 'read-only' shost attribute. 189 */ 190 static ssize_t pm8001_ctl_host_sas_address_show(struct device *cdev, 191 struct device_attribute *attr, char *buf) 192 { 193 struct Scsi_Host *shost = class_to_shost(cdev); 194 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 195 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 196 return snprintf(buf, PAGE_SIZE, "0x%016llx\n", 197 be64_to_cpu(*(__be64 *)pm8001_ha->sas_addr)); 198 } 199 static DEVICE_ATTR(host_sas_address, S_IRUGO, 200 pm8001_ctl_host_sas_address_show, NULL); 201 202 /** 203 * pm8001_ctl_logging_level_show - logging level 204 * @cdev: pointer to embedded class device 205 * @buf: the buffer returned 206 * 207 * A sysfs 'read/write' shost attribute. 208 */ 209 static ssize_t pm8001_ctl_logging_level_show(struct device *cdev, 210 struct device_attribute *attr, char *buf) 211 { 212 struct Scsi_Host *shost = class_to_shost(cdev); 213 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 214 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 215 216 return snprintf(buf, PAGE_SIZE, "%08xh\n", pm8001_ha->logging_level); 217 } 218 static ssize_t pm8001_ctl_logging_level_store(struct device *cdev, 219 struct device_attribute *attr, const char *buf, size_t count) 220 { 221 struct Scsi_Host *shost = class_to_shost(cdev); 222 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 223 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 224 int val = 0; 225 226 if (sscanf(buf, "%x", &val) != 1) 227 return -EINVAL; 228 229 pm8001_ha->logging_level = val; 230 return strlen(buf); 231 } 232 233 static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, 234 pm8001_ctl_logging_level_show, pm8001_ctl_logging_level_store); 235 /** 236 * pm8001_ctl_aap_log_show - aap1 event log 237 * @cdev: pointer to embedded class device 238 * @buf: the buffer returned 239 * 240 * A sysfs 'read-only' shost attribute. 241 */ 242 static ssize_t pm8001_ctl_aap_log_show(struct device *cdev, 243 struct device_attribute *attr, char *buf) 244 { 245 struct Scsi_Host *shost = class_to_shost(cdev); 246 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 247 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 248 int i; 249 #define AAP1_MEMMAP(r, c) \ 250 (*(u32 *)((u8*)pm8001_ha->memoryMap.region[AAP1].virt_ptr + (r) * 32 \ 251 + (c))) 252 253 char *str = buf; 254 int max = 2; 255 for (i = 0; i < max; i++) { 256 str += sprintf(str, "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x" 257 "0x%08x 0x%08x\n", 258 AAP1_MEMMAP(i, 0), 259 AAP1_MEMMAP(i, 4), 260 AAP1_MEMMAP(i, 8), 261 AAP1_MEMMAP(i, 12), 262 AAP1_MEMMAP(i, 16), 263 AAP1_MEMMAP(i, 20), 264 AAP1_MEMMAP(i, 24), 265 AAP1_MEMMAP(i, 28)); 266 } 267 268 return str - buf; 269 } 270 static DEVICE_ATTR(aap_log, S_IRUGO, pm8001_ctl_aap_log_show, NULL); 271 /** 272 * pm8001_ctl_aap_log_show - IOP event log 273 * @cdev: pointer to embedded class device 274 * @buf: the buffer returned 275 * 276 * A sysfs 'read-only' shost attribute. 277 */ 278 static ssize_t pm8001_ctl_iop_log_show(struct device *cdev, 279 struct device_attribute *attr, char *buf) 280 { 281 struct Scsi_Host *shost = class_to_shost(cdev); 282 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 283 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 284 #define IOP_MEMMAP(r, c) \ 285 (*(u32 *)((u8*)pm8001_ha->memoryMap.region[IOP].virt_ptr + (r) * 32 \ 286 + (c))) 287 int i; 288 char *str = buf; 289 int max = 2; 290 for (i = 0; i < max; i++) { 291 str += sprintf(str, "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x" 292 "0x%08x 0x%08x\n", 293 IOP_MEMMAP(i, 0), 294 IOP_MEMMAP(i, 4), 295 IOP_MEMMAP(i, 8), 296 IOP_MEMMAP(i, 12), 297 IOP_MEMMAP(i, 16), 298 IOP_MEMMAP(i, 20), 299 IOP_MEMMAP(i, 24), 300 IOP_MEMMAP(i, 28)); 301 } 302 303 return str - buf; 304 } 305 static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL); 306 307 #define FLASH_CMD_NONE 0x00 308 #define FLASH_CMD_UPDATE 0x01 309 #define FLASH_CMD_SET_NVMD 0x02 310 311 struct flash_command { 312 u8 command[8]; 313 int code; 314 }; 315 316 static struct flash_command flash_command_table[] = 317 { 318 {"set_nvmd", FLASH_CMD_SET_NVMD}, 319 {"update", FLASH_CMD_UPDATE}, 320 {"", FLASH_CMD_NONE} /* Last entry should be NULL. */ 321 }; 322 323 struct error_fw { 324 char *reason; 325 int err_code; 326 }; 327 328 static struct error_fw flash_error_table[] = 329 { 330 {"Failed to open fw image file", FAIL_OPEN_BIOS_FILE}, 331 {"image header mismatch", FLASH_UPDATE_HDR_ERR}, 332 {"image offset mismatch", FLASH_UPDATE_OFFSET_ERR}, 333 {"image CRC Error", FLASH_UPDATE_CRC_ERR}, 334 {"image length Error.", FLASH_UPDATE_LENGTH_ERR}, 335 {"Failed to program flash chip", FLASH_UPDATE_HW_ERR}, 336 {"Flash chip not supported.", FLASH_UPDATE_DNLD_NOT_SUPPORTED}, 337 {"Flash update disabled.", FLASH_UPDATE_DISABLED}, 338 {"Flash in progress", FLASH_IN_PROGRESS}, 339 {"Image file size Error", FAIL_FILE_SIZE}, 340 {"Input parameter error", FAIL_PARAMETERS}, 341 {"Out of memory", FAIL_OUT_MEMORY}, 342 {"OK", 0} /* Last entry err_code = 0. */ 343 }; 344 345 static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha) 346 { 347 struct pm8001_ioctl_payload *payload; 348 DECLARE_COMPLETION_ONSTACK(completion); 349 u8 *ioctlbuffer = NULL; 350 u32 length = 0; 351 u32 ret = 0; 352 353 length = 1024 * 5 + sizeof(*payload) - 1; 354 ioctlbuffer = kzalloc(length, GFP_KERNEL); 355 if (!ioctlbuffer) 356 return -ENOMEM; 357 if ((pm8001_ha->fw_image->size <= 0) || 358 (pm8001_ha->fw_image->size > 4096)) { 359 ret = FAIL_FILE_SIZE; 360 goto out; 361 } 362 payload = (struct pm8001_ioctl_payload *)ioctlbuffer; 363 memcpy((u8 *)payload->func_specific, (u8 *)pm8001_ha->fw_image->data, 364 pm8001_ha->fw_image->size); 365 payload->length = pm8001_ha->fw_image->size; 366 payload->id = 0; 367 pm8001_ha->nvmd_completion = &completion; 368 ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload); 369 wait_for_completion(&completion); 370 out: 371 kfree(ioctlbuffer); 372 return ret; 373 } 374 375 static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) 376 { 377 struct pm8001_ioctl_payload *payload; 378 DECLARE_COMPLETION_ONSTACK(completion); 379 u8 *ioctlbuffer = NULL; 380 u32 length = 0; 381 struct fw_control_info *fwControl; 382 u32 loopNumber, loopcount = 0; 383 u32 sizeRead = 0; 384 u32 partitionSize, partitionSizeTmp; 385 u32 ret = 0; 386 u32 partitionNumber = 0; 387 struct pm8001_fw_image_header *image_hdr; 388 389 length = 1024 * 16 + sizeof(*payload) - 1; 390 ioctlbuffer = kzalloc(length, GFP_KERNEL); 391 image_hdr = (struct pm8001_fw_image_header *)pm8001_ha->fw_image->data; 392 if (!ioctlbuffer) 393 return -ENOMEM; 394 if (pm8001_ha->fw_image->size < 28) { 395 ret = FAIL_FILE_SIZE; 396 goto out; 397 } 398 399 while (sizeRead < pm8001_ha->fw_image->size) { 400 partitionSizeTmp = 401 *(u32 *)((u8 *)&image_hdr->image_length + sizeRead); 402 partitionSize = be32_to_cpu(partitionSizeTmp); 403 loopcount = (partitionSize + HEADER_LEN)/IOCTL_BUF_SIZE; 404 if (loopcount % IOCTL_BUF_SIZE) 405 loopcount++; 406 if (loopcount == 0) 407 loopcount++; 408 for (loopNumber = 0; loopNumber < loopcount; loopNumber++) { 409 payload = (struct pm8001_ioctl_payload *)ioctlbuffer; 410 payload->length = 1024*16; 411 payload->id = 0; 412 fwControl = 413 (struct fw_control_info *)payload->func_specific; 414 fwControl->len = IOCTL_BUF_SIZE; /* IN */ 415 fwControl->size = partitionSize + HEADER_LEN;/* IN */ 416 fwControl->retcode = 0;/* OUT */ 417 fwControl->offset = loopNumber * IOCTL_BUF_SIZE;/*OUT */ 418 419 /* for the last chunk of data in case file size is not even with 420 4k, load only the rest*/ 421 if (((loopcount-loopNumber) == 1) && 422 ((partitionSize + HEADER_LEN) % IOCTL_BUF_SIZE)) { 423 fwControl->len = 424 (partitionSize + HEADER_LEN) % IOCTL_BUF_SIZE; 425 memcpy((u8 *)fwControl->buffer, 426 (u8 *)pm8001_ha->fw_image->data + sizeRead, 427 (partitionSize + HEADER_LEN) % IOCTL_BUF_SIZE); 428 sizeRead += 429 (partitionSize + HEADER_LEN) % IOCTL_BUF_SIZE; 430 } else { 431 memcpy((u8 *)fwControl->buffer, 432 (u8 *)pm8001_ha->fw_image->data + sizeRead, 433 IOCTL_BUF_SIZE); 434 sizeRead += IOCTL_BUF_SIZE; 435 } 436 437 pm8001_ha->nvmd_completion = &completion; 438 ret = PM8001_CHIP_DISP->fw_flash_update_req(pm8001_ha, payload); 439 wait_for_completion(&completion); 440 if (ret || (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS)) { 441 ret = fwControl->retcode; 442 kfree(ioctlbuffer); 443 ioctlbuffer = NULL; 444 break; 445 } 446 } 447 if (ret) 448 break; 449 partitionNumber++; 450 } 451 out: 452 kfree(ioctlbuffer); 453 return ret; 454 } 455 static ssize_t pm8001_store_update_fw(struct device *cdev, 456 struct device_attribute *attr, 457 const char *buf, size_t count) 458 { 459 struct Scsi_Host *shost = class_to_shost(cdev); 460 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 461 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 462 char *cmd_ptr, *filename_ptr; 463 int res, i; 464 int flash_command = FLASH_CMD_NONE; 465 int err = 0; 466 if (!capable(CAP_SYS_ADMIN)) 467 return -EACCES; 468 469 cmd_ptr = kzalloc(count*2, GFP_KERNEL); 470 471 if (!cmd_ptr) { 472 err = FAIL_OUT_MEMORY; 473 goto out; 474 } 475 476 filename_ptr = cmd_ptr + count; 477 res = sscanf(buf, "%s %s", cmd_ptr, filename_ptr); 478 if (res != 2) { 479 err = FAIL_PARAMETERS; 480 goto out1; 481 } 482 483 for (i = 0; flash_command_table[i].code != FLASH_CMD_NONE; i++) { 484 if (!memcmp(flash_command_table[i].command, 485 cmd_ptr, strlen(cmd_ptr))) { 486 flash_command = flash_command_table[i].code; 487 break; 488 } 489 } 490 if (flash_command == FLASH_CMD_NONE) { 491 err = FAIL_PARAMETERS; 492 goto out1; 493 } 494 495 if (pm8001_ha->fw_status == FLASH_IN_PROGRESS) { 496 err = FLASH_IN_PROGRESS; 497 goto out1; 498 } 499 err = request_firmware(&pm8001_ha->fw_image, 500 filename_ptr, 501 pm8001_ha->dev); 502 503 if (err) { 504 PM8001_FAIL_DBG(pm8001_ha, 505 pm8001_printk("Failed to load firmware image file %s," 506 " error %d\n", filename_ptr, err)); 507 err = FAIL_OPEN_BIOS_FILE; 508 goto out1; 509 } 510 511 switch (flash_command) { 512 case FLASH_CMD_UPDATE: 513 pm8001_ha->fw_status = FLASH_IN_PROGRESS; 514 err = pm8001_update_flash(pm8001_ha); 515 break; 516 case FLASH_CMD_SET_NVMD: 517 pm8001_ha->fw_status = FLASH_IN_PROGRESS; 518 err = pm8001_set_nvmd(pm8001_ha); 519 break; 520 default: 521 pm8001_ha->fw_status = FAIL_PARAMETERS; 522 err = FAIL_PARAMETERS; 523 break; 524 } 525 release_firmware(pm8001_ha->fw_image); 526 out1: 527 kfree(cmd_ptr); 528 out: 529 pm8001_ha->fw_status = err; 530 531 if (!err) 532 return count; 533 else 534 return -err; 535 } 536 537 static ssize_t pm8001_show_update_fw(struct device *cdev, 538 struct device_attribute *attr, char *buf) 539 { 540 int i; 541 struct Scsi_Host *shost = class_to_shost(cdev); 542 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 543 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; 544 545 for (i = 0; flash_error_table[i].err_code != 0; i++) { 546 if (flash_error_table[i].err_code == pm8001_ha->fw_status) 547 break; 548 } 549 if (pm8001_ha->fw_status != FLASH_IN_PROGRESS) 550 pm8001_ha->fw_status = FLASH_OK; 551 552 return snprintf(buf, PAGE_SIZE, "status=%x %s\n", 553 flash_error_table[i].err_code, 554 flash_error_table[i].reason); 555 } 556 557 static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUGO, 558 pm8001_show_update_fw, pm8001_store_update_fw); 559 struct device_attribute *pm8001_host_attrs[] = { 560 &dev_attr_interface_rev, 561 &dev_attr_fw_version, 562 &dev_attr_update_fw, 563 &dev_attr_aap_log, 564 &dev_attr_iop_log, 565 &dev_attr_max_out_io, 566 &dev_attr_max_devices, 567 &dev_attr_max_sg_list, 568 &dev_attr_sas_spec_support, 569 &dev_attr_logging_level, 570 &dev_attr_host_sas_address, 571 NULL, 572 }; 573 574