Re: [PATCH v2 04/11] qla2xxx: Add support for online flash update for ISP27XX.

2016-01-28 Thread Johannes Thumshirn
On Wed, Jan 27, 2016 at 12:03:31PM -0500, Himanshu Madhani wrote:
> From: Sawan Chandak 
> 
> Signed-off-by: Sawan Chandak 
> Signed-off-by: Himanshu Madhani 
> ---
>  drivers/scsi/qla2xxx/qla_attr.c |   12 -
>  drivers/scsi/qla2xxx/qla_bsg.c  |   80 ++
>  drivers/scsi/qla2xxx/qla_bsg.h  |7 +++
>  drivers/scsi/qla2xxx/qla_dbg.c  |2 +-
>  drivers/scsi/qla2xxx/qla_def.h  |   22 +
>  drivers/scsi/qla2xxx/qla_fw.h   |   10 
>  drivers/scsi/qla2xxx/qla_gbl.h  |1 +
>  drivers/scsi/qla2xxx/qla_init.c |   91 
> +++
>  drivers/scsi/qla2xxx/qla_sup.c  |   47 +++-
>  9 files changed, 266 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
> index 6992ebc..fef659a 100644
> --- a/drivers/scsi/qla2xxx/qla_attr.c
> +++ b/drivers/scsi/qla2xxx/qla_attr.c
> @@ -562,6 +562,7 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject 
> *kobj,
>   struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
>   struct device, kobj)));
>   struct qla_hw_data *ha = vha->hw;
> + uint32_t faddr;
>  
>   if (unlikely(pci_channel_offline(ha->pdev)))
>   return -EAGAIN;
> @@ -569,9 +570,16 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject 
> *kobj,
>   if (!capable(CAP_SYS_ADMIN))
>   return -EINVAL;
>  
> - if (IS_NOCACHE_VPD_TYPE(ha))
> - ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
> + if (IS_NOCACHE_VPD_TYPE(ha)) {
> + faddr = ha->flt_region_vpd << 2;
> +
> + if (IS_QLA27XX(ha) &&
> + qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
> + faddr = ha->flt_region_vpd_sec << 2;
> +
> + ha->isp_ops->read_optrom(vha, ha->vpd, faddr,
>   ha->vpd_size);
> + }
>   return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size);
>  }
>  
> diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
> index c26acde..64fe17a 100644
> --- a/drivers/scsi/qla2xxx/qla_bsg.c
> +++ b/drivers/scsi/qla2xxx/qla_bsg.c
> @@ -2107,6 +2107,80 @@ qla8044_serdes_op(struct fc_bsg_job *bsg_job)
>  }
>  
>  static int
> +qla27xx_get_flash_upd_cap(struct fc_bsg_job *bsg_job)
> +{
> + struct Scsi_Host *host = bsg_job->shost;
> + scsi_qla_host_t *vha = shost_priv(host);
> + struct qla_hw_data *ha = vha->hw;
> + struct qla_flash_update_caps cap;
> +
> + if (!(IS_QLA27XX(ha)))
> + return -EPERM;
> +
> + memset(&cap, 0, sizeof(cap));
> + cap.capabilities = (uint64_t)ha->fw_attributes_ext[1] << 48 |
> +(uint64_t)ha->fw_attributes_ext[0] << 32 |
> +(uint64_t)ha->fw_attributes_h << 16 |
> +(uint64_t)ha->fw_attributes;
> +
> + sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> + bsg_job->reply_payload.sg_cnt, &cap, sizeof(cap));
> + bsg_job->reply->reply_payload_rcv_len = sizeof(cap);
> +
> + bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
> + EXT_STATUS_OK;
> +
> + bsg_job->reply_len = sizeof(struct fc_bsg_reply);
> + bsg_job->reply->result = DID_OK << 16;
> + bsg_job->job_done(bsg_job);
> + return 0;
> +}
> +
> +static int
> +qla27xx_set_flash_upd_cap(struct fc_bsg_job *bsg_job)
> +{
> + struct Scsi_Host *host = bsg_job->shost;
> + scsi_qla_host_t *vha = shost_priv(host);
> + struct qla_hw_data *ha = vha->hw;
> + uint64_t online_fw_attr = 0;
> + struct qla_flash_update_caps cap;
> +
> + if (!(IS_QLA27XX(ha)))
> + return -EPERM;
> +
> + memset(&cap, 0, sizeof(cap));
> + sg_copy_to_buffer(bsg_job->request_payload.sg_list,
> + bsg_job->request_payload.sg_cnt, &cap, sizeof(cap));
> +
> + online_fw_attr = (uint64_t)ha->fw_attributes_ext[1] << 48 |
> +  (uint64_t)ha->fw_attributes_ext[0] << 32 |
> +  (uint64_t)ha->fw_attributes_h << 16 |
> +  (uint64_t)ha->fw_attributes;
> +
> + if (online_fw_attr != cap.capabilities) {
> + bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
> + EXT_STATUS_INVALID_PARAM;
> + return -EINVAL;
> + }
> +
> + if (cap.outage_duration < MAX_LOOP_TIMEOUT)  {
> + bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
> + EXT_STATUS_INVALID_PARAM;
> + return -EINVAL;
> + }
> +
> + bsg_job->reply->reply_payload_rcv_len = 0;
> +
> + bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
> + EXT_STATUS_OK;
> +
> + bsg_job->reply_len = sizeof(struct fc_bsg_reply);
> + bsg_job->reply->result = DID_OK << 16;
> + bsg_job->job_done(bsg_job);
> + return 0;
> +}
> +
> +static int
>  qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)

