Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * PMC-Sierra 8001/8081/8088/8089 SAS/SATA based host adapters driver
0003  *
0004  * Copyright (c) 2008-2009 USI Co., Ltd.
0005  * All rights reserved.
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions, and the following disclaimer,
0012  *    without modification.
0013  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
0014  *    substantially similar to the "NO WARRANTY" disclaimer below
0015  *    ("Disclaimer") and any redistribution must be conditioned upon
0016  *    including a substantially similar Disclaimer requirement for further
0017  *    binary redistribution.
0018  * 3. Neither the names of the above-listed copyright holders nor the names
0019  *    of any contributors may be used to endorse or promote products derived
0020  *    from this software without specific prior written permission.
0021  *
0022  * Alternatively, this software may be distributed under the terms of the
0023  * GNU General Public License ("GPL") version 2 as published by the Free
0024  * Software Foundation.
0025  *
0026  * NO WARRANTY
0027  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0028  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0029  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
0030  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0031  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0032  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0033  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0034  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
0035  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
0036  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0037  * POSSIBILITY OF SUCH DAMAGES.
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 /* scsi host attributes */
0047 
0048 /**
0049  * pm8001_ctl_mpi_interface_rev_show - MPI interface revision number
0050  * @cdev: pointer to embedded class device
0051  * @attr: device attribute (unused)
0052  * @buf: the buffer returned
0053  *
0054  * A sysfs 'read-only' shost attribute.
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  * controller_fatal_error_show - check controller is under fatal err
0076  * @cdev: pointer to embedded class device
0077  * @attr: device attribute (unused)
0078  * @buf: the buffer returned
0079  *
0080  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_fw_version_show - firmware version
0096  * @cdev: pointer to embedded class device
0097  * @attr: device attribute (unused)
0098  * @buf: the buffer returned
0099  *
0100  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_ila_version_show - ila version
0127  * @cdev: pointer to embedded class device
0128  * @attr: device attribute (unused)
0129  * @buf: the buffer returned
0130  *
0131  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_inactive_fw_version_show - Inactive firmware version number
0153  * @cdev: pointer to embedded class device
0154  * @attr: device attribute (unused)
0155  * @buf: the buffer returned
0156  *
0157  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_max_out_io_show - max outstanding io supported
0180  * @cdev: pointer to embedded class device
0181  * @attr: device attribute (unused)
0182  * @buf: the buffer returned
0183  *
0184  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_max_devices_show - max devices support
0204  * @cdev: pointer to embedded class device
0205  * @attr: device attribute (unused)
0206  * @buf: the buffer returned
0207  *
0208  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_max_sg_list_show - max sg list supported iff not 0.0 for no
0230  * hardware limitation
0231  * @cdev: pointer to embedded class device
0232  * @attr: device attribute (unused)
0233  * @buf: the buffer returned
0234  *
0235  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_sas_spec_support_show - sas spec supported
0276  * @cdev: pointer to embedded class device
0277  * @attr: device attribute (unused)
0278  * @buf: the buffer returned
0279  *
0280  * A sysfs 'read-only' shost attribute.
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     /* fe000000 means supports SAS2.1 */
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         /* fe000000 means supports SAS2.1 */
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  * pm8001_ctl_host_sas_address_show - sas address
0304  * @cdev: pointer to embedded class device
0305  * @attr: device attribute (unused)
0306  * @buf: the buffer returned
0307  *
0308  * This is the controller sas address
0309  *
0310  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_logging_level_show - logging level
0326  * @cdev: pointer to embedded class device
0327  * @attr: device attribute (unused)
0328  * @buf: the buffer returned
0329  *
0330  * A sysfs 'read/write' shost attribute.
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  * pm8001_ctl_aap_log_show - aap1 event log
0361  * @cdev: pointer to embedded class device
0362  * @attr: device attribute (unused)
0363  * @buf: the buffer returned
0364  *
0365  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_ib_queue_log_show - Out bound Queue log
0396  * @cdev:pointer to embedded class device
0397  * @attr: device attribute (unused)
0398  * @buf: the buffer returned
0399  *
0400  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_ob_queue_log_show - Out bound Queue log
0432  * @cdev:pointer to embedded class device
0433  * @attr: device attribute (unused)
0434  * @buf: the buffer returned
0435  *
0436  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_bios_version_show - Bios version Display
0468  * @cdev:pointer to embedded class device
0469  * @attr: device attribute (unused)
0470  * @buf:the buffer returned
0471  *
0472  * A sysfs 'read-only' shost attribute.
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  * event_log_size_show - event log size
0507  * @cdev: pointer to embedded class device
0508  * @attr: device attribute (unused)
0509  * @buf: the buffer returned
0510  *
0511  * A sysfs read  shost attribute.
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  * pm8001_ctl_iop_log_show - IOP event log
0526  * @cdev: pointer to embedded class device
0527  * @attr: device attribute (unused)
0528  * @buf: the buffer returned
0529  *
0530  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_fatal_log_show - fatal error logging
0564  * @cdev:pointer to embedded class device
0565  * @attr: device attribute
0566  * @buf: the buffer returned
0567  *
0568  * A sysfs 'read-only' shost attribute.
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  * non_fatal_log_show - non fatal error logging
0584  * @cdev:pointer to embedded class device
0585  * @attr: device attribute
0586  * @buf: the buffer returned
0587  *
0588  * A sysfs 'read-only' shost attribute.
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  * pm8001_ctl_gsm_log_show - gsm dump collection
0629  * @cdev:pointer to embedded class device
0630  * @attr: device attribute (unused)
0631  * @buf: the buffer returned
0632  *
0633  * A sysfs 'read-only' shost attribute.
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} /* Last entry should be NULL. */
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}  /* Last entry err_code = 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;   /* IN */
0757             fwControl->size = partitionSize + HEADER_LEN;/* IN */
0758             fwControl->retcode = 0;/* OUT */
0759             fwControl->offset = loopNumber * IOCTL_BUF_SIZE;/*OUT */
0760 
0761             /*
0762              * for the last chunk of data in case file size is
0763              * not even with 4k, load only the rest
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     /* this test protects us from running two flash processes at once,
0812      * so we should start with this test */
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  * ctl_mpi_state_show - controller MPI state check
0903  * @cdev: pointer to embedded class device
0904  * @attr: device attribute (unused)
0905  * @buf: the buffer returned
0906  *
0907  * A sysfs 'read-only' shost attribute.
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  * ctl_hmi_error_show - controller MPI initialization fails
0924  * @cdev: pointer to embedded class device
0925  * @attr: device attribute (unused)
0926  * @buf: the buffer returned
0927  *
0928  * A sysfs 'read-only' shost attribute.
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  * ctl_raae_count_show - controller raae count check
0945  * @cdev: pointer to embedded class device
0946  * @attr: device attribute (unused)
0947  * @buf: the buffer returned
0948  *
0949  * A sysfs 'read-only' shost attribute.
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  * ctl_iop0_count_show - controller iop0 count check
0966  * @cdev: pointer to embedded class device
0967  * @attr: device attribute (unused)
0968  * @buf: the buffer returned
0969  *
0970  * A sysfs 'read-only' shost attribute.
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  * ctl_iop1_count_show - controller iop1 count check
0987  * @cdev: pointer to embedded class device
0988  * @attr: device attribute (unused)
0989  * @buf: the buffer returned
0990  *
0991  * A sysfs 'read-only' shost attribute.
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 };