[PATCH v2 04/11] qla2xxx: Add support for online flash update for ISP27XX.

2016-01-27 Thread Himanshu Madhani
From: Sawan Chandak 

Signed-off-by: Sawan Chandak 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_attr.c |   12 -
 drivers/scsi/qla2xxx/qla_bsg.c  |   80 ++
 drivers/scsi/qla2xxx/qla_bsg.h  |7 +++
 drivers/scsi/qla2xxx/qla_dbg.c  |2 +-
 drivers/scsi/qla2xxx/qla_def.h  |   22 +
 drivers/scsi/qla2xxx/qla_fw.h   |   10 
 drivers/scsi/qla2xxx/qla_gbl.h  |1 +
 drivers/scsi/qla2xxx/qla_init.c |   91 +++
 drivers/scsi/qla2xxx/qla_sup.c  |   47 +++-
 9 files changed, 266 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 6992ebc..fef659a 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -562,6 +562,7 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject 
*kobj,
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
+   uint32_t faddr;
 
if (unlikely(pci_channel_offline(ha->pdev)))
return -EAGAIN;
@@ -569,9 +570,16 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject 
*kobj,
if (!capable(CAP_SYS_ADMIN))
return -EINVAL;
 
-   if (IS_NOCACHE_VPD_TYPE(ha))
-   ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
+   if (IS_NOCACHE_VPD_TYPE(ha)) {
+   faddr = ha->flt_region_vpd << 2;
+
+   if (IS_QLA27XX(ha) &&
+   qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
+   faddr = ha->flt_region_vpd_sec << 2;
+
+   ha->isp_ops->read_optrom(vha, ha->vpd, faddr,
ha->vpd_size);
+   }
return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size);
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index c26acde..64fe17a 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -2107,6 +2107,80 @@ qla8044_serdes_op(struct fc_bsg_job *bsg_job)
 }
 
 static int
+qla27xx_get_flash_upd_cap(struct fc_bsg_job *bsg_job)
+{
+   struct Scsi_Host *host = bsg_job->shost;
+   scsi_qla_host_t *vha = shost_priv(host);
+   struct qla_hw_data *ha = vha->hw;
+   struct qla_flash_update_caps cap;
+
+   if (!(IS_QLA27XX(ha)))
+   return -EPERM;
+
+   memset(&cap, 0, sizeof(cap));
+   cap.capabilities = (uint64_t)ha->fw_attributes_ext[1] << 48 |
+  (uint64_t)ha->fw_attributes_ext[0] << 32 |
+  (uint64_t)ha->fw_attributes_h << 16 |
+  (uint64_t)ha->fw_attributes;
+
+   sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+   bsg_job->reply_payload.sg_cnt, &cap, sizeof(cap));
+   bsg_job->reply->reply_payload_rcv_len = sizeof(cap);
+
+   bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+   EXT_STATUS_OK;
+
+   bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+   bsg_job->reply->result = DID_OK << 16;
+   bsg_job->job_done(bsg_job);
+   return 0;
+}
+
+static int
+qla27xx_set_flash_upd_cap(struct fc_bsg_job *bsg_job)
+{
+   struct Scsi_Host *host = bsg_job->shost;
+   scsi_qla_host_t *vha = shost_priv(host);
+   struct qla_hw_data *ha = vha->hw;
+   uint64_t online_fw_attr = 0;
+   struct qla_flash_update_caps cap;
+
+   if (!(IS_QLA27XX(ha)))
+   return -EPERM;
+
+   memset(&cap, 0, sizeof(cap));
+   sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+   bsg_job->request_payload.sg_cnt, &cap, sizeof(cap));
+
+   online_fw_attr = (uint64_t)ha->fw_attributes_ext[1] << 48 |
+(uint64_t)ha->fw_attributes_ext[0] << 32 |
+(uint64_t)ha->fw_attributes_h << 16 |
+(uint64_t)ha->fw_attributes;
+
+   if (online_fw_attr != cap.capabilities) {
+   bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+   EXT_STATUS_INVALID_PARAM;
+   return -EINVAL;
+   }
+
+   if (cap.outage_duration < MAX_LOOP_TIMEOUT)  {
+   bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+   EXT_STATUS_INVALID_PARAM;
+   return -EINVAL;
+   }
+
+   bsg_job->reply->reply_payload_rcv_len = 0;
+
+   bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
+   EXT_STATUS_OK;
+
+   bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+   bsg_job->reply->result = DID_OK << 16;
+   bsg_job->job_done(bsg_job);
+   return 0;
+}
+
+static int
 qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
 {
switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
@@ -2161,6 +2235,12 @@ qla2x00_process_vendor_specific(struct fc_bsg_job 
*bsg_job)
case QL_VND_SERDES_OP_EX: