[PATCH v2 11/37] qla2xxx: Add option for use reserve exch for ELS

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Add option to tell FW to reserve 1/2 of emergency exchanges for ELS.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_gbl.h  | 1 +
 drivers/scsi/qla2xxx/qla_init.c | 6 ++
 drivers/scsi/qla2xxx/qla_os.c   | 6 ++
 3 files changed, 13 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index cf1f1a3baf21..aabd49ef95a3 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -148,6 +148,7 @@ extern int ql2xuctrlirq;
 extern int ql2xnvmeenable;
 extern int ql2xautodetectsfp;
 extern int ql2xenablemsix;
+extern int qla2xuseresexchforels;
 
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 728c66f34666..39d1edc6c2b1 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3348,6 +3348,12 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
ha->fw_options[2] |= BIT_4;
else
ha->fw_options[2] &= ~BIT_4;
+
+   /* Reserve 1/2 of emergency exchanges for ELS.*/
+   if (qla2xuseresexchforels)
+   ha->fw_options[2] |= BIT_8;
+   else
+   ha->fw_options[2] &= ~BIT_8;
}
 
ql_dbg(ql_dbg_init, vha, 0x00e8,
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index e1761bd552fe..487e1affacf4 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -277,6 +277,12 @@ MODULE_PARM_DESC(ql2xenablemsix,
 " 1 -- enable MSI-X interrupt mechanism.\n"
 " 2 -- enable MSI interrupt mechanism.\n");
 
+int qla2xuseresexchforels;
+module_param(qla2xuseresexchforels, int, 0444);
+MODULE_PARM_DESC(qla2xuseresexchforels,
+"Reserve 1/2 of emergency exchanges for ELS.\n"
+" 0 (default): disabled");
+
 /*
  * SCSI host template entry points
  */
-- 
2.12.0



[PATCH v2 16/37] qla2xxx: Fix session cleanup for N2N

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

When connection type is N_Port to N_Port (point-to-point), there
is a possibilty where initiator will not send PLOGI request and
will directly send PRLI. In N2N connection the port has higher
port name sends the PLOGI but not allow to send PRLI if is a
target mode. Only initiator is allowed to send PRLI.

Current driver code deletes old session when it receives PLOGI
request. If we will not receive PLOGI request then we will not
delete old session and create new session. Add check for N2N
with PRLI receive only and trigger cleanup. For this case, the
cleanup requires individual cmd abort instead of using implicit
logout as a broad stroke flush.

Signed-off-by: Krishna Kant 
Signed-off-by: Alexei Potashnik 
Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h|  11 ++
 drivers/scsi/qla2xxx/qla_fw.h |   2 +-
 drivers/scsi/qla2xxx/qla_init.c   | 151 +---
 drivers/scsi/qla2xxx/qla_isr.c|   4 +-
 drivers/scsi/qla2xxx/qla_mbx.c|  38 -
 drivers/scsi/qla2xxx/qla_os.c |  41 +-
 drivers/scsi/qla2xxx/qla_target.c | 286 +-
 7 files changed, 378 insertions(+), 155 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 7a42aad55ec3..a7b810213aac 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3508,6 +3508,7 @@ struct qla_hw_data {
 
uint32_tdetected_lr_sfp:1;
uint32_tusing_lr_setting:1;
+   uint32_trida_fmt2:1;
} flags;
 
uint16_t max_exchg;
@@ -4529,6 +4530,16 @@ struct sff_8247_a0 {
 #define USER_CTRL_IRQ(_ha) (ql2xuctrlirq && QLA_TGT_MODE_ENABLED() && \
(IS_QLA27XX(_ha) || IS_QLA83XX(_ha)))
 
+#define SAVE_TOPO(_ha) { \
+   if (_ha->current_topology)  \
+   _ha->prev_topology = _ha->current_topology; \
+}
+
+#define N2N_TOPO(ha) \
+   ((ha->prev_topology == ISP_CFG_N && !ha->current_topology) || \
+ha->current_topology == ISP_CFG_N || \
+!ha->current_topology)
+
 #include "qla_target.h"
 #include "qla_gbl.h"
 #include "qla_dbg.h"
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index d5cef0727e72..5d8688e5bc7c 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -1392,7 +1392,7 @@ struct vp_rpt_id_entry_24xx {
 
uint8_t port_name[8];
uint8_t node_name[8];
-   uint32_t remote_nport_id;
+   uint8_t remote_nport_id[4];
uint32_t reserved_5;
} f2;
} u;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 34ee8c755655..c671852131ef 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -181,11 +181,6 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t 
*fcport,
if (!vha->flags.online)
goto done;
 
-   if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
-   (fcport->fw_login_state == DSC_LS_PLOGI_COMP) ||
-   (fcport->fw_login_state == DSC_LS_PRLI_PEND))
-   goto done;
-
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
@@ -1013,6 +1008,43 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
spin_unlock_irqrestore(>hw->tgt.sess_lock, flags);
 } /* gpdb event */
 
+
+static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+   u8 login = 0;
+
+   if (qla_tgt_mode_enabled(vha))
+   return;
+
+   if (qla_dual_mode_enabled(vha)) {
+   if (N2N_TOPO(vha->hw)) {
+   u64 mywwn, wwn;
+
+   mywwn = wwn_to_u64(vha->port_name);
+   wwn = wwn_to_u64(fcport->port_name);
+   if (mywwn > wwn)
+   login = 1;
+   else if ((fcport->fw_login_state == DSC_LS_PLOGI_COMP)
+   && time_after_eq(jiffies,
+   fcport->plogi_nack_done_deadline))
+   login = 1;
+   } else {
+   login = 1;
+   }
+   } else {
+   /* initiator mode */
+   login = 1;
+   }
+
+   if (login) {
+   ql_dbg(ql_dbg_disc, vha, 0x20bf,
+   "%s %d %8phC post login\n",
+   __func__, __LINE__, fcport->port_name);
+   fcport->disc_state = DSC_LOGIN_PEND;
+   qla2x00_post_async_login_work(vha, fcport, NULL);
+   }
+}
+
 int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)

[PATCH v2 14/37] qla2xxx: Allow target mode to accept PRLI in dual mode

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

For Dual Mode, Initiator side of the driver finish login,
target side receive PRLI, but driver terminates PRLI.
This patch allows target side to go ahead and accept PRLI.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_init.c   |  5 +
 drivers/scsi/qla2xxx/qla_target.c | 16 +---
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 4e6d3eb4caa4..34ee8c755655 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1537,6 +1537,7 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host 
*vha, struct event_arg *ea)
port_id_t cid;  /* conflict Nport id */
u16 lid;
struct fc_port *conflict_fcport;
+   unsigned long flags;
 
switch (ea->data[0]) {
case MBS_COMMAND_COMPLETE:
@@ -1557,10 +1558,14 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host 
*vha, struct event_arg *ea)
ea->fcport->loop_id, ea->fcport->d_id.b24);
 
set_bit(ea->fcport->loop_id, vha->hw->loop_id_map);
+   spin_lock_irqsave(>hw->tgt.sess_lock, flags);
ea->fcport->loop_id = FC_NO_LOOP_ID;
ea->fcport->chip_reset = 
vha->hw->base_qpair->chip_reset;
ea->fcport->logout_on_delete = 1;
ea->fcport->send_els_logo = 0;
+   ea->fcport->fw_login_state = DSC_LS_PRLI_COMP;
+   spin_unlock_irqrestore(>hw->tgt.sess_lock, flags);
+
qla24xx_post_gpdb_work(vha, ea->fcport, 0);
}
break;
diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index db6fd3b747ed..52a412132abb 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -4682,7 +4682,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
uint16_t wd3_lo;
int res = 0;
struct qlt_plogi_ack_t *pla;
-   unsigned long flags;
+   unsigned long flags = 0;
 
wwn = wwn_to_u64(iocb->u.isp24.port_name);
 
@@ -4818,8 +4818,14 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
}
 
if (sess != NULL) {
-   if (sess->fw_login_state != DSC_LS_PLOGI_PEND &&
-   sess->fw_login_state != DSC_LS_PLOGI_COMP) {
+   spin_lock_irqsave(>ha->tgt.sess_lock, flags);
+   switch (sess->fw_login_state) {
+   case DSC_LS_PLOGI_COMP:
+   case DSC_LS_PRLI_COMP:
+   break;
+   default:
+   spin_unlock_irqrestore(>ha->tgt.sess_lock,
+   flags);
/*
 * Impatient initiator sent PRLI before last
 * PLOGI could finish. Will force him to re-try,
@@ -4830,6 +4836,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
sess);
qlt_send_term_imm_notif(vha, iocb, 1);
res = 0;
+   spin_lock_irqsave(>ha->tgt.sess_lock,
+   flags);
break;
}
 
@@ -4853,6 +4861,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
sess->port_type = FCT_INITIATOR;
else
sess->port_type = FCT_TARGET;
+
+   spin_unlock_irqrestore(>ha->tgt.sess_lock, flags);
}
res = 1; /* send notify ack */
 
-- 
2.12.0



[PATCH v2 18/37] qla2xxx: Add switch command to simplify fabric discovery

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

- add "async" gpn_ft, gnn_ft, gfpn_id, gnn_id switch commands.
- For 8G and newer adapters, use async commands when it comes to
fabric scan to reduce bottle neck.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_attr.c   |   2 +
 drivers/scsi/qla2xxx/qla_def.h|  72 +++-
 drivers/scsi/qla2xxx/qla_gbl.h|  15 +-
 drivers/scsi/qla2xxx/qla_gs.c | 711 +-
 drivers/scsi/qla2xxx/qla_init.c   | 308 +++--
 drivers/scsi/qla2xxx/qla_mbx.c|   5 +-
 drivers/scsi/qla2xxx/qla_os.c |  47 ++-
 drivers/scsi/qla2xxx/qla_target.c |  62 +++-
 drivers/scsi/qla2xxx/qla_target.h |   2 +-
 9 files changed, 1103 insertions(+), 121 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 9ce28c4f9812..b360df9936ff 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -2170,6 +2170,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
dma_free_coherent(>pdev->dev, vha->gnl.size, vha->gnl.l,
vha->gnl.ldma);
 
+   vfree(vha->scan.l);
+
if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) {
if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
ql_log(ql_log_warn, vha, 0x7087,
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index bf50b4fbe648..240767c862e6 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2270,11 +2270,13 @@ struct ct_sns_desc {
 
 enum discovery_state {
DSC_DELETED,
+   DSC_GNN_ID,
DSC_GID_PN,
DSC_GNL,
DSC_LOGIN_PEND,
DSC_LOGIN_FAILED,
DSC_GPDB,
+   DSC_GFPN_ID,
DSC_GPSC,
DSC_UPD_FCPORT,
DSC_LOGIN_COMPLETE,
@@ -2304,8 +2306,9 @@ enum fcport_mgt_event {
FCME_GPDB_DONE,
FCME_GPNID_DONE,
FCME_GFFID_DONE,
-   FCME_DELETE_DONE,
FCME_ADISC_DONE,
+   FCME_GNNID_DONE,
+   FCME_GFPNID_DONE,
 };
 
 enum rscn_addr_format {
@@ -2338,6 +2341,7 @@ typedef struct fc_port {
unsigned int login_pause:1;
unsigned int login_succ:1;
unsigned int query:1;
+   unsigned int id_changed:1;
 
struct work_struct nvme_del_work;
struct completion nvme_del_done;
@@ -2485,6 +2489,11 @@ static const char * const port_state_str[] = {
 #defineGA_NXT_REQ_SIZE (16 + 4)
 #defineGA_NXT_RSP_SIZE (16 + 620)
 
+#defineGPN_FT_CMD  0x172
+#defineGPN_FT_REQ_SIZE (16 + 4)
+#defineGNN_FT_CMD  0x173
+#defineGNN_FT_REQ_SIZE (16 + 4)
+
 #defineGID_PT_CMD  0x1A1
 #defineGID_PT_REQ_SIZE (16 + 4)
 
@@ -2740,6 +2749,13 @@ struct ct_sns_req {
} port_id;
 
struct {
+   uint8_t reserved;
+   uint8_t domain;
+   uint8_t area;
+   uint8_t port_type;
+   } gpn_ft;
+
+   struct {
uint8_t port_type;
uint8_t domain;
uint8_t area;
@@ -2852,6 +2868,27 @@ struct ct_sns_gid_pt_data {
uint8_t port_id[3];
 };
 
+/* It's the same for both GPN_FT and GNN_FT */
+struct ct_sns_gpnft_rsp {
+   struct {
+   struct ct_cmd_hdr header;
+   uint16_t response;
+   uint16_t residual;
+   uint8_t fragment_id;
+   uint8_t reason_code;
+   uint8_t explanation_code;
+   uint8_t vendor_unique;
+   };
+   /* Assume the largest number of targets for the union */
+   struct ct_sns_gpn_ft_data {
+   u8 control_byte;
+   u8 port_id[3];
+   u32 reserved;
+   u8 port_name[8];
+   } entries[1];
+};
+
+/* CT command response */
 struct ct_sns_rsp {
struct ct_rsp_hdr header;
 
@@ -2927,6 +2964,24 @@ struct ct_sns_pkt {
} p;
 };
 
+struct ct_sns_gpnft_pkt {
+   union {
+   struct ct_sns_req req;
+   struct ct_sns_gpnft_rsp rsp;
+   } p;
+};
+
+struct fab_scan_rp {
+   port_id_t id;
+   u8 port_name[8];
+   u8 node_name[8];
+};
+
+struct fab_scan {
+   struct fab_scan_rp *l;
+   u32 size;
+};
+
 /*
  * SNS command structures -- for 2200 compatibility.
  */
@@ -3143,6 +3198,11 @@ enum qla_work_type {
QLA_EVT_RELOGIN,
QLA_EVT_ASYNC_PRLO,
QLA_EVT_ASYNC_PRLO_DONE,
+   QLA_EVT_GPNFT,
+   QLA_EVT_GPNFT_DONE,
+   QLA_EVT_GNNFT_DONE,
+   QLA_EVT_GNNID,
+   QLA_EVT_GFPNID,
 };
 
 
@@ -3184,7 +3244,9 @@ struct qla_work_evt {
struct {
port_id_t id;
u8 port_name[8];
+   u8 node_name[8];
void *pla;
+  

[PATCH v2 33/37] qla2xxx: Prevent relogin trigger from sending too many commands

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

This patch adds check for pending work event before queueing
relogin work to prevent redundant work to be active at the
same time.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h  |  1 +
 drivers/scsi/qla2xxx/qla_gs.c   |  6 --
 drivers/scsi/qla2xxx/qla_init.c | 14 +-
 drivers/scsi/qla2xxx/qla_os.c   |  4 +++-
 4 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 99d2afa520c2..ac2f340bc1c6 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2454,6 +2454,7 @@ static const char * const port_state_str[] = {
 #define FCF_FCP2_DEVICEBIT_2
 #define FCF_ASYNC_SENT BIT_3
 #define FCF_CONF_COMP_SUPPORTED BIT_4
+#define FCF_ASYNC_ACTIVE   BIT_5
 
 /* No loop ID flag. */
 #define FC_NO_LOOP_ID  0x1000
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index abc31b983b93..546011b1a765 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3088,7 +3088,7 @@ static void qla2x00_async_gidpn_sp_done(void *s, int res)
u8 *id = fcport->ct_desc.ct_sns->p.rsp.rsp.gid_pn.port_id;
struct event_arg ea;
 
-   fcport->flags &= ~FCF_ASYNC_SENT;
+   fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 
memset(, 0, sizeof(ea));
ea.fcport = fcport;
@@ -3197,6 +3197,7 @@ int qla24xx_post_gidpn_work(struct scsi_qla_host *vha, 
fc_port_t *fcport)
return QLA_FUNCTION_FAILED;
 
e->u.fcport.fcport = fcport;
+   fcport->flags |= FCF_ASYNC_ACTIVE;
return qla2x00_post_work(vha, e);
 }
 
@@ -3209,6 +3210,7 @@ int qla24xx_post_gpsc_work(struct scsi_qla_host *vha, 
fc_port_t *fcport)
return QLA_FUNCTION_FAILED;
 
e->u.fcport.fcport = fcport;
+   fcport->flags |= FCF_ASYNC_ACTIVE;
return qla2x00_post_work(vha, e);
 }
 
@@ -3256,7 +3258,7 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res)
"Async done-%s res %x, WWPN %8phC \n",
sp->name, res, fcport->port_name);
 
-   fcport->flags &= ~FCF_ASYNC_SENT;
+   fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 
if (res == (DID_ERROR << 16)) {
/* entry status error */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 93febc177aa7..956f51e78e5c 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -109,7 +109,7 @@ qla2x00_async_iocb_timeout(void *data)
"Async-%s timeout - hdl=%x portid=%06x %8phC.\n",
sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
 
-   fcport->flags &= ~FCF_ASYNC_SENT;
+   fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
} else {
pr_info("Async-%s timeout - hdl=%x.\n",
sp->name, sp->handle);
@@ -154,7 +154,8 @@ qla2x00_async_login_sp_done(void *ptr, int res)
ql_dbg(ql_dbg_disc, vha, 0x20dd,
"%s %8phC res %d \n", __func__, sp->fcport->port_name, res);
 
-   sp->fcport->flags &= ~FCF_ASYNC_SENT;
+   sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
+
if (!test_bit(UNLOADING, >dpc_flags)) {
memset(, 0, sizeof(ea));
ea.event = FCME_PLOGI_DONE;
@@ -232,7 +233,7 @@ qla2x00_async_logout_sp_done(void *ptr, int res)
srb_t *sp = ptr;
struct srb_iocb *lio = >u.iocb_cmd;
 
-   sp->fcport->flags &= ~FCF_ASYNC_SENT;
+   sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
if (!test_bit(UNLOADING, >vha->dpc_flags))
qla2x00_post_async_logout_done_work(sp->vha, sp->fcport,
lio->u.logio.data);
@@ -665,7 +666,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
 
list_for_each_entry_safe(fcport, tf, , gnl_entry) {
list_del_init(>gnl_entry);
-   fcport->flags &= ~FCF_ASYNC_SENT;
+   fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
ea.fcport = fcport;
 
qla2x00_fcport_event_handler(vha, );
@@ -788,6 +789,7 @@ int qla24xx_post_gnl_work(struct scsi_qla_host *vha, 
fc_port_t *fcport)
return QLA_FUNCTION_FAILED;
 
e->u.fcport.fcport = fcport;
+   fcport->flags |= FCF_ASYNC_ACTIVE;
return qla2x00_post_work(vha, e);
 }
 
@@ -805,7 +807,7 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
"Async done-%s res %x, WWPN %8phC mb[1]=%x mb[2]=%x \n",
sp->name, res, fcport->port_name, mb[1], mb[2]);
 
-   fcport->flags &= ~FCF_ASYNC_SENT;
+   fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 
memset(, 0, sizeof(ea));
ea.event = FCME_GPDB_DONE;
@@ -927,6 +929,7 @@ int 

[PATCH v2 34/37] qla2xxx: Remove unused argument from qlt_schedule_sess_for_deletion()

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Immeadiate flag is not used for scheduling session deletion.
Remove it to simplfy session deletion code path.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_gbl.h|  2 +-
 drivers/scsi/qla2xxx/qla_init.c   | 10 +-
 drivers/scsi/qla2xxx/qla_target.c | 16 +++-
 3 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 3f3863c09de2..47bff9ab1176 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -887,7 +887,7 @@ void qla24xx_do_nack_work(struct scsi_qla_host *, struct 
qla_work_evt *);
 void qlt_plogi_ack_link(struct scsi_qla_host *, struct qlt_plogi_ack_t *,
struct fc_port *, enum qlt_plogi_link_t);
 void qlt_plogi_ack_unref(struct scsi_qla_host *, struct qlt_plogi_ack_t *);
-extern void qlt_schedule_sess_for_deletion(struct fc_port *, bool);
+extern void qlt_schedule_sess_for_deletion(struct fc_port *);
 extern void qlt_schedule_sess_for_deletion_lock(struct fc_port *);
 extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 956f51e78e5c..aaa8c07b2d8d 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -353,7 +353,7 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
ql_dbg(ql_dbg_disc, vha, 0x2066,
"%s %8phC: adisc fail: post delete\n",
__func__, ea->fcport->port_name);
-   qlt_schedule_sess_for_deletion(ea->fcport, 1);
+   qlt_schedule_sess_for_deletion(ea->fcport);
return;
}
 
@@ -527,7 +527,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t 
*vha,
ql_dbg(ql_dbg_disc, vha, 0x20e3,
"%s %d %8phC post del sess\n",
__func__, __LINE__, fcport->port_name);
-   qlt_schedule_sess_for_deletion(fcport, 1);
+   qlt_schedule_sess_for_deletion(fcport);
return;
}
 
@@ -599,7 +599,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t 
*vha,
__func__, __LINE__,
conflict_fcport->port_name);
qlt_schedule_sess_for_deletion
-   (conflict_fcport, 1);
+   (conflict_fcport);
}
 
/* FW already picked this loop id for another fcport */
@@ -1134,7 +1134,7 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host 
*vha, fc_port_t *fcport)
"%s %d %8phC post del sess - out of 
loopid\n",
__func__, __LINE__, fcport->port_name);
fcport->scan_state = 0;
-   qlt_schedule_sess_for_deletion(fcport, true);
+   qlt_schedule_sess_for_deletion(fcport);
return;
}
}
@@ -1780,7 +1780,7 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host 
*vha, struct event_arg *ea)
set_bit(lid, vha->hw->loop_id_map);
ea->fcport->loop_id = lid;
ea->fcport->keep_nport_handle = 0;
-   qlt_schedule_sess_for_deletion(ea->fcport, false);
+   qlt_schedule_sess_for_deletion(ea->fcport);
}
break;
}
diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index 786efdb5788a..867d089c3ebe 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -1211,8 +1211,7 @@ static void qla24xx_chk_fcp_state(struct fc_port *sess)
 }
 
 /* ha->tgt.sess_lock supposed to be held on entry */
-void qlt_schedule_sess_for_deletion(struct fc_port *sess,
-   bool immediate)
+void qlt_schedule_sess_for_deletion(struct fc_port *sess)
 {
struct qla_tgt *tgt = sess->tgt;
 
@@ -1252,7 +1251,7 @@ void qlt_schedule_sess_for_deletion_lock(struct fc_port 
*sess)
unsigned long flags;
struct qla_hw_data *ha = sess->vha->hw;
spin_lock_irqsave(>tgt.sess_lock, flags);
-   qlt_schedule_sess_for_deletion(sess, 1);
+   qlt_schedule_sess_for_deletion(sess);
spin_unlock_irqrestore(>tgt.sess_lock, flags);
 }
 
@@ -1264,7 +1263,7 @@ static void qlt_clear_tgt_db(struct qla_tgt *tgt)
 
list_for_each_entry(sess, >vp_fcports, list) {
if (sess->se_sess)
-   

[PATCH v2 32/37] qla2xxx: Prevent multiple active discovery commands per session

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Add check to allow single discovery command per session to be sent

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_gs.c   | 34 +-
 drivers/scsi/qla2xxx/qla_init.c | 30 +++---
 2 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 8e09f6f16643..abc31b983b93 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3127,16 +3127,16 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t 
*fcport)
struct ct_sns_req   *ct_req;
srb_t *sp;
 
-   if (!vha->flags.online)
-   goto done;
+   if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+   return rval;
 
-   fcport->flags |= FCF_ASYNC_SENT;
fcport->disc_state = DSC_GID_PN;
fcport->scan_state = QLA_FCPORT_SCAN;
sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
if (!sp)
goto done;
 
+   fcport->flags |= FCF_ASYNC_SENT;
sp->type = SRB_CT_PTHRU_CMD;
sp->name = "gidpn";
sp->gen1 = fcport->rscn_gen;
@@ -3177,8 +3177,8 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t 
*fcport)
 
 done_free_sp:
sp->free(sp);
-done:
fcport->flags &= ~FCF_ASYNC_SENT;
+done:
return rval;
 }
 
@@ -3319,14 +3319,14 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t 
*fcport)
struct ct_sns_req   *ct_req;
srb_t *sp;
 
-   if (!vha->flags.online)
-   goto done;
+   if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+   return rval;
 
-   fcport->flags |= FCF_ASYNC_SENT;
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
 
+   fcport->flags |= FCF_ASYNC_SENT;
sp->type = SRB_CT_PTHRU_CMD;
sp->name = "gpsc";
sp->gen1 = fcport->rscn_gen;
@@ -3366,8 +3366,8 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t 
*fcport)
 
 done_free_sp:
sp->free(sp);
-done:
fcport->flags &= ~FCF_ASYNC_SENT;
+done:
return rval;
 }
 
@@ -3780,7 +3780,7 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t 
*fcport)
struct ct_sns_req   *ct_req;
srb_t *sp;
 
-   if (!vha->flags.online)
+   if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
return rval;
 
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
@@ -4337,15 +4337,15 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t 
*fcport)
struct ct_sns_req   *ct_req;
srb_t *sp;
 
-   if (!vha->flags.online)
-   goto done;
+   if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+   return rval;
 
-   fcport->flags |= FCF_ASYNC_SENT;
fcport->disc_state = DSC_GNN_ID;
sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
if (!sp)
goto done;
 
+   fcport->flags |= FCF_ASYNC_SENT;
sp->type = SRB_CT_PTHRU_CMD;
sp->name = "gnnid";
sp->gen1 = fcport->rscn_gen;
@@ -4386,8 +4386,8 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t 
*fcport)
 
 done_free_sp:
sp->free(sp);
-done:
fcport->flags &= ~FCF_ASYNC_SENT;
+done:
return rval;
 }
 
@@ -4474,15 +4474,15 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, 
fc_port_t *fcport)
struct ct_sns_req   *ct_req;
srb_t *sp;
 
-   if (!vha->flags.online)
-   goto done;
+   if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+   return rval;
 
-   fcport->flags |= FCF_ASYNC_SENT;
fcport->disc_state = DSC_GFPN_ID;
sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
if (!sp)
goto done;
 
+   fcport->flags |= FCF_ASYNC_SENT;
sp->type = SRB_CT_PTHRU_CMD;
sp->name = "gfpnid";
sp->gen1 = fcport->rscn_gen;
@@ -4524,8 +4524,8 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t 
*fcport)
 
 done_free_sp:
sp->free(sp);
-done:
fcport->flags &= ~FCF_ASYNC_SENT;
+done:
return rval;
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 6452f4c8df5e..93febc177aa7 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -207,7 +207,6 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t 
*fcport,
lio->u.logio.flags |= SRB_LOGIN_RETRIED;
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
-   fcport->flags &= ~FCF_ASYNC_SENT;
fcport->flags |= FCF_LOGIN_NEEDED;
set_bit(RELOGIN_NEEDED, >dpc_flags);
goto done_free_sp;
@@ -222,8 +221,8 @@ qla2x00_async_login(struct scsi_qla_host *vha, 

[PATCH v2 22/37] qla2xxx: Fix login state machine freeze

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Relogin stop moving forward due to improper check of scan_state flag.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_init.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 4f4d8b2b7b32..bb0669901e13 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1268,11 +1268,6 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
 {
fc_port_t *fcport = ea->fcport;
 
-   if (fcport->scan_state != QLA_FCPORT_FOUND) {
-   fcport->login_retry++;
-   return;
-   }
-
ql_dbg(ql_dbg_disc, vha, 0x2102,
"%s %8phC DS %d LS %d P %d del %d cnfl %p rscn %d|%d login %d|%d fl 
%x\n",
__func__, fcport->port_name, fcport->disc_state,
@@ -1322,7 +1317,6 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, 
struct event_arg *ea)
int rc;
 
switch (ea->event) {
-   case FCME_RELOGIN:
case FCME_RSCN:
case FCME_GIDPN_DONE:
case FCME_GPSC_DONE:
-- 
2.12.0



[PATCH v2 31/37] qla2xxx: Add retry limit for fabric scan logic

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Switch scan is assumed to succeed most of the time.
If the scan failed, then scan is limit 5 retries.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h |  2 ++
 drivers/scsi/qla2xxx/qla_gs.c  | 32 
 drivers/scsi/qla2xxx/qla_isr.c |  1 +
 3 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 0d20f5f8d7ab..99d2afa520c2 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2986,6 +2986,8 @@ struct fab_scan_rp {
 struct fab_scan {
struct fab_scan_rp *l;
u32 size;
+   u16 scan_retry;
+#define MAX_SCAN_RETRIES 5
enum scan_flags_t scan_flags;
struct delayed_work scan_work;
 };
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 963ebcb7cf2c..8e09f6f16643 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3875,13 +3875,17 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, 
srb_t *sp)
 
rc = sp->rc;
if (rc) {
-   ql_dbg(ql_dbg_disc, vha, 0x,
-   "GPNFT failed. FC4type %x. Rescanning.\n",
-   fc4type);
-   set_bit(LOCAL_LOOP_UPDATE, >dpc_flags);
-   set_bit(LOOP_RESYNC_NEEDED, >dpc_flags);
+   vha->scan.scan_retry++;
+   if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
+   set_bit(LOCAL_LOOP_UPDATE, >dpc_flags);
+   set_bit(LOOP_RESYNC_NEEDED, >dpc_flags);
+   } else {
+   ql_dbg(ql_dbg_disc, vha, 0x,
+   "Fabric scan failed on all retries.\n");
+   }
goto out;
}
+   vha->scan.scan_retry = 0;
 
list_for_each_entry(fcport, >vp_fcports, list)
fcport->scan_state = QLA_FCPORT_SCAN;
@@ -3964,7 +3968,6 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t 
*sp)
 
 out:
qla24xx_sp_unmap(vha, sp);
-
spin_lock_irqsave(>work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
spin_unlock_irqrestore(>work_lock, flags);
@@ -3992,16 +3995,21 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, 
int res)
if (res) {
unsigned long flags;
 
-   ql_dbg(ql_dbg_disc, sp->vha, 0x,
-   "Async done-%s timed out.\n",
-   sp->name);
sp->free(sp);
spin_lock_irqsave(>work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
+   vha->scan.scan_retry++;
spin_unlock_irqrestore(>work_lock, flags);
-   set_bit(LOCAL_LOOP_UPDATE, >dpc_flags);
-   set_bit(LOOP_RESYNC_NEEDED, >dpc_flags);
-   qla2xxx_wake_dpc(vha);
+
+   if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
+   set_bit(LOCAL_LOOP_UPDATE, >dpc_flags);
+   set_bit(LOOP_RESYNC_NEEDED, >dpc_flags);
+   qla2xxx_wake_dpc(vha);
+   } else {
+   ql_dbg(ql_dbg_disc, sp->vha, 0x,
+   "Async done-%s rescan failed on all retries\n",
+   sp->name);
+   }
return;
}
 
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 67434b9ee7de..a37a2a474a50 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1059,6 +1059,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que 
*rsp, uint16_t *mb)
 * Mark all devices as missing so we will login again.
 */
atomic_set(>loop_state, LOOP_UP);
+   vha->scan.scan_retry = 0;
 
set_bit(LOOP_RESYNC_NEEDED, >dpc_flags);
set_bit(LOCAL_LOOP_UPDATE, >dpc_flags);
-- 
2.12.0



[PATCH v2 37/37] qla2xxx: Update driver version to 10.00.00.04-k

2017-12-28 Thread Himanshu Madhani
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_version.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_version.h 
b/drivers/scsi/qla2xxx/qla_version.h
index 911b82226d13..0843def08356 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION  "10.00.00.03-k"
+#define QLA2XXX_VERSION  "10.00.00.04-k"
 
 #define QLA_DRIVER_MAJOR_VER   10
 #define QLA_DRIVER_MINOR_VER   0
-- 
2.12.0



[PATCH v2 36/37] qla2xxx: Serialize session free in qlt_free_session_done

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Add free_pending flag to serialize queueing of
free_work element onto the work queue

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h|  1 +
 drivers/scsi/qla2xxx/qla_target.c | 13 +
 2 files changed, 14 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index ac2f340bc1c6..f7396a2e28ba 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2334,6 +2334,7 @@ typedef struct fc_port {
 
unsigned int conf_compl_supported:1;
unsigned int deleted:2;
+   unsigned int free_pending:1;
unsigned int local:1;
unsigned int logout_on_delete:1;
unsigned int logo_ack_needed:1;
diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index 72b452db26da..0d3c3f647f91 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -1105,6 +1105,7 @@ static void qlt_free_session_done(struct work_struct 
*work)
sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN] = NULL;
}
}
+
spin_unlock_irqrestore(>tgt.sess_lock, flags);
 
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001,
@@ -1118,6 +1119,9 @@ static void qlt_free_session_done(struct work_struct 
*work)
wake_up_all(>fcport_waitQ);
 
base_vha = pci_get_drvdata(ha->pdev);
+
+   sess->free_pending = 0;
+
if (test_bit(PFLG_DRIVER_REMOVING, _vha->pci_flags))
return;
 
@@ -1140,11 +1144,20 @@ static void qlt_free_session_done(struct work_struct 
*work)
 void qlt_unreg_sess(struct fc_port *sess)
 {
struct scsi_qla_host *vha = sess->vha;
+   unsigned long flags;
 
ql_dbg(ql_dbg_disc, sess->vha, 0x210a,
"%s sess %p for deletion %8phC\n",
__func__, sess, sess->port_name);
 
+   spin_lock_irqsave(>vha->work_lock, flags);
+   if (sess->free_pending) {
+   spin_unlock_irqrestore(>vha->work_lock, flags);
+   return;
+   }
+   sess->free_pending = 1;
+   spin_unlock_irqrestore(>vha->work_lock, flags);
+
if (sess->se_sess)
vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess);
 
-- 
2.12.0



[PATCH v2 35/37] qla2xxx: Serialize session deletion by using work_lock

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

for session deletion, replace sess_lock with work_lock.
Under certain case sess_lock is not feasiable to acquire.
The lock is needed temporarily to make sure a single
call to schedule of the work element.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_gbl.h|  1 -
 drivers/scsi/qla2xxx/qla_gs.c | 14 ++
 drivers/scsi/qla2xxx/qla_init.c   |  9 +++--
 drivers/scsi/qla2xxx/qla_isr.c|  4 ++--
 drivers/scsi/qla2xxx/qla_mbx.c|  2 +-
 drivers/scsi/qla2xxx/qla_os.c |  5 ++---
 drivers/scsi/qla2xxx/qla_target.c | 29 ++---
 7 files changed, 28 insertions(+), 36 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 47bff9ab1176..e9295398050c 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -888,7 +888,6 @@ void qlt_plogi_ack_link(struct scsi_qla_host *, struct 
qlt_plogi_ack_t *,
struct fc_port *, enum qlt_plogi_link_t);
 void qlt_plogi_ack_unref(struct scsi_qla_host *, struct qlt_plogi_ack_t *);
 extern void qlt_schedule_sess_for_deletion(struct fc_port *);
-extern void qlt_schedule_sess_for_deletion_lock(struct fc_port *);
 extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
 void qla24xx_delete_sess_fn(struct work_struct *);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 546011b1a765..6bfe24eeb402 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3047,7 +3047,7 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
ql_dbg(ql_dbg_disc, vha, 0x2021,
"%s %d %8phC post del sess\n",
__func__, __LINE__, 
fcport->port_name);
-   
qlt_schedule_sess_for_deletion_lock(fcport);
+   qlt_schedule_sess_for_deletion(fcport);
}
}
} else { /* ea->sp->gen1 != fcport->rscn_gen */
@@ -3064,7 +3064,7 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
ql_dbg(ql_dbg_disc, vha, 0x2042,
"%s %d %8phC post del sess\n", __func__,
__LINE__, fcport->port_name);
-   qlt_schedule_sess_for_deletion_lock(fcport);
+   qlt_schedule_sess_for_deletion(fcport);
} else {
ql_dbg(ql_dbg_disc, vha, 0x2045,
"%s %d %8phC login\n", __func__, __LINE__,
@@ -3436,8 +3436,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
"%s %d %8phC post del sess\n",
__func__, __LINE__,
fcport->port_name);
-   qlt_schedule_sess_for_deletion_lock
-   (fcport);
+   qlt_schedule_sess_for_deletion(fcport);
break;
}
}
@@ -3470,7 +3469,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
"%s %d %8phC post del 
sess\n",
__func__, __LINE__,
conflict->port_name);
-   
qlt_schedule_sess_for_deletion_lock
+   qlt_schedule_sess_for_deletion
(conflict);
break;
}
@@ -3528,7 +3527,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
"%s %d %8phC post del 
sess\n",
__func__, __LINE__,
conflict->port_name);
-   
qlt_schedule_sess_for_deletion_lock
+   qlt_schedule_sess_for_deletion
(conflict);
break;
}
@@ -3959,8 +3958,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t 
*sp)
   

[PATCH v2 28/37] qla2xxx: Allow relogin and session creation after reset

2017-12-28 Thread Himanshu Madhani
When any kind of reset is issued, current code was setting
state of LOGIN pending too early. This resulted into driver
not retrying relogin until pervious reloin completes.

Signed-off-by: Himanshu Madhani 
Signed-off-by: Quinn Tran 
---
 drivers/scsi/qla2xxx/qla_init.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 61534b9bef7b..e9513ec344b1 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1132,7 +1132,6 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host 
*vha, fc_port_t *fcport)
ql_dbg(ql_dbg_disc, vha, 0x20bf,
"%s %d %8phC post login\n",
__func__, __LINE__, fcport->port_name);
-   fcport->disc_state = DSC_LOGIN_PEND;
qla2x00_post_async_login_work(vha, fcport, NULL);
}
 }
-- 
2.12.0



[PATCH v2 25/37] qla2xxx: Fix GPNFT/GNNFT error handling

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

retry gpnft/gnnft if error is encountered.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_gs.c   | 15 +++
 drivers/scsi/qla2xxx/qla_init.c |  8 
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index a530c777eac9..fff12d770583 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3878,6 +3878,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t 
*sp)
ql_dbg(ql_dbg_disc, vha, 0x,
"GPNFT failed. FC4type %x. Rescanning.\n",
fc4type);
+   set_bit(LOCAL_LOOP_UPDATE, >dpc_flags);
set_bit(LOOP_RESYNC_NEEDED, >dpc_flags);
goto out;
}
@@ -3987,6 +3988,19 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, 
int res)
"Async done-%s res %x FC4Type %x\n",
sp->name, res, sp->gen2);
 
+   if (res) {
+   unsigned long flags;
+
+   ql_dbg(ql_dbg_disc, sp->vha, 0x,
+   "Async done-%s timed out.\n",
+   sp->name);
+   sp->free(sp);
+   set_bit(LOCAL_LOOP_UPDATE, >dpc_flags);
+   set_bit(LOOP_RESYNC_NEEDED, >dpc_flags);
+   qla2xxx_wake_dpc(vha);
+   return;
+   }
+
if (!res) {
port_id_t id;
u64 wwn;
@@ -4048,6 +4062,7 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, 
int res)
"Async done-%s unable to alloc work element\n",
sp->name);
sp->free(sp);
+   set_bit(LOCAL_LOOP_UPDATE, >dpc_flags);
set_bit(LOOP_RESYNC_NEEDED, >dpc_flags);
return;
}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index bb0669901e13..0ea948db910f 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -681,15 +681,15 @@ qla24xx_async_gnl_sp_done(void *s, int res)
}
}
 
-   id.b.domain = e->port_id[0];
+   id.b.domain = e->port_id[2];
id.b.area = e->port_id[1];
-   id.b.al_pa = e->port_id[2];
+   id.b.al_pa = e->port_id[0];
id.b.rsvd_1 = 0;
 
if (!found && wwn && !IS_SW_RESV_ADDR(id)) {
ql_dbg(ql_dbg_disc, vha, 0x2065,
-   "%s %d %8phC post new sess\n",
-   __func__, __LINE__, (u8 *));
+   "%s %d %8phC %06x post new sess\n",
+   __func__, __LINE__, (u8 *), id.b24);
wwnn = wwn_to_u64(e->node_name);
qla24xx_post_newsess_work(vha, , (u8 *),
(u8 *), NULL, FC4_TYPE_UNKNOWN);
-- 
2.12.0



[PATCH v2 29/37] qla2xxx: Increase verbosity of debug messages logged

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Add verbose bit for debug messages to reduce excessive
log messages

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_target.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index a4783eb11711..786efdb5788a 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -209,7 +209,7 @@ struct scsi_qla_host *qlt_find_host_by_d_id(struct 
scsi_qla_host *vha,
 
host = btree_lookup32(>hw->tgt.host_map, key);
if (!host)
-   ql_dbg(ql_dbg_tgt_mgt, vha, 0xf005,
+   ql_dbg(ql_dbg_tgt_mgt + ql_dbg_verbose, vha, 0xf005,
"Unable to find host %06x\n", key);
 
return host;
@@ -310,17 +310,17 @@ static void qlt_try_to_dequeue_unknown_atios(struct 
scsi_qla_host *vha,
 
host = qlt_find_host_by_d_id(vha, u->atio.u.isp24.fcp_hdr.d_id);
if (host != NULL) {
-   ql_dbg(ql_dbg_async, vha, 0x502f,
+   ql_dbg(ql_dbg_async + ql_dbg_verbose, vha, 0x502f,
"Requeuing unknown ATIO_TYPE7 %p\n", u);
qlt_24xx_atio_pkt(host, >atio, ha_locked);
} else if (tgt->tgt_stop) {
-   ql_dbg(ql_dbg_async, vha, 0x503a,
+   ql_dbg(ql_dbg_async + ql_dbg_verbose, vha, 0x503a,
"Freeing unknown %s %p, because tgt is being 
stopped\n",
"ATIO_TYPE7", u);
qlt_send_term_exchange(vha->hw->base_qpair, NULL,
>atio, ha_locked, 0);
} else {
-   ql_dbg(ql_dbg_async, vha, 0x503d,
+   ql_dbg(ql_dbg_async + ql_dbg_verbose, vha, 0x503d,
"Reschedule u %p, vha %p, host %p\n", u, vha, host);
if (!queued) {
queued = 1;
-- 
2.12.0



[PATCH v2 24/37] qla2xxx: Remove session creation redundant code

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Current code creates a session when a new port is
discovered, and a PLOGI/PRLI is received. There is
no need to create session when command has arrived.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_target.c | 122 ++
 1 file changed, 5 insertions(+), 117 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index 75474725fe59..a4783eb11711 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -2018,15 +2018,10 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host 
*vha,
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012,
"qla_target(%d): task abort for non-existant session\n",
vha->vp_idx);
-   rc = qlt_sched_sess_work(vha->vha_tgt.qla_tgt,
-   QLA_TGT_SESS_WORK_ABORT, abts, sizeof(*abts));
-
spin_unlock_irqrestore(>tgt.sess_lock, flags);
 
-   if (rc != 0) {
-   qlt_24xx_send_abts_resp(ha->base_qpair, abts,
-   FCP_TMF_REJECTED, false);
-   }
+   qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED,
+   false);
return;
}
spin_unlock_irqrestore(>tgt.sess_lock, flags);
@@ -4246,87 +4241,6 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t 
*vha,
return cmd;
 }
 
-static void qlt_create_sess_from_atio(struct work_struct *work)
-{
-   struct qla_tgt_sess_op *op = container_of(work,
-   struct qla_tgt_sess_op, work);
-   scsi_qla_host_t *vha = op->vha;
-   struct qla_hw_data *ha = vha->hw;
-   struct fc_port *sess;
-   struct qla_tgt_cmd *cmd;
-   unsigned long flags;
-   uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id;
-
-   spin_lock_irqsave(>cmd_list_lock, flags);
-   list_del(>cmd_list);
-   spin_unlock_irqrestore(>cmd_list_lock, flags);
-
-   if (op->aborted) {
-   ql_dbg(ql_dbg_tgt_mgt, vha, 0xf083,
-   "sess_op with tag %u is aborted\n",
-   op->atio.u.isp24.exchange_addr);
-   goto out_term;
-   }
-
-   ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022,
-   "qla_target(%d): Unable to find wwn login"
-   " (s_id %x:%x:%x), trying to create it manually\n",
-   vha->vp_idx, s_id[0], s_id[1], s_id[2]);
-
-   if (op->atio.u.raw.entry_count > 1) {
-   ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023,
-   "Dropping multy entry atio %p\n", >atio);
-   goto out_busy;
-   }
-
-   sess = qlt_make_local_sess(vha, s_id);
-   /* sess has an extra creation ref. */
-
-   if (!sess)
-   goto out_busy;
-   /*
-* Now obtain a pre-allocated session tag using the original op->atio
-* packet header, and dispatch into __qlt_do_work() using the existing
-* process context.
-*/
-   cmd = qlt_get_tag(vha, sess, >atio);
-   if (!cmd) {
-   struct qla_qpair *qpair = ha->base_qpair;
-
-   spin_lock_irqsave(qpair->qp_lock_ptr, flags);
-   qlt_send_busy(qpair, >atio, tc_sam_status);
-   spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
-
-   spin_lock_irqsave(>tgt.sess_lock, flags);
-   ha->tgt.tgt_ops->put_sess(sess);
-   spin_unlock_irqrestore(>tgt.sess_lock, flags);
-   kfree(op);
-   return;
-   }
-
-   /*
-* __qlt_do_work() will call qlt_put_sess() to release
-* the extra reference taken above by qlt_make_local_sess()
-*/
-   __qlt_do_work(cmd);
-   kfree(op);
-   return;
-out_term:
-   qlt_send_term_exchange(vha->hw->base_qpair, NULL, >atio, 0, 0);
-   kfree(op);
-   return;
-out_busy:
-   {
-   struct qla_qpair *qpair = ha->base_qpair;
-
-   spin_lock_irqsave(qpair->qp_lock_ptr, flags);
-   qlt_send_busy(qpair, >atio, qla_sam_status);
-   spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
-   kfree(op);
-   }
-   return;
-}
-
 /* ha->hardware_lock supposed to be held on entry */
 static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
struct atio_from_isp *atio)
@@ -4351,23 +4265,8 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host 
*vha,
return -EBUSY;
 
sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, 
atio->u.isp24.fcp_hdr.s_id);
-   if (unlikely(!sess)) {
-   struct qla_tgt_sess_op *op = kzalloc(sizeof(struct 
qla_tgt_sess_op),
-GFP_ATOMIC);
-   if (!op)
-   return -ENOMEM;
-
-   memcpy(>atio, 

[PATCH v2 26/37] qla2xxx: Properly extract ADISC error codes

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

This patch fixes issue with extraction of ADISC error codes
for decoding the error returned

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_init.c | 24 
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 0ea948db910f..75dc76587f43 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -339,16 +339,21 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t 
*fcport)
 static
 void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
-   if (ea->rc) {
+   struct fc_port *fcport = ea->fcport;
+
+   ql_dbg(ql_dbg_disc, vha, 0x20d2,
+   "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
+   __func__, fcport->port_name, fcport->disc_state,
+   fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
+   fcport->rscn_gen, ea->sp->gen1, fcport->loop_id);
+
+   if (ea->data[0] != MBS_COMMAND_COMPLETE) {
ql_dbg(ql_dbg_disc, vha, 0x2066,
"%s %8phC: adisc fail: post delete\n",
__func__, ea->fcport->port_name);
qlt_schedule_sess_for_deletion(ea->fcport, 1);
return;
}
-   ql_dbg(ql_dbg_disc, vha, 0x20d2,
-   "%s %8phC DS %d LS %d\n", __func__, ea->fcport->port_name,
-   ea->fcport->disc_state, ea->fcport->fw_login_state);
 
if (ea->fcport->disc_state == DSC_DELETE_PEND)
return;
@@ -356,10 +361,8 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
if (ea->sp->gen2 != ea->fcport->login_gen) {
/* target side must have changed it. */
ql_dbg(ql_dbg_disc, vha, 0x20d3,
-   "%s %8phC generation changed rscn %d|%d login %d|%d\n",
-   __func__, ea->fcport->port_name, ea->fcport->last_rscn_gen,
-   ea->fcport->rscn_gen, ea->fcport->last_login_gen,
-   ea->fcport->login_gen);
+   "%s %8phC generation changed\n",
+   __func__, ea->fcport->port_name);
return;
} else if (ea->sp->gen1 != ea->fcport->rscn_gen) {
ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
@@ -377,6 +380,7 @@ qla2x00_async_adisc_sp_done(void *ptr, int res)
srb_t *sp = ptr;
struct scsi_qla_host *vha = sp->vha;
struct event_arg ea;
+   struct srb_iocb *lio = >u.iocb_cmd;
 
ql_dbg(ql_dbg_disc, vha, 0x2066,
"Async done-%s res %x %8phC\n",
@@ -385,6 +389,10 @@ qla2x00_async_adisc_sp_done(void *ptr, int res)
memset(, 0, sizeof(ea));
ea.event = FCME_ADISC_DONE;
ea.rc = res;
+   ea.data[0] = lio->u.logio.data[0];
+   ea.data[1] = lio->u.logio.data[1];
+   ea.iop[0] = lio->u.logio.iop[0];
+   ea.iop[1] = lio->u.logio.iop[1];
ea.fcport = sp->fcport;
ea.sp = sp;
 
-- 
2.12.0



[PATCH v2 30/37] qla2xxx: Delay loop id allocation at login

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Delay loop id allocation to login time

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_init.c | 64 ++---
 1 file changed, 35 insertions(+), 29 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index e9513ec344b1..6452f4c8df5e 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -580,36 +580,29 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t 
*vha,
 
if (!found) {
/* fw has no record of this port */
-   if (fcport->loop_id == FC_NO_LOOP_ID) {
-   qla2x00_find_new_loop_id(vha, fcport);
-   fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
-   } else {
-   for (i = 0; i < n; i++) {
-   e = >gnl.l[i];
-   id.b.domain = e->port_id[0];
-   id.b.area = e->port_id[1];
-   id.b.al_pa = e->port_id[2];
-   id.b.rsvd_1 = 0;
-   loop_id = le16_to_cpu(e->nport_handle);
-
-   if (fcport->d_id.b24 == id.b24) {
-   conflict_fcport =
-   qla2x00_find_fcport_by_wwpn(vha,
-   e->port_name, 0);
-
-   ql_dbg(ql_dbg_disc, vha, 0x20e6,
-   "%s %d %8phC post del sess\n",
-   __func__, __LINE__,
-   conflict_fcport->port_name);
-   qlt_schedule_sess_for_deletion
-   (conflict_fcport, 1);
-   }
-
-   if (fcport->loop_id == loop_id) {
-   /* FW already picked this loop id for 
another fcport */
-   qla2x00_find_new_loop_id(vha, fcport);
-   }
+   for (i = 0; i < n; i++) {
+   e = >gnl.l[i];
+   id.b.domain = e->port_id[0];
+   id.b.area = e->port_id[1];
+   id.b.al_pa = e->port_id[2];
+   id.b.rsvd_1 = 0;
+   loop_id = le16_to_cpu(e->nport_handle);
+
+   if (fcport->d_id.b24 == id.b24) {
+   conflict_fcport =
+   qla2x00_find_fcport_by_wwpn(vha,
+   e->port_name, 0);
+   ql_dbg(ql_dbg_disc, vha, 0x20e6,
+   "%s %d %8phC post del sess\n",
+   __func__, __LINE__,
+   conflict_fcport->port_name);
+   qlt_schedule_sess_for_deletion
+   (conflict_fcport, 1);
}
+
+   /* FW already picked this loop id for another fcport */
+   if (fcport->loop_id == loop_id)
+   fcport->loop_id = FC_NO_LOOP_ID;
}
qla24xx_fcport_handle_login(vha, fcport);
}
@@ -1104,6 +1097,7 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
 static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 {
u8 login = 0;
+   int rc;
 
if (qla_tgt_mode_enabled(vha))
return;
@@ -1129,6 +1123,18 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host 
*vha, fc_port_t *fcport)
}
 
if (login) {
+   if (fcport->loop_id == FC_NO_LOOP_ID) {
+   fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
+   rc = qla2x00_find_new_loop_id(vha, fcport);
+   if (rc) {
+   ql_dbg(ql_dbg_disc, vha, 0x20e6,
+   "%s %d %8phC post del sess - out of 
loopid\n",
+   __func__, __LINE__, fcport->port_name);
+   fcport->scan_state = 0;
+   qlt_schedule_sess_for_deletion(fcport, true);
+   return;
+   }
+   }
ql_dbg(ql_dbg_disc, vha, 0x20bf,
"%s %d %8phC post login\n",
__func__, __LINE__, fcport->port_name);
-- 
2.12.0



[PATCH v2 12/37] qla2xxx: Add ability to send PRLO

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Add ability to send Implicit PRLO to flush IOs
from FW back to driver.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h  |  3 +++
 drivers/scsi/qla2xxx/qla_gbl.h  |  8 ++
 drivers/scsi/qla2xxx/qla_init.c | 59 +
 drivers/scsi/qla2xxx/qla_iocb.c | 17 
 drivers/scsi/qla2xxx/qla_os.c   |  9 +++
 5 files changed, 96 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 92dbba47d3cf..7a42aad55ec3 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -507,6 +507,7 @@ struct srb_iocb {
 #define SRB_NVME_LS20
 #define SRB_PRLI_CMD   21
 #define SRB_CTRL_VP22
+#define SRB_PRLO_CMD   23
 
 enum {
TYPE_SRB,
@@ -3140,6 +3141,8 @@ enum qla_work_type {
QLA_EVT_GNL,
QLA_EVT_NACK,
QLA_EVT_RELOGIN,
+   QLA_EVT_ASYNC_PRLO,
+   QLA_EVT_ASYNC_PRLO_DONE,
 };
 
 
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index aabd49ef95a3..7b61c96502e4 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -66,6 +66,7 @@ extern void qla84xx_put_chip(struct scsi_qla_host *);
 extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
 uint16_t *);
 extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
+extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *);
 extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
 uint16_t *);
 extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t);
@@ -109,6 +110,13 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, 
port_id_t *, u8 *,
 int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_detect_sfp(scsi_qla_host_t *vha);
 int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
+void qla2x00_async_prlo_done(struct scsi_qla_host *, fc_port_t *,
+uint16_t *);
+extern int qla2x00_post_async_prlo_work(struct scsi_qla_host *, fc_port_t *,
+uint16_t *);
+extern int qla2x00_post_async_prlo_done_work(struct scsi_qla_host *,
+fc_port_t *, uint16_t *);
+
 /*
  * Global Data in qla_os.c source file.
  */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 39d1edc6c2b1..56bff7856cf8 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -278,6 +278,65 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t 
*fcport)
fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
 }
+
+void
+qla2x00_async_prlo_done(struct scsi_qla_host *vha, fc_port_t *fcport,
+uint16_t *data)
+{
+   /* Don't re-login in target mode */
+   if (!fcport->tgt_session)
+   qla2x00_mark_device_lost(vha, fcport, 1, 0);
+   qlt_logo_completion_handler(fcport, data[0]);
+}
+
+static void
+qla2x00_async_prlo_sp_done(void *s, int res)
+{
+   srb_t *sp = (srb_t *)s;
+   struct srb_iocb *lio = >u.iocb_cmd;
+   struct scsi_qla_host *vha = sp->vha;
+
+   if (!test_bit(UNLOADING, >dpc_flags))
+   qla2x00_post_async_prlo_done_work(sp->fcport->vha, sp->fcport,
+   lio->u.logio.data);
+   sp->free(sp);
+}
+
+int
+qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+   srb_t *sp;
+   struct srb_iocb *lio;
+   int rval;
+
+   rval = QLA_FUNCTION_FAILED;
+   sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+   if (!sp)
+   goto done;
+
+   sp->type = SRB_PRLO_CMD;
+   sp->name = "prlo";
+   qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+   lio = >u.iocb_cmd;
+   lio->timeout = qla2x00_async_iocb_timeout;
+   sp->done = qla2x00_async_prlo_sp_done;
+   rval = qla2x00_start_sp(sp);
+   if (rval != QLA_SUCCESS)
+   goto done_free_sp;
+
+   ql_dbg(ql_dbg_disc, vha, 0x2070,
+   "Async-prlo - hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
+   sp->handle, fcport->loop_id, fcport->d_id.b.domain,
+   fcport->d_id.b.area, fcport->d_id.b.al_pa);
+   return rval;
+
+done_free_sp:
+   sp->free(sp);
+done:
+   return rval;
+}
+
 static
 void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index d1dfa784d895..14a3f6932c9c 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -3390,6 +3390,20 @@ qla25xx_ctrlvp_iocb(srb_t *sp, struct vp_ctrl_entry_24xx 
*vce)
vce->vp_idx_map[map] |= 1 << pos;
 }
 
+static void
+qla24xx_prlo_iocb(srb_t *sp, struct logio_entry_24xx *logio)
+{
+   logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
+   logio->control_flags =
+   cpu_to_le16(LCF_COMMAND_PRLO|LCF_IMPL_PRLO);
+
+   

[PATCH v2 23/37] qla2xxx: Migrate switch registration commands away from mailbox interface

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Migrate switch registration commands: RFTID, RFFID, RNNID and RSNN_NN
out of mailbox interface to reduce fabric scan bottle neck.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h|   4 +-
 drivers/scsi/qla2xxx/qla_gbl.h|   2 +-
 drivers/scsi/qla2xxx/qla_gs.c | 450 ++
 drivers/scsi/qla2xxx/qla_os.c |  20 +-
 drivers/scsi/qla2xxx/qla_target.c |  13 +-
 drivers/scsi/qla2xxx/qla_target.h |   2 +-
 6 files changed, 347 insertions(+), 144 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 240767c862e6..68b327827739 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -535,6 +535,7 @@ typedef struct srb {
u32 gen1;   /* scratch */
u32 gen2;   /* scratch */
int rc;
+   int retry_count;
struct completion comp;
union {
struct srb_iocb iocb_cmd;
@@ -3187,7 +3188,7 @@ enum qla_work_type {
QLA_EVT_AENFX,
QLA_EVT_GIDPN,
QLA_EVT_GPNID,
-   QLA_EVT_GPNID_DONE,
+   QLA_EVT_UNMAP,
QLA_EVT_NEW_SESS,
QLA_EVT_GPDB,
QLA_EVT_PRLI,
@@ -3203,6 +3204,7 @@ enum qla_work_type {
QLA_EVT_GNNFT_DONE,
QLA_EVT_GNNID,
QLA_EVT_GFPNID,
+   QLA_EVT_SP_RETRY,
 };
 
 
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 4e504e5e7586..643cc536454b 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -650,7 +650,6 @@ extern void qla2x00_free_fcport(fc_port_t *);
 
 extern int qla24xx_post_gpnid_work(struct scsi_qla_host *, port_id_t *);
 extern int qla24xx_async_gpnid(scsi_qla_host_t *, port_id_t *);
-void qla24xx_async_gpnid_done(scsi_qla_host_t *, srb_t*);
 void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *);
 
 int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *);
@@ -668,6 +667,7 @@ int qla24xx_post_gnnid_work(struct scsi_qla_host *, 
fc_port_t *);
 int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *);
 void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *);
+void qla24xx_sp_unmap(scsi_qla_host_t *, srb_t *);
 
 /*
  * Global Function Prototypes in qla_attr.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 2132c7ad8044..a530c777eac9 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -14,6 +14,10 @@ static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t 
*);
 static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
 static int qla2x00_sns_rft_id(scsi_qla_host_t *);
 static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
+static int qla_async_rftid(scsi_qla_host_t *, port_id_t *);
+static int qla_async_rffid(scsi_qla_host_t *, port_id_t *, u8, u8);
+static int qla_async_rnnid(scsi_qla_host_t *, port_id_t *, u8*);
+static int qla_async_rsnn_nn(scsi_qla_host_t *);
 
 /**
  * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
@@ -511,6 +515,72 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
return (rval);
 }
 
+static void qla2x00_async_sns_sp_done(void *s, int rc)
+{
+   struct srb *sp = s;
+   struct scsi_qla_host *vha = sp->vha;
+   struct ct_sns_pkt *ct_sns;
+   struct qla_work_evt *e;
+
+   sp->rc = rc;
+   if (rc == QLA_SUCCESS) {
+   ql_dbg(ql_dbg_disc, vha, 0x204f,
+   "Async done-%s exiting normally.\n",
+   sp->name);
+   } else if (rc == QLA_FUNCTION_TIMEOUT) {
+   ql_dbg(ql_dbg_disc, vha, 0x204f,
+   "Async done-%s timeout\n", sp->name);
+   } else {
+   ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
+   memset(ct_sns, 0, sizeof(*ct_sns));
+   sp->retry_count++;
+   if (sp->retry_count > 3)
+   goto err;
+
+   ql_dbg(ql_dbg_disc, vha, 0x204f,
+   "Async done-%s fail rc %x.  Retry count %d\n",
+   sp->name, rc, sp->retry_count);
+
+   e = qla2x00_alloc_work(vha, QLA_EVT_SP_RETRY);
+   if (!e)
+   goto err2;
+
+   del_timer(>u.iocb_cmd.timer);
+   e->u.iosb.sp = sp;
+   qla2x00_post_work(vha, e);
+   return;
+   }
+
+err:
+   e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
+err2:
+   if (!e) {
+   /* please ignore kernel warning. otherwise, we have mem leak. */
+   if (sp->u.iocb_cmd.u.ctarg.req) {
+   dma_free_coherent(>hw->pdev->dev,
+   sizeof(struct ct_sns_pkt),
+   sp->u.iocb_cmd.u.ctarg.req,
+

[PATCH v2 27/37] qla2xxx: Add ability to use GPNFT/GNNFT for RSCN handling

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

add ability to use gpnft/gnnft to handle RSCN.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h  |  7 +++
 drivers/scsi/qla2xxx/qla_gbl.h  |  1 +
 drivers/scsi/qla2xxx/qla_gs.c   | 99 -
 drivers/scsi/qla2xxx/qla_init.c | 65 ++-
 drivers/scsi/qla2xxx/qla_os.c   |  1 +
 5 files changed, 113 insertions(+), 60 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 68b327827739..0d20f5f8d7ab 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2972,6 +2972,11 @@ struct ct_sns_gpnft_pkt {
} p;
 };
 
+enum scan_flags_t {
+   SF_SCANNING = BIT_0,
+   SF_QUEUED = BIT_1,
+};
+
 struct fab_scan_rp {
port_id_t id;
u8 port_name[8];
@@ -2981,6 +2986,8 @@ struct fab_scan_rp {
 struct fab_scan {
struct fab_scan_rp *l;
u32 size;
+   enum scan_flags_t scan_flags;
+   struct delayed_work scan_work;
 };
 
 /*
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 643cc536454b..3f3863c09de2 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -668,6 +668,7 @@ int qla24xx_post_gfpnid_work(struct scsi_qla_host *, 
fc_port_t *);
 int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *);
 void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *);
 void qla24xx_sp_unmap(scsi_qla_host_t *, srb_t *);
+void qla_scan_work_fn(struct work_struct *);
 
 /*
  * Global Function Prototypes in qla_attr.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index fff12d770583..963ebcb7cf2c 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -2976,8 +2976,10 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
fc_port_t *fcport = ea->fcport;
 
ql_dbg(ql_dbg_disc, vha, 0x201d,
-   "%s %8phC login state %d\n",
-   __func__, fcport->port_name, fcport->fw_login_state);
+   "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
+   __func__, fcport->port_name, fcport->disc_state,
+   fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
+   fcport->rscn_gen, ea->sp->gen1, fcport->loop_id);
 
if (fcport->disc_state == DSC_DELETE_PEND)
return;
@@ -2985,9 +2987,9 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
if (ea->sp->gen2 != fcport->login_gen) {
/* PLOGI/PRLI/LOGO came in while cmd was out.*/
ql_dbg(ql_dbg_disc, vha, 0x201e,
-   "%s %8phC generation changed rscn %d|%d login %d|%d \n",
+   "%s %8phC generation changed rscn %d|%d n",
__func__, fcport->port_name, fcport->last_rscn_gen,
-   fcport->rscn_gen, fcport->last_login_gen, 
fcport->login_gen);
+   fcport->rscn_gen);
return;
}
 
@@ -3215,11 +3217,10 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
struct fc_port *fcport = ea->fcport;
 
ql_dbg(ql_dbg_disc, vha, 0x20d8,
-   "%s %8phC DS %d LS %d rscn %d|%d login %d|%d lid %d\n",
+   "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
__func__, fcport->port_name, fcport->disc_state,
-   fcport->fw_login_state, fcport->last_rscn_gen, fcport->rscn_gen,
-   fcport->last_login_gen, fcport->login_gen,
-   fcport->loop_id);
+   fcport->fw_login_state, ea->rc, ea->sp->gen2, fcport->login_gen,
+   ea->sp->gen2, fcport->rscn_gen|ea->sp->gen1, fcport->loop_id);
 
if (fcport->disc_state == DSC_DELETE_PEND)
return;
@@ -3227,10 +3228,8 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
if (ea->sp->gen2 != fcport->login_gen) {
/* target side must have changed it. */
ql_dbg(ql_dbg_disc, vha, 0x20d3,
-   "%s %8phC generation changed rscn %d|%d login %d|%d\n",
-   __func__, fcport->port_name, fcport->last_rscn_gen,
-   fcport->rscn_gen, fcport->last_login_gen,
-   fcport->login_gen);
+   "%s %8phC generation changed\n",
+   __func__, fcport->port_name);
return;
} else if (ea->sp->gen1 != fcport->rscn_gen) {
ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
@@ -3862,6 +3861,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t 
*sp)
bool found;
u8 fc4type = sp->gen2;
struct fab_scan_rp *rp;
+   unsigned long flags;
 
ql_dbg(ql_dbg_disc, vha, 0x,
"%s enter\n", __func__);
@@ 

[PATCH v2 21/37] qla2xxx: Reduce trace noise for Async Events

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Add NPIV id check to reduce multiple debug messages
of the same RSCN event.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_mid.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index bf365f8a9d32..e965b16f21e3 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -265,13 +265,20 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
case MBA_LIP_RESET:
case MBA_POINT_TO_POINT:
case MBA_CHG_IN_CONNECTION:
-   case MBA_PORT_UPDATE:
-   case MBA_RSCN_UPDATE:
ql_dbg(ql_dbg_async, vha, 0x5024,
"Async_event for VP[%d], mb=0x%x vha=%p.\n",
i, *mb, vha);
qla2x00_async_event(vha, rsp, mb);
break;
+   case MBA_PORT_UPDATE:
+   case MBA_RSCN_UPDATE:
+   if ((mb[3] & 0xff) == vha->vp_idx) {
+   ql_dbg(ql_dbg_async, vha, 0x5024,
+   "Async_event for VP[%d], mb=0x%x 
vha=%p\n",
+   i, *mb, vha);
+   qla2x00_async_event(vha, rsp, mb);
+   }
+   break;
}
 
spin_lock_irqsave(>vport_slock, flags);
-- 
2.12.0



[PATCH v2 01/37] qla2xxx: Fix NULL pointer access for fcport structure

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

when processing iocb in a timeout case, driver was trying to log messages
without verifying if the fcport structure could have valid data. This
results in a NULL pointer access.

Fixes: 726b85487067("qla2xxx: Add framework for async fabric discovery")
Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_init.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 58663df38627..b650ebec1b9d 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -102,11 +102,16 @@ qla2x00_async_iocb_timeout(void *data)
struct srb_iocb *lio = >u.iocb_cmd;
struct event_arg ea;
 
-   ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
-   "Async-%s timeout - hdl=%x portid=%06x %8phC.\n",
-   sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
+   if (fcport) {
+   ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
+   "Async-%s timeout - hdl=%x portid=%06x %8phC.\n",
+   sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
 
-   fcport->flags &= ~FCF_ASYNC_SENT;
+   fcport->flags &= ~FCF_ASYNC_SENT;
+   } else {
+   pr_info("Async-%s timeout - hdl=%x.\n",
+   sp->name, sp->handle);
+   }
 
switch (sp->type) {
case SRB_LOGIN_CMD:
-- 
2.12.0



[PATCH v2 09/37] qla2xxx: Enable ATIO interrupt handshake for ISP27XX

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Enable ATIO Q interrupt handshake for ISP27XX. This patch
coalesce ATIO's interrupts for Quad port ISP27XX adapter.
Interrupt coalesce allows performance to scale for this
specific case.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_target.c | 39 +--
 1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index 067bcc57a9ad..db6fd3b747ed 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -6574,7 +6574,9 @@ void
 qlt_24xx_config_rings(struct scsi_qla_host *vha)
 {
struct qla_hw_data *ha = vha->hw;
-   struct init_cb_24xx *icb;
+   struct qla_msix_entry *msix = >msix_entries[2];
+   struct init_cb_24xx *icb = (struct init_cb_24xx *)ha->init_cb;
+
if (!QLA_TGT_MODE_ENABLED())
return;
 
@@ -6582,19 +6584,28 @@ qlt_24xx_config_rings(struct scsi_qla_host *vha)
WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), 0);
RD_REG_DWORD(ISP_ATIO_Q_OUT(vha));
 
-   icb = (struct init_cb_24xx *)ha->init_cb;
-
-   if ((ql2xenablemsix != 0) && IS_ATIO_MSIX_CAPABLE(ha)) {
-   struct qla_msix_entry *msix = >msix_entries[2];
-
-   icb->msix_atio = cpu_to_le16(msix->entry);
-   ql_dbg(ql_dbg_init, vha, 0xf072,
-   "Registering ICB vector 0x%x for atio que.\n",
-   msix->entry);
-   } else if (ql2xenablemsix == 0) {
-   icb->firmware_options_2 |= cpu_to_le32(BIT_26);
-   ql_dbg(ql_dbg_init, vha, 0xf07f,
-   "Registering INTx vector for ATIO.\n");
+   if (ha->flags.msix_enabled) {
+   if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+   if (IS_QLA2071(ha)) {
+   /* 4 ports Baker: Enable Interrupt Handshake */
+   icb->msix_atio = 0;
+   icb->firmware_options_2 |= BIT_26;
+   } else {
+   icb->msix_atio = cpu_to_le16(msix->entry);
+   icb->firmware_options_2 &= ~BIT_26;
+   }
+   ql_dbg(ql_dbg_init, vha, 0xf072,
+   "Registering ICB vector 0x%x for atio que.\n",
+   msix->entry);
+   }
+   } else {
+   /* INTx|MSI */
+   if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+   icb->msix_atio = 0;
+   icb->firmware_options_2 |= BIT_26;
+   ql_dbg(ql_dbg_init, vha, 0xf072,
+   "%s: Use INTx for ATIOQ.\n", __func__);
+   }
}
 }
 
-- 
2.12.0



[PATCH v2 08/37] qla2xxx: Move work element processing out of DPC thread

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

DPC thread can stall during switch scan due to slow switch response.
This will stall other work element that needs attention. Moving work
element processing and relogin logic out of DPC thread and into its
own work queue.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h  |  6 ++--
 drivers/scsi/qla2xxx/qla_gbl.h  |  1 +
 drivers/scsi/qla2xxx/qla_init.c |  1 +
 drivers/scsi/qla2xxx/qla_mid.c  |  6 +---
 drivers/scsi/qla2xxx/qla_os.c   | 76 +++--
 5 files changed, 63 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index ca2ad477a4df..92dbba47d3cf 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3139,6 +3139,7 @@ enum qla_work_type {
QLA_EVT_UPD_FCPORT,
QLA_EVT_GNL,
QLA_EVT_NACK,
+   QLA_EVT_RELOGIN,
 };
 
 
@@ -3447,10 +3448,6 @@ struct qlt_hw_data {
 
 #define LEAK_EXCHG_THRESH_HOLD_PERCENT 75  /* 75 percent */
 
-#define QLA_EARLY_LINKUP(_ha) \
-   ((_ha->flags.n2n_ae || _ha->flags.lip_ae) && \
-_ha->flags.fw_started && !_ha->flags.fw_init_done)
-
 /*
  * Qlogic host adapter specific data structure.
 */
@@ -4155,6 +4152,7 @@ typedef struct scsi_qla_host {
 #define SET_ZIO_THRESHOLD_NEEDED   28
 #define DETECT_SFP_CHANGE  29
 #define N2N_LOGIN_NEEDED   30
+#define IOCB_WORK_ACTIVE   31
 
unsigned long   pci_flags;
 #define PFLG_DISCONNECTED  0   /* PCI device removed */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index fa115c7433e5..cf1f1a3baf21 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -203,6 +203,7 @@ void qla2x00_handle_login_done_event(struct scsi_qla_host 
*, fc_port_t *,
uint16_t *);
 int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_async_abort_cmd(srb_t *);
+int qla24xx_post_relogin_work(struct scsi_qla_host *vha);
 
 /*
  * Global Functions in qla_mid.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 93d0077ba388..728c66f34666 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -898,6 +898,7 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct 
event_arg *ea)
__func__, fcport->port_name, fcport->last_rscn_gen,
fcport->rscn_gen, fcport->last_login_gen,
fcport->login_gen);
+   set_bit(RELOGIN_NEEDED, >dpc_flags);
return;
} else if (ea->sp->gen1 != fcport->rscn_gen) {
ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index e6f3d2d62c61..966ff0f1bed4 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -319,8 +319,6 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_dpc + ql_dbg_verbose, vha, 0x4012,
"Entering %s vp_flags: 0x%lx.\n", __func__, vha->vp_flags);
 
-   qla2x00_do_work(vha);
-
/* Check if Fw is ready to configure VP first */
if (test_bit(VP_CONFIG_OK, _vha->vp_flags)) {
if (test_and_clear_bit(VP_IDX_ACQUIRED, >vp_flags)) {
@@ -354,9 +352,7 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
 
ql_dbg(ql_dbg_dpc, vha, 0x4018,
"Relogin needed scheduled.\n");
-   qla2x00_relogin(vha);
-   ql_dbg(ql_dbg_dpc, vha, 0x4019,
-   "Relogin needed end.\n");
+   qla24xx_post_relogin_work(vha);
}
}
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 2e4bfb7aabf7..e1761bd552fe 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2698,14 +2698,22 @@ static void qla2x00_iocb_work_fn(struct work_struct 
*work)
 {
struct scsi_qla_host *vha = container_of(work,
struct scsi_qla_host, iocb_work);
-   int cnt = 0;
+   struct qla_hw_data *ha = vha->hw;
+   struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+   int i = 20;
+   unsigned long flags;
+
+   if (test_bit(UNLOADING, _vha->dpc_flags))
+   return;
 
-   while (!list_empty(>work_list)) {
+   while (!list_empty(>work_list) && i > 0) {
qla2x00_do_work(vha);
-   cnt++;
-   if (cnt > 10)
-   break;
+   i--;
}
+
+   spin_lock_irqsave(>work_lock, flags);
+   clear_bit(IOCB_WORK_ACTIVE, >dpc_flags);
+   spin_unlock_irqrestore(>work_lock, flags);
 }
 
 /*
@@ -3203,7 +3211,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct 
pci_device_id *id)
   

[PATCH v2 19/37] qla2xxx: Add lock protection around host lookup

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Host lookup via btree is currently protected by the hardware_lock.
Add hardware_lock when modifying btree to store host pointer.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_init.c   | 3 +++
 drivers/scsi/qla2xxx/qla_mid.c| 9 +
 drivers/scsi/qla2xxx/qla_target.c | 6 --
 3 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index f26acb7ce315..4f4d8b2b7b32 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3939,6 +3939,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
port_id_t id;
+   unsigned long flags;
 
/* Get host addresses. */
rval = qla2x00_get_adapter_id(vha,
@@ -4020,7 +4021,9 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
id.b.area = area;
id.b.al_pa = al_pa;
id.b.rsvd_1 = 0;
+   spin_lock_irqsave(>hardware_lock, flags);
qlt_update_host_map(vha, id);
+   spin_unlock_irqrestore(>hardware_lock, flags);
 
if (!vha->flags.init_done)
ql_log(ql_log_info, vha, 0x2010,
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 2570146beae4..bf365f8a9d32 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -50,10 +50,11 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
 
spin_lock_irqsave(>vport_slock, flags);
list_add_tail(>list, >vp_list);
+   spin_unlock_irqrestore(>vport_slock, flags);
 
+   spin_lock_irqsave(>hardware_lock, flags);
qlt_update_vp_map(vha, SET_VP_IDX);
-
-   spin_unlock_irqrestore(>vport_slock, flags);
+   spin_unlock_irqrestore(>hardware_lock, flags);
 
mutex_unlock(>vport_lock);
return vp_id;
@@ -158,9 +159,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
atomic_set(>loop_down_timer, LOOP_DOWN_TIME);
 
/* Remove port id from vp target map */
-   spin_lock_irqsave(>hw->vport_slock, flags);
+   spin_lock_irqsave(>hw->hardware_lock, flags);
qlt_update_vp_map(vha, RESET_AL_PA);
-   spin_unlock_irqrestore(>hw->vport_slock, flags);
+   spin_unlock_irqrestore(>hw->hardware_lock, flags);
 
qla2x00_mark_vp_devices_dead(vha);
atomic_set(>vp_state, VP_FAILED);
diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index d4ead404100c..5695fc249b73 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -7184,20 +7184,14 @@ qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
 
 void qlt_update_host_map(struct scsi_qla_host *vha, port_id_t id)
 {
-   unsigned long flags;
-   struct qla_hw_data *ha = vha->hw;
 
if (!vha->d_id.b24) {
-   spin_lock_irqsave(>vport_slock, flags);
vha->d_id = id;
qlt_update_vp_map(vha, SET_AL_PA);
-   spin_unlock_irqrestore(>vport_slock, flags);
} else if (vha->d_id.b24 != id.b24) {
-   spin_lock_irqsave(>vport_slock, flags);
qlt_update_vp_map(vha, RESET_AL_PA);
vha->d_id = id;
qlt_update_vp_map(vha, SET_AL_PA);
-   spin_unlock_irqrestore(>vport_slock, flags);
}
 }
 
-- 
2.12.0



[PATCH v2 20/37] qla2xxx: Reduce the use of terminate exchange

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

reduce usage of terminate exchange when command encounter
resource bottle neck.  Remote initiator view it as command
drop.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_target.c | 140 --
 1 file changed, 74 insertions(+), 66 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index 5695fc249b73..b23d3a187758 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -75,7 +75,8 @@ MODULE_PARM_DESC(ql2xuctrlirq,
 
 int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE;
 
-static int temp_sam_status = SAM_STAT_BUSY;
+static int qla_sam_status = SAM_STAT_BUSY;
+static int tc_sam_status = SAM_STAT_TASK_SET_FULL; /* target core */
 
 /*
  * From scsi/fc/fc_fcp.h
@@ -4275,14 +4276,14 @@ static void qlt_create_sess_from_atio(struct 
work_struct *work)
if (op->atio.u.raw.entry_count > 1) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023,
"Dropping multy entry atio %p\n", >atio);
-   goto out_term;
+   goto out_busy;
}
 
sess = qlt_make_local_sess(vha, s_id);
/* sess has an extra creation ref. */
 
if (!sess)
-   goto out_term;
+   goto out_busy;
/*
 * Now obtain a pre-allocated session tag using the original op->atio
 * packet header, and dispatch into __qlt_do_work() using the existing
@@ -4293,7 +4294,7 @@ static void qlt_create_sess_from_atio(struct work_struct 
*work)
struct qla_qpair *qpair = ha->base_qpair;
 
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
-   qlt_send_busy(qpair, >atio, SAM_STAT_BUSY);
+   qlt_send_busy(qpair, >atio, tc_sam_status);
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
 
spin_lock_irqsave(>tgt.sess_lock, flags);
@@ -4313,6 +4314,17 @@ static void qlt_create_sess_from_atio(struct work_struct 
*work)
 out_term:
qlt_send_term_exchange(vha->hw->base_qpair, NULL, >atio, 0, 0);
kfree(op);
+   return;
+out_busy:
+   {
+   struct qla_qpair *qpair = ha->base_qpair;
+
+   spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+   qlt_send_busy(qpair, >atio, qla_sam_status);
+   spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+   kfree(op);
+   }
+   return;
 }
 
 /* ha->hardware_lock supposed to be held on entry */
@@ -4329,7 +4341,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host 
*vha,
if (unlikely(tgt->tgt_stop)) {
ql_dbg(ql_dbg_io, vha, 0x3061,
"New command while device %p is shutting down\n", tgt);
-   return -EFAULT;
+   return -ENODEV;
}
 
id.b.al_pa = atio->u.isp24.fcp_hdr.s_id[2];
@@ -4384,7 +4396,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host 
*vha,
spin_lock_irqsave(>tgt.sess_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(>tgt.sess_lock, flags);
-   return -ENOMEM;
+   return -EBUSY;
}
 
cmd->cmd_in_wq = 1;
@@ -5485,7 +5497,6 @@ qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, 
struct qla_qpair *qpair,
struct atio_from_isp *atio, uint8_t ha_locked)
 {
struct qla_hw_data *ha = vha->hw;
-   uint16_t status;
unsigned long flags;
 
if (ha->tgt.num_pend_cmds < Q_FULL_THRESH_HOLD(ha))
@@ -5493,8 +5504,7 @@ qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, 
struct qla_qpair *qpair,
 
if (!ha_locked)
spin_lock_irqsave(>hardware_lock, flags);
-   status = temp_sam_status;
-   qlt_send_busy(qpair, atio, status);
+   qlt_send_busy(qpair, atio, qla_sam_status);
if (!ha_locked)
spin_unlock_irqrestore(>hardware_lock, flags);
 
@@ -5509,7 +5519,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
struct qla_hw_data *ha = vha->hw;
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
int rc;
-   unsigned long flags;
+   unsigned long flags = 0;
 
if (unlikely(tgt == NULL)) {
ql_dbg(ql_dbg_tgt, vha, 0x3064,
@@ -5533,8 +5543,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
"sending QUEUE_FULL\n", vha->vp_idx);
if (!ha_locked)
spin_lock_irqsave(>hardware_lock, flags);
-   qlt_send_busy(ha->base_qpair, atio,
-   SAM_STAT_TASK_SET_FULL);
+   qlt_send_busy(ha->base_qpair, atio, qla_sam_status);
if (!ha_locked)
spin_unlock_irqrestore(>hardware_lock,

[PATCH v2 10/37] qla2xxx: Use shadow register for ISP27XX

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

For ISP27XX, use shadow register to read FW provided REQQ's consumer
index. The shadow register is dma'ed by firmware.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_iocb.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 2d523b71cc1f..d1dfa784d895 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2158,7 +2158,9 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp)
 skip_cmd_array:
/* Check for room on request queue. */
if (req->cnt < req_cnt + 2) {
-   if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+   if (qpair->use_shadow_reg)
+   cnt = *req->out_ptr;
+   else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha))
cnt = RD_REG_DWORD(>isp25mq.req_q_out);
else if (IS_P3P_TYPE(ha))
cnt = RD_REG_DWORD(>isp82.req_q_out);
-- 
2.12.0



[PATCH v2 05/37] qla2xxx: Chip reset uses wrong lock during IO flush.

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

As part of chip reset, all commands from all QPairs are
flushed. This patch fixes code to use Q Pair lock for flush
instead of using old hardware_lock.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_os.c | 158 ++
 1 file changed, 84 insertions(+), 74 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 029b95b2bd8a..2e4bfb7aabf7 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1704,93 +1704,103 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
return QLA_SUCCESS;
 }
 
-void
-qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
+static void
+__qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
 {
-   int que, cnt, status;
+   int cnt, status;
unsigned long flags;
srb_t *sp;
+   scsi_qla_host_t *vha = qp->vha;
struct qla_hw_data *ha = vha->hw;
struct req_que *req;
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
struct qla_tgt_cmd *cmd;
uint8_t trace = 0;
 
-   spin_lock_irqsave(>hardware_lock, flags);
-   for (que = 0; que < ha->max_req_queues; que++) {
-   req = ha->req_q_map[que];
-   if (!req)
-   continue;
-   if (!req->outstanding_cmds)
-   continue;
-   for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
-   sp = req->outstanding_cmds[cnt];
-   if (sp) {
-   req->outstanding_cmds[cnt] = NULL;
-   if (sp->cmd_type == TYPE_SRB) {
-   if (sp->type == SRB_NVME_CMD ||
-   sp->type == SRB_NVME_LS) {
-   sp_get(sp);
-   spin_unlock_irqrestore(
-   >hardware_lock, flags);
-   qla_nvme_abort(ha, sp);
-   spin_lock_irqsave(
-   >hardware_lock, flags);
-   } else if (GET_CMD_SP(sp) &&
-   !ha->flags.eeh_busy &&
-   (!test_bit(ABORT_ISP_ACTIVE,
-   >dpc_flags)) &&
-   (sp->type == SRB_SCSI_CMD)) {
-   /*
-* Don't abort commands in
-* adapter during EEH
-* recovery as it's not
-* accessible/responding.
-*
-* Get a reference to the sp
-* and drop the lock. The
-* reference ensures this
-* sp->done() call and not the
-* call in qla2xxx_eh_abort()
-* ends the SCSI command (with
-* result 'res').
-*/
-   sp_get(sp);
-   spin_unlock_irqrestore(
-   >hardware_lock, flags);
-   status = qla2xxx_eh_abort(
-   GET_CMD_SP(sp));
-   spin_lock_irqsave(
-   >hardware_lock, flags);
-   /*
-* Get rid of extra reference
-* if immediate exit from
-* ql2xxx_eh_abort
-*/
-   if (status == FAILED &&
-   (qla2x00_isp_reg_stat(ha)))
-   atomic_dec(
-   >ref_count);
-   }
-   sp->done(sp, res);
-   } else {
-   if (!vha->hw->tgt.tgt_ops || !tgt ||
-

[PATCH v2 02/37] qla2xxx: Use IOCB path to submit Control VP MBX command

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Use IOCB patch to submit Control VP MBX command to reduce
bottle-neck for mbx interface.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h|  7 
 drivers/scsi/qla2xxx/qla_init.c   |  1 +
 drivers/scsi/qla2xxx/qla_inline.h |  1 +
 drivers/scsi/qla2xxx/qla_iocb.c   | 23 
 drivers/scsi/qla2xxx/qla_isr.c| 35 ++
 drivers/scsi/qla2xxx/qla_mbx.c| 77 ---
 drivers/scsi/qla2xxx/qla_mid.c| 76 ++
 7 files changed, 143 insertions(+), 77 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 93ff92e2363f..969a7dee9f72 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -472,6 +472,10 @@ struct srb_iocb {
uint32_t timeout_sec;
struct  list_head   entry;
} nvme;
+   struct {
+   u16 cmd;
+   u16 vp_index;
+   } ctrlvp;
} u;
 
struct timer_list timer;
@@ -500,6 +504,7 @@ struct srb_iocb {
 #define SRB_NVME_CMD   19
 #define SRB_NVME_LS20
 #define SRB_PRLI_CMD   21
+#define SRB_CTRL_VP22
 
 enum {
TYPE_SRB,
@@ -526,6 +531,8 @@ typedef struct srb {
struct list_head elem;
u32 gen1;   /* scratch */
u32 gen2;   /* scratch */
+   int rc;
+   struct completion comp;
union {
struct srb_iocb iocb_cmd;
struct bsg_job *bsg_job;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index b650ebec1b9d..5fef2bf55a9f 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -135,6 +135,7 @@ qla2x00_async_iocb_timeout(void *data)
case SRB_NACK_PLOGI:
case SRB_NACK_PRLI:
case SRB_NACK_LOGO:
+   case SRB_CTRL_VP:
sp->done(sp, QLA_FUNCTION_TIMEOUT);
break;
}
diff --git a/drivers/scsi/qla2xxx/qla_inline.h 
b/drivers/scsi/qla2xxx/qla_inline.h
index 17d2c20f1f75..4d32426393c7 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -273,6 +273,7 @@ qla2x00_init_timer(srb_t *sp, unsigned long tmo)
sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ;
add_timer(>u.iocb_cmd.timer);
sp->free = qla2x00_sp_free;
+   init_completion(>comp);
if (IS_QLAFX00(sp->vha->hw) && (sp->type == SRB_FXIOCB_DCMD))
init_completion(>u.iocb_cmd.u.fxiocb.fxiocb_comp);
if (sp->type == SRB_ELS_DCMD)
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 8ea59586f4f1..2d523b71cc1f 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -3368,6 +3368,26 @@ qla_nvme_ls(srb_t *sp, struct pt_ls4_request *cmd_pkt)
return rval;
 }
 
+static void
+qla25xx_ctrlvp_iocb(srb_t *sp, struct vp_ctrl_entry_24xx *vce)
+{
+   int map, pos;
+
+   vce->entry_type = VP_CTRL_IOCB_TYPE;
+   vce->handle = sp->handle;
+   vce->entry_count = 1;
+   vce->command = cpu_to_le16(sp->u.iocb_cmd.u.ctrlvp.cmd);
+   vce->vp_count = cpu_to_le16(1);
+
+   /*
+* index map in firmware starts with 1; decrement index
+* this is ok as we never use index 0
+*/
+   map = (sp->u.iocb_cmd.u.ctrlvp.vp_index - 1) / 8;
+   pos = (sp->u.iocb_cmd.u.ctrlvp.vp_index - 1) & 7;
+   vce->vp_idx_map[map] |= 1 << pos;
+}
+
 int
 qla2x00_start_sp(srb_t *sp)
 {
@@ -3446,6 +3466,9 @@ qla2x00_start_sp(srb_t *sp)
case SRB_NACK_LOGO:
qla2x00_send_notify_ack_iocb(sp, pkt);
break;
+   case SRB_CTRL_VP:
+   qla25xx_ctrlvp_iocb(sp, pkt);
+   break;
default:
break;
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index a55bfaa790a3..a265c2d8c9cc 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1937,6 +1937,37 @@ qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct 
req_que *req, void *tsk)
sp->done(sp, ret);
 }
 
+static void qla_ctrlvp_completed(scsi_qla_host_t *vha, struct req_que *req,
+struct vp_ctrl_entry_24xx *vce)
+{
+   const char func[] = "CTRLVP-IOCB";
+   srb_t *sp;
+   int rval = QLA_SUCCESS;
+
+   sp = qla2x00_get_sp_from_handle(vha, func, req, vce);
+   if (!sp)
+   return;
+
+   if (vce->entry_status != 0) {
+   ql_dbg(ql_dbg_vport, vha, 0x10c4,
+   "%s: Failed to complete IOCB -- error status (%x)\n",
+   sp->name, vce->entry_status);
+   rval = QLA_FUNCTION_FAILED;
+   } else if (vce->comp_status != cpu_to_le16(CS_COMPLETE)) {
+   

[PATCH v2 06/37] qla2xxx: Fix Firmware dump size for Extended login and Exchange Offload

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

This patch adjusts and reallocates fw_dump memory for target mode
to save for extended login and exchange offload buffers into
dump captured.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_init.c | 209 +---
 drivers/scsi/qla2xxx/qla_tmpl.c |  40 +++-
 2 files changed, 147 insertions(+), 102 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 5fef2bf55a9f..fc307752b2f5 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2593,70 +2593,27 @@ qla24xx_chip_diag(scsi_qla_host_t *vha)
return rval;
 }
 
-void
-qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
+static void
+qla2x00_alloc_offload_mem(scsi_qla_host_t *vha)
 {
int rval;
-   uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size,
-   eft_size, fce_size, mq_size;
dma_addr_t tc_dma;
void *tc;
struct qla_hw_data *ha = vha->hw;
-   struct req_que *req = ha->req_q_map[0];
-   struct rsp_que *rsp = ha->rsp_q_map[0];
 
-   if (ha->fw_dump) {
+   if (ha->eft) {
ql_dbg(ql_dbg_init, vha, 0x00bd,
-   "Firmware dump already allocated.\n");
+   "%s: Offload Mem is already allocated.\n",
+   __func__);
return;
}
 
-   ha->fw_dumped = 0;
-   ha->fw_dump_cap_flags = 0;
-   dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0;
-   req_q_size = rsp_q_size = 0;
-
-   if (IS_QLA27XX(ha))
-   goto try_fce;
-
-   if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
-   fixed_size = sizeof(struct qla2100_fw_dump);
-   } else if (IS_QLA23XX(ha)) {
-   fixed_size = offsetof(struct qla2300_fw_dump, data_ram);
-   mem_size = (ha->fw_memory_size - 0x11000 + 1) *
-   sizeof(uint16_t);
-   } else if (IS_FWI2_CAPABLE(ha)) {
-   if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
-   fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
-   else if (IS_QLA81XX(ha))
-   fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
-   else if (IS_QLA25XX(ha))
-   fixed_size = offsetof(struct qla25xx_fw_dump, ext_mem);
-   else
-   fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem);
-
-   mem_size = (ha->fw_memory_size - 0x10 + 1) *
-   sizeof(uint32_t);
-   if (ha->mqenable) {
-   if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
-   mq_size = sizeof(struct qla2xxx_mq_chain);
-   /*
-* Allocate maximum buffer size for all queues.
-* Resizing must be done at end-of-dump processing.
-*/
-   mq_size += ha->max_req_queues *
-   (req->length * sizeof(request_t));
-   mq_size += ha->max_rsp_queues *
-   (rsp->length * sizeof(response_t));
-   }
-   if (ha->tgt.atio_ring)
-   mq_size += ha->tgt.atio_q_length * sizeof(request_t);
+   if (IS_FWI2_CAPABLE(ha)) {
/* Allocate memory for Fibre Channel Event Buffer. */
if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
!IS_QLA27XX(ha))
goto try_eft;
 
-try_fce:
if (ha->fce)
dma_free_coherent(>pdev->dev,
FCE_SIZE, ha->fce, ha->fce_dma);
@@ -2684,7 +2641,6 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_init, vha, 0x00c0,
"Allocate (%d KB) for FCE...\n", FCE_SIZE / 1024);
 
-   fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
ha->flags.fce_enabled = 1;
ha->fce_dma = tc_dma;
ha->fce = tc;
@@ -2701,7 +2657,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
ql_log(ql_log_warn, vha, 0x00c1,
"Unable to allocate (%d KB) for EFT.\n",
EFT_SIZE / 1024);
-   goto cont_alloc;
+   goto eft_err;
}
 
rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
@@ -2710,17 +2666,76 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
"Unable to initialize EFT (%d).\n", rval);
dma_free_coherent(>pdev->dev, EFT_SIZE, tc,
tc_dma);
-   goto cont_alloc;
+   goto eft_err;
}

[PATCH v2 04/37] qla2xxx: Add boundary checks for exchanges to be offloaded

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Max boundary for exchange off load is 32k exchanges. If a system
is unable to allocate large memory buffer to support this feature,
then driver will reduce the number of exchanges down to a value
system can support.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h |  3 +++
 drivers/scsi/qla2xxx/qla_os.c  | 39 ++-
 2 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 969a7dee9f72..043dd51a2760 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -288,6 +288,8 @@ struct name_list_extended {
 #define ATIO_ENTRY_CNT_24XX4096/* Number of ATIO entries. */
 #define RESPONSE_ENTRY_CNT_FX00256 /* Number of response 
entries.*/
 #define FW_DEF_EXCHANGES_CNT 2048
+#define FW_MAX_EXCHANGES_CNT (32 * 1024)
+#define REDUCE_EXCHANGES_CNT  (8 * 1024)
 
 struct req_que;
 struct qla_tgt_sess;
@@ -3506,6 +3508,7 @@ struct qla_hw_data {
uint32_tusing_lr_setting:1;
} flags;
 
+   uint16_t max_exchg;
uint16_t long_range_distance;   /* 32G & above */
 #define LR_DISTANCE_5K  1
 #define LR_DISTANCE_10K 0
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 987bade1c606..029b95b2bd8a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2789,6 +2789,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct 
pci_device_id *id)
ha->init_cb_size = sizeof(init_cb_t);
ha->link_data_rate = PORT_SPEED_UNKNOWN;
ha->optrom_size = OPTROM_SIZE_2300;
+   ha->max_exchg = FW_MAX_EXCHANGES_CNT;
 
/* Assign ISP specific operations. */
if (IS_QLA2100(ha)) {
@@ -4230,6 +4231,9 @@ qla2x00_number_of_exch(scsi_qla_host_t *vha, u32 
*ret_cnt, u16 max_cnt)
u32 temp;
*ret_cnt = FW_DEF_EXCHANGES_CNT;
 
+   if (max_cnt > vha->hw->max_exchg)
+   max_cnt = vha->hw->max_exchg;
+
if (qla_ini_mode_enabled(vha)) {
if (ql2xiniexchg > max_cnt)
ql2xiniexchg = max_cnt;
@@ -4259,8 +4263,8 @@ int
 qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
 {
int rval;
-   u16 size, max_cnt;
-   u32 temp;
+   u16 size, max_cnt;
+   u32 actual_cnt, totsz;
struct qla_hw_data *ha = vha->hw;
 
if (!ha->flags.exchoffld_enabled)
@@ -4277,16 +4281,19 @@ qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
return rval;
}
 
-   qla2x00_number_of_exch(vha, , max_cnt);
-   temp *= size;
+   qla2x00_number_of_exch(vha, _cnt, max_cnt);
+   ql_log(ql_log_info, vha, 0xd014,
+   "Actual exchange offload count: %d.\n", actual_cnt);
+
+   totsz = actual_cnt * size;
 
-   if (temp != ha->exchoffld_size) {
+   if (totsz != ha->exchoffld_size) {
qla2x00_free_exchoffld_buffer(ha);
-   ha->exchoffld_size = temp;
+   ha->exchoffld_size = totsz;
 
ql_log(ql_log_info, vha, 0xd016,
-   "Exchange offload: max_count=%d, buffers=0x%x, total=%d.\n",
-   max_cnt, size, temp);
+   "Exchange offload: max_count=%d, actual count=%d entry 
sz=0x%x, total sz=0x%x\n",
+   max_cnt, actual_cnt, size, totsz);
 
ql_log(ql_log_info, vha, 0xd017,
"Exchange Buffers requested size = 0x%x\n",
@@ -4297,7 +4304,21 @@ qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
ha->exchoffld_size, >exchoffld_buf_dma, GFP_KERNEL);
if (!ha->exchoffld_buf) {
ql_log_pci(ql_log_fatal, ha->pdev, 0xd013,
-   "Failed to allocate memory for exchoffld_buf_dma.\n");
+   "Failed to allocate memory for Exchange Offload.\n");
+
+   if (ha->max_exchg >
+   (FW_DEF_EXCHANGES_CNT + REDUCE_EXCHANGES_CNT)) {
+   ha->max_exchg -= REDUCE_EXCHANGES_CNT;
+   } else if (ha->max_exchg >
+   (FW_DEF_EXCHANGES_CNT + 512)) {
+   ha->max_exchg -= 512;
+   } else {
+   ha->flags.exchoffld_enabled = 0;
+   ql_log_pci(ql_log_fatal, ha->pdev, 0xd013,
+   "Disabling Exchange offload due to lack of 
memory\n");
+   }
+   ha->exchoffld_size = 0;
+
return -ENOMEM;
}
}
-- 
2.12.0



[PATCH v2 00/37] qla2xxx: driver updates

2017-12-28 Thread Himanshu Madhani
Hi Martin, 

This series contains number of improvments in handling of switch 
registration commands in the driver. Switch commands are now submitted
via IOCB patch asynchronously instead of mailbox interface.

Please apply this series to 4.16/scsi-queue branch at your earliest
convenience. 

Changes from v1 -> v2

o Drop patches which needs more work from Bart's comments. These dropped
  patches will be included in the next driver update after necessary rework.

Thanks,
Himanshu

Giridhar Malavali (1):
  qla2xxx: Don't call dma_free_coherent with IRQ disabled.

Himanshu Madhani (3):
  qla2xxx: Use known NPort ID for Management Server login
  qla2xxx: Allow relogin and session creation after reset
  qla2xxx: Update driver version to 10.00.00.04-k

Quinn Tran (33):
  qla2xxx: Fix NULL pointer access for fcport structure
  qla2xxx: Use IOCB path to submit Control VP MBX command
  qla2xxx: Use chip reset to bring down laser on unload.
  qla2xxx: Add boundary checks for exchanges to be offloaded
  qla2xxx: Chip reset uses wrong lock during IO flush.
  qla2xxx: Fix Firmware dump size for Extended login and Exchange
Offload
  qla2xxx: Replace GPDB with async ADISC command
  qla2xxx: Move work element processing out of DPC thread
  qla2xxx: Enable ATIO interrupt handshake for ISP27XX
  qla2xxx: Use shadow register for ISP27XX
  qla2xxx: Add option for use reserve exch for ELS
  qla2xxx: Add ability to send PRLO
  qla2xxx: Allow target mode to accept PRLI in dual mode
  qla2xxx: Tweak resource count dump
  qla2xxx: Fix session cleanup for N2N
  qla2xxx: Add switch command to simplify fabric discovery
  qla2xxx: Add lock protection around host lookup
  qla2xxx: Reduce the use of terminate exchange
  qla2xxx: Reduce trace noise for Async Events
  qla2xxx: Fix login state machine freeze
  qla2xxx: Migrate switch registration commands away from mailbox
interface
  qla2xxx: Remove session creation redundant code
  qla2xxx: Fix GPNFT/GNNFT error handling
  qla2xxx: Properly extract ADISC error codes
  qla2xxx: Add ability to use GPNFT/GNNFT for RSCN handling
  qla2xxx: Increase verbosity of debug messages logged
  qla2xxx: Delay loop id allocation at login
  qla2xxx: Add retry limit for fabric scan logic
  qla2xxx: Prevent multiple active discovery commands per session
  qla2xxx: Prevent relogin trigger from sending too many commands
  qla2xxx: Remove unused argument from qlt_schedule_sess_for_deletion()
  qla2xxx: Serialize session deletion by using work_lock
  qla2xxx: Serialize session free in qlt_free_session_done

 drivers/scsi/qla2xxx/qla_attr.c|2 +
 drivers/scsi/qla2xxx/qla_def.h |  123 +++-
 drivers/scsi/qla2xxx/qla_dfs.c |   32 +-
 drivers/scsi/qla2xxx/qla_fw.h  |2 +-
 drivers/scsi/qla2xxx/qla_gbl.h |   32 +-
 drivers/scsi/qla2xxx/qla_gs.c  | 1297 +++-
 drivers/scsi/qla2xxx/qla_init.c|  983 +--
 drivers/scsi/qla2xxx/qla_inline.h  |1 +
 drivers/scsi/qla2xxx/qla_iocb.c|   44 +-
 drivers/scsi/qla2xxx/qla_isr.c |   44 +-
 drivers/scsi/qla2xxx/qla_mbx.c |  148 ++--
 drivers/scsi/qla2xxx/qla_mid.c |  104 ++-
 drivers/scsi/qla2xxx/qla_os.c  |  460 -
 drivers/scsi/qla2xxx/qla_target.c  |  704 ++-
 drivers/scsi/qla2xxx/qla_target.h  |4 +-
 drivers/scsi/qla2xxx/qla_tmpl.c|   40 +-
 drivers/scsi/qla2xxx/qla_version.h |2 +-
 17 files changed, 2891 insertions(+), 1131 deletions(-)

-- 
2.12.0



[PATCH v2 17/37] qla2xxx: Use known NPort ID for Management Server login

2017-12-28 Thread Himanshu Madhani
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h | 4 ++--
 drivers/scsi/qla2xxx/qla_mid.c | 2 +-
 drivers/scsi/qla2xxx/qla_os.c  | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index a7b810213aac..bf50b4fbe648 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -246,8 +246,8 @@
  * There is no correspondence between an N-PORT id and an AL_PA.  Therefore the
  * valid range of an N-PORT id is 0 through 0x7ef.
  */
-#define NPH_LAST_HANDLE0x7ef
-#define NPH_MGMT_SERVER0x7fa   /*  FA */
+#define NPH_LAST_HANDLE0x7ee
+#define NPH_MGMT_SERVER0x7ef   /*  EF */
 #define NPH_SNS0x7fc   /*  FC */
 #define NPH_FABRIC_CONTROLLER  0x7fd   /*  FD */
 #define NPH_F_PORT 0x7fe   /*  FE */
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 966ff0f1bed4..2570146beae4 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -477,7 +477,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
"Couldn't allocate vp_id.\n");
goto create_vhost_failed;
}
-   vha->mgmt_svr_loop_id = 10 + vha->vp_idx;
+   vha->mgmt_svr_loop_id = NPH_MGMT_SERVER;
 
vha->dpc_flags = 0L;
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 38d6d12571f7..4c3527f54b74 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3047,7 +3047,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct 
pci_device_id *id)
host = base_vha->host;
base_vha->req = req;
if (IS_QLA2XXX_MIDTYPE(ha))
-   base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx;
+   base_vha->mgmt_svr_loop_id = NPH_MGMT_SERVER;
else
base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER +
base_vha->vp_idx;
-- 
2.12.0



[PATCH v2 15/37] qla2xxx: Tweak resource count dump

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Fetch actual data from firmware instead of static data
at chip reset time.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_dfs.c | 32 +---
 drivers/scsi/qla2xxx/qla_gbl.h |  1 +
 drivers/scsi/qla2xxx/qla_mbx.c | 30 ++
 3 files changed, 48 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index d231e7156134..ddb53db61fd2 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -127,21 +127,23 @@ static int
 qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused)
 {
struct scsi_qla_host *vha = s->private;
-   struct qla_hw_data *ha = vha->hw;
-
-   seq_puts(s, "FW Resource count\n\n");
-   seq_printf(s, "Original TGT exchg count[%d]\n",
-   ha->orig_fw_tgt_xcb_count);
-   seq_printf(s, "current TGT exchg count[%d]\n",
-   ha->cur_fw_tgt_xcb_count);
-   seq_printf(s, "original Initiator Exchange count[%d]\n",
-   ha->orig_fw_xcb_count);
-   seq_printf(s, "Current Initiator Exchange count[%d]\n",
-   ha->cur_fw_xcb_count);
-   seq_printf(s, "Original IOCB count[%d]\n", ha->orig_fw_iocb_count);
-   seq_printf(s, "Current IOCB count[%d]\n", ha->cur_fw_iocb_count);
-   seq_printf(s, "MAX VP count[%d]\n", ha->max_npiv_vports);
-   seq_printf(s, "MAX FCF count[%d]\n", ha->fw_max_fcf_count);
+   uint16_t mb[MAX_IOCB_MB_REG];
+   int rc;
+
+   rc = qla24xx_res_count_wait(vha, mb, SIZEOF_IOCB_MB_REG);
+   if (rc != QLA_SUCCESS) {
+   seq_printf(s, "Mailbox Command failed %d, mb %#x", rc, mb[0]);
+   } else {
+   seq_puts(s, "FW Resource count\n\n");
+   seq_printf(s, "Original TGT exchg count[%d]\n", mb[1]);
+   seq_printf(s, "current TGT exchg count[%d]\n", mb[2]);
+   seq_printf(s, "original Initiator Exchange count[%d]\n", mb[3]);
+   seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[6]);
+   seq_printf(s, "Original IOCB count[%d]\n", mb[7]);
+   seq_printf(s, "Current IOCB count[%d]\n", mb[10]);
+   seq_printf(s, "MAX VP count[%d]\n", mb[11]);
+   seq_printf(s, "MAX FCF count[%d]\n", mb[12]);
+   }
 
return 0;
 }
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 7b61c96502e4..9d7b66abfc10 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -504,6 +504,7 @@ int qla24xx_get_port_login_templ(scsi_qla_host_t *, 
dma_addr_t,
 
 extern int qla27xx_get_zio_threshold(scsi_qla_host_t *, uint16_t *);
 extern int qla27xx_set_zio_threshold(scsi_qla_host_t *, uint16_t);
+int qla24xx_res_count_wait(struct scsi_qla_host *, uint16_t *, int);
 
 /*
  * Global Function Prototypes in qla_isr.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index dea2e66be0b1..adc93a505f15 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -17,6 +17,7 @@ static struct mb_cmd_name {
{MBC_GET_PORT_DATABASE, "GPDB"},
{MBC_GET_ID_LIST,   "GIDList"},
{MBC_GET_LINK_PRIV_STATS,   "Stats"},
+   {MBC_GET_RESOURCE_COUNTS,   "ResCnt"},
 };
 
 static const char *mb_to_str(uint16_t cmd)
@@ -6272,3 +6273,32 @@ qla2x00_read_sfp_dev(struct scsi_qla_host *vha, char 
*buf, int count)
 
return rval;
 }
+
+int qla24xx_res_count_wait(struct scsi_qla_host *vha,
+uint16_t *out_mb, int out_mb_sz)
+{
+   int rval = QLA_FUNCTION_FAILED;
+   mbx_cmd_t mc;
+
+   if (!vha->hw->flags.fw_started)
+   goto done;
+
+   memset(, 0, sizeof(mc));
+   mc.mb[0] = MBC_GET_RESOURCE_COUNTS;
+
+   rval = qla24xx_send_mb_cmd(vha, );
+   if (rval != QLA_SUCCESS) {
+   ql_dbg(ql_dbg_mbx, vha, 0x,
+   "%s:  fail\n", __func__);
+   } else {
+   if (out_mb_sz <= SIZEOF_IOCB_MB_REG)
+   memcpy(out_mb, mc.mb, out_mb_sz);
+   else
+   memcpy(out_mb, mc.mb, SIZEOF_IOCB_MB_REG);
+
+   ql_dbg(ql_dbg_mbx, vha, 0x,
+   "%s:  done\n", __func__);
+   }
+done:
+   return rval;
+}
-- 
2.12.0



[PATCH v2 07/37] qla2xxx: Replace GPDB with async ADISC command

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Replace call to Get Port DataBase MB with PDO_FORCE_ADISC
flag with async ADISC command so driver can see ADISC command
has error or not.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h  |  2 ++
 drivers/scsi/qla2xxx/qla_gs.c   | 20 -
 drivers/scsi/qla2xxx/qla_init.c | 65 ++---
 3 files changed, 50 insertions(+), 37 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 043dd51a2760..ca2ad477a4df 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2277,6 +2277,7 @@ enum discovery_state {
DSC_GPSC,
DSC_UPD_FCPORT,
DSC_LOGIN_COMPLETE,
+   DSC_ADISC,
DSC_DELETE_PEND,
 };
 
@@ -2303,6 +2304,7 @@ enum fcport_mgt_event {
FCME_GPNID_DONE,
FCME_GFFID_DONE,
FCME_DELETE_DONE,
+   FCME_ADISC_DONE,
 };
 
 enum rscn_addr_format {
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 07fe17a986b0..bb96219ce525 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -2823,15 +2823,19 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
"%s %d %8phC post %s\n", __func__,
__LINE__, fcport->port_name,
(atomic_read(>state) ==
-   FCS_ONLINE) ? "gpdb" : "gnl");
+   FCS_ONLINE) ? "adisc" : "gnl");
 
if (atomic_read(>state) ==
-   FCS_ONLINE)
-   qla24xx_post_gpdb_work(vha,
-   fcport, PDO_FORCE_ADISC);
-   else
+   FCS_ONLINE) {
+   u16 data[2];
+
+   data[0] = data[1] = 0;
+   qla2x00_post_async_adisc_work(
+   vha, fcport, data);
+   } else {
qla24xx_post_gnl_work(vha,
fcport);
+   }
break;
}
} else { /* fcport->d_id.b24 != ea->id.b24 */
@@ -3172,6 +3176,7 @@ void qla24xx_async_gpnid_done(scsi_qla_host_t *vha, srb_t 
*sp)
 void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
fc_port_t *fcport, *conflict, *t;
+   u16 data[2];
 
ql_dbg(ql_dbg_disc, vha, 0x,
"%s %d port_id: %06x\n",
@@ -3246,8 +3251,9 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
ql_dbg(ql_dbg_disc, vha, 0x210d,
"%s %d %8phC revalidate session with 
ADISC\n",
__func__, __LINE__, fcport->port_name);
-   qla24xx_post_gpdb_work(vha, fcport,
-   PDO_FORCE_ADISC);
+   data[0] = data[1] = 0;
+   qla2x00_post_async_adisc_work(vha, fcport,
+   data);
break;
case DSC_DELETED:
ql_dbg(ql_dbg_disc, vha, 0x210d,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index fc307752b2f5..93d0077ba388 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -41,6 +41,7 @@ static void qla24xx_handle_plogi_done_event(struct 
scsi_qla_host *,
 struct event_arg *);
 static void qla24xx_handle_prli_done_event(struct scsi_qla_host *,
 struct event_arg *);
+static void qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *);
 
 /* SRB Extensions -- */
 
@@ -277,17 +278,31 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t 
*fcport)
fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
 }
+static
+void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
+{
+   qla24xx_handle_gpdb_event(vha, ea);
+}
 
 static void
 qla2x00_async_adisc_sp_done(void *ptr, int res)
 {
srb_t *sp = ptr;
struct scsi_qla_host *vha = sp->vha;
-   struct srb_iocb *lio = >u.iocb_cmd;
+   struct event_arg ea;
+
+   ql_dbg(ql_dbg_disc, vha, 0x2066,
+   "Async done-%s res %x %8phC\n",
+ 

[PATCH v2 13/37] qla2xxx: Don't call dma_free_coherent with IRQ disabled.

2017-12-28 Thread Himanshu Madhani
From: Giridhar Malavali 

The logo ELS command allocates dma coherent memory for the
data payload and serialize the completions. When this command
times out, the timeout routine completes the thread waiting
for completion which in turn cleanup resources allocated for
this ELS command processing. Don't call generic sp->free
routine when this ELS command times out to avoid to double
freeing of the same resources.

Signed-off-by: Giridhar Malavali 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_init.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 56bff7856cf8..4e6d3eb4caa4 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -59,7 +59,8 @@ qla2x00_sp_timeout(struct timer_list *t)
req->outstanding_cmds[sp->handle] = NULL;
iocb = >u.iocb_cmd;
iocb->timeout(sp);
-   sp->free(sp);
+   if (sp->type != SRB_ELS_DCMD)
+   sp->free(sp);
spin_unlock_irqrestore(>hw->hardware_lock, flags);
 }
 
-- 
2.12.0



[PATCH v2 03/37] qla2xxx: Use chip reset to bring down laser on unload.

2017-12-28 Thread Himanshu Madhani
From: Quinn Tran 

Current code uses Stop Firmware MB cmd to stop the chip before
driver unload.  This will leave the laser in its current state.
This give the illusion of this adapter is still alive.
For 8G & newer adapters, use chip reset to stop the chip and
bring down the laser.

Signed-off-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_os.c | 52 ++-
 1 file changed, 17 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 789030c9dd26..987bade1c606 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -294,7 +294,6 @@ static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
 
 static void qla2x00_clear_drv_active(struct qla_hw_data *);
 static void qla2x00_free_device(scsi_qla_host_t *);
-static void qla83xx_disable_laser(scsi_qla_host_t *vha);
 static int qla2xxx_map_queues(struct Scsi_Host *shost);
 static void qla2x00_destroy_deferred_work(struct qla_hw_data *);
 
@@ -3449,8 +3448,13 @@ qla2x00_shutdown(struct pci_dev *pdev)
if (ha->eft)
qla2x00_disable_eft_trace(vha);
 
-   /* Stop currently executing firmware. */
-   qla2x00_try_to_stop_firmware(vha);
+   if (IS_QLA25XX(ha) ||  IS_QLA2031(ha) || IS_QLA27XX(ha)) {
+   if (ha->flags.fw_started)
+   qla2x00_abort_isp_cleanup(vha);
+   } else {
+   /* Stop currently executing firmware. */
+   qla2x00_try_to_stop_firmware(vha);
+   }
 
/* Turn adapter off line */
vha->flags.online = 0;
@@ -3629,10 +3633,6 @@ qla2x00_remove_one(struct pci_dev *pdev)
 
qla84xx_put_chip(base_vha);
 
-   /* Laser should be disabled only for ISP2031 */
-   if (IS_QLA2031(ha))
-   qla83xx_disable_laser(base_vha);
-
/* Disable timer */
if (base_vha->timer_active)
qla2x00_stop_timer(base_vha);
@@ -3693,8 +3693,16 @@ qla2x00_free_device(scsi_qla_host_t *vha)
if (ha->eft)
qla2x00_disable_eft_trace(vha);
 
-   /* Stop currently executing firmware. */
-   qla2x00_try_to_stop_firmware(vha);
+   if (IS_QLA25XX(ha) ||  IS_QLA2031(ha) || IS_QLA27XX(ha)) {
+   if (ha->flags.fw_started)
+   qla2x00_abort_isp_cleanup(vha);
+   } else {
+   if (ha->flags.fw_started) {
+   /* Stop currently executing firmware. */
+   qla2x00_try_to_stop_firmware(vha);
+   ha->flags.fw_started = 0;
+   }
+   }
 
vha->flags.online = 0;
 
@@ -6617,32 +6625,6 @@ qla2xxx_pci_resume(struct pci_dev *pdev)
ha->flags.eeh_busy = 0;
 }
 
-static void
-qla83xx_disable_laser(scsi_qla_host_t *vha)
-{
-   uint32_t reg, data, fn;
-   struct qla_hw_data *ha = vha->hw;
-   struct device_reg_24xx __iomem *isp_reg = >iobase->isp24;
-
-   /* pci func #/port # */
-   ql_dbg(ql_dbg_init, vha, 0x004b,
-   "Disabling Laser for hba: %p\n", vha);
-
-   fn = (RD_REG_DWORD(_reg->ctrl_status) &
-   (BIT_15|BIT_14|BIT_13|BIT_12));
-
-   fn = (fn >> 12);
-
-   if (fn & 1)
-   reg = PORT_1_2031;
-   else
-   reg = PORT_0_2031;
-
-   data = LASER_OFF_2031;
-
-   qla83xx_wr_reg(vha, reg, data);
-}
-
 static int qla2xxx_map_queues(struct Scsi_Host *shost)
 {
int rc;
-- 
2.12.0



Re: [PATCH 2/2 v4] scsi: ufs: introduce sysfs entries exposing UFS health info

2017-12-28 Thread Jaegeuk Kim
On 12/27, Greg Kroah-Hartman wrote:
> On Wed, Dec 27, 2017 at 09:00:10AM +, Avri Altman wrote:
> > 
> > 
> > > -Original Message-
> > > From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi-
> > > ow...@vger.kernel.org] On Behalf Of Greg Kroah-Hartman
> > > Sent: Thursday, December 21, 2017 10:00 AM
> > > To: Jaegeuk Kim 
> > > Cc: linux-ker...@vger.kernel.org; linux-scsi@vger.kernel.org; Jaegeuk Kim
> > > 
> > > Subject: Re: [PATCH 2/2 v4] scsi: ufs: introduce sysfs entries exposing 
> > > UFS
> > > health info
> > > 
> > > On Wed, Dec 20, 2017 at 02:13:25PM -0800, Jaegeuk Kim wrote:
> > > > This patch adds a new sysfs group, namely health, via:
> > > >
> > > >/sys/devices/soc/X.ufshc/health/
> > As device health is just one piece of information out of the device 
> > management,
> > I think that you should address this in a more comprehensive way,
> > And set hooks for much more device info:
> > Allow access to device descriptors, attributes and flags.
> 
> Add on patches are easy to create for this if people really want and
> need it :)
> 
> > The attributes and flags should be placed in separate subfolders
> 
> Why?  What is that going to help with?
> 
> > The LUN specific descriptors and attributes should be placed in a luns
> > subfolder, and then per descriptor / attribute type
> 
> Again, why?
> 
> > You might also would like to consider differentiating read and write -
> > to control those type of accesses as well.
> 
> What do you mean by this exactly?
> 
> As it is, this is a step forward in getting attributes that people are
> asking for and already using, into the kernel tree.  Please don't object
> because not all attributes that are possible are being added here, it
> should be trivial to add more as needed, right?
> 
> I'm really tired of seeing all of the various out-of-tree forks of this
> driver, it's about time that someone works to get those features merged,
> right?

Indeed, it seems someone has already done similar work before. Let me drop
my patches and dive into that, although I have to clean up all the mess once
again. :(

Thanks,

> 
> thanks,
> 
> greg k-h


Re: [PATCH v3 9/9] ufs: sysfs: attributes

2017-12-28 Thread Jaegeuk Kim
On 12/28, Stanislav Nijnikov wrote:
> This patch introduces a sysfs group entry for the UFS attributes. The
> group adds "attributes" folder under the UFS driver sysfs entry
> (/sys/bus/platform/drivers/ufshcd/*). The attributes are shown
> as hexadecimal numbers. The full information about the attributes could
> be found at UFS specifications 2.1.
> 
> Signed-off-by: Stanislav Nijnikov 
> ---
>  Documentation/ABI/testing/sysfs-driver-ufs | 155 
> +++--
>  drivers/scsi/ufs/ufs-sysfs.c   |  89 +
>  drivers/scsi/ufs/ufs-sysfs.h   |   1 +
>  drivers/scsi/ufs/ufs.h |  27 -
>  drivers/scsi/ufs/ufshcd.c  |   5 +-
>  drivers/scsi/ufs/ufshcd.h  |   2 +
>  6 files changed, 265 insertions(+), 14 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs 
> b/Documentation/ABI/testing/sysfs-driver-ufs
> index 90f8574..f2c3679 100644
> --- a/Documentation/ABI/testing/sysfs-driver-ufs
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> @@ -601,14 +601,14 @@ Description:This file shows the granularity of the 
> LUN. This is one of
>  
>  
>  What:/sys/bus/platform/drivers/ufshcd/*/flags/device_init
> -Date:August 2017
> +Date:December 2017

Must be fixed in the original patch.

Thanks,

>  Contact: Stanislav Nijnikov 
>  Description: This file shows the device init status. The full information
>   about the flag could be found at UFS specifications 2.1.
>   The file is read only.
>  
>  What:/sys/bus/platform/drivers/ufshcd/*/flags/permanent_wpe
> -Date:August 2017
> +Date:December 2017
>  Contact: Stanislav Nijnikov 
>  Description: This file shows whether permanent write protection is enabled.
>   The full information about the flag could be found at
> @@ -616,7 +616,7 @@ Description:  This file shows whether permanent write 
> protection is enabled.
>   The file is read only.
>  
>  What:/sys/bus/platform/drivers/ufshcd/*/flags/power_on_wpe
> -Date:August 2017
> +Date:December 2017
>  Contact: Stanislav Nijnikov 
>  Description: This file shows whether write protection is enabled on all
>   logical units configured as power on write protected. The
> @@ -625,7 +625,7 @@ Description:  This file shows whether write 
> protection is enabled on all
>   The file is read only.
>  
>  What:/sys/bus/platform/drivers/ufshcd/*/flags/bkops_enable
> -Date:August 2017
> +Date:December 2017
>  Contact: Stanislav Nijnikov 
>  Description: This file shows whether the device background operations are
>   enabled. The full information about the flag could be
> @@ -633,7 +633,7 @@ Description:  This file shows whether the device 
> background operations are
>   The file is read only.
>  
>  What:
> /sys/bus/platform/drivers/ufshcd/*/flags/life_span_mode_enable
> -Date:August 2017
> +Date:December 2017
>  Contact: Stanislav Nijnikov 
>  Description: This file shows whether the device life span mode is enabled.
>   The full information about the flag could be found at
> @@ -641,7 +641,7 @@ Description:  This file shows whether the device life 
> span mode is enabled.
>   The file is read only.
>  
>  What:
> /sys/bus/platform/drivers/ufshcd/*/flags/phy_resource_removal
> -Date:August 2017
> +Date:December 2017
>  Contact: Stanislav Nijnikov 
>  Description: This file shows whether physical resource removal is enable.
>   The full information about the flag could be found at
> @@ -649,7 +649,7 @@ Description:  This file shows whether physical 
> resource removal is enable.
>   The file is read only.
>  
>  What:/sys/bus/platform/drivers/ufshcd/*/flags/busy_rtc
> -Date:August 2017
> +Date:December 2017
>  Contact: Stanislav Nijnikov 
>  Description: This file shows whether the device is executing internal
>   operation related to real time clock. The full information
> @@ -657,9 +657,148 @@ Description:This file shows whether the device is 
> executing internal
>   The file is read only.
>  
>  What:
> /sys/bus/platform/drivers/ufshcd/*/flags/disable_fw_update
> -Date:August 2017
> +Date:December 2017
>  Contact: Stanislav Nijnikov 
>  Description: This file 

Re: [PATCH v3 4/9] ufs: sysfs: health descriptor

2017-12-28 Thread Jaegeuk Kim
On 12/28, Stanislav Nijnikov wrote:
> This patch introduces a sysfs group entry for the UFS health descriptor
> parameters. The group adds "health_descriptor" folder under the UFS driver
> sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown
> as hexadecimal numbers. The full information about the parameters could be
> found at UFS specifications 2.1.
> 
> Signed-off-by: Stanislav Nijnikov 

It needs to remove the above SOB.

> 
> Reviewed-by: Greg Kroah-Hartman 

Reviewed-by: Jaegeuk Kim 

> Signed-off-by: Stanislav Nijnikov 
> ---
>  Documentation/ABI/testing/sysfs-driver-ufs | 28 
>  drivers/scsi/ufs/ufs-sysfs.c   | 20 
>  drivers/scsi/ufs/ufs.h | 11 +++
>  drivers/scsi/ufs/ufshcd.c  |  8 
>  drivers/scsi/ufs/ufshcd.h  |  1 +
>  5 files changed, 68 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs 
> b/Documentation/ABI/testing/sysfs-driver-ufs
> index 55134d3..6ba0f4d 100644
> --- a/Documentation/ABI/testing/sysfs-driver-ufs
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> @@ -413,3 +413,31 @@ Description: This file shows the memory capacity 
> adjustment factor for
>   descriptor parameters. The full information about the
>   descriptor could be found at UFS specifications 2.1.
>   The file is read only.
> +
> +
> +What:
> /sys/bus/platform/drivers/ufshcd/*/health_descriptor/eol_info
> +Date:December 2017
> +Contact: Stanislav Nijnikov 
> +Description: This file shows preend of life information. This is one
> + of the UFS health descriptor parameters. The full
> + information about the descriptor could be found at
> + UFS specifications 2.1.
> + The file is read only.
> +
> +What:
> /sys/bus/platform/drivers/ufshcd/*/health_descriptor/life_time_estimation_a
> +Date:December 2017
> +Contact: Stanislav Nijnikov 
> +Description: This file shows indication of the device life time
> + (method a). This is one of the UFS health descriptor
> + parameters. The full information about the descriptor
> + could be found at UFS specifications 2.1.
> + The file is read only.
> +
> +What:
> /sys/bus/platform/drivers/ufshcd/*/health_descriptor/life_time_estimation_b
> +Date:December 2017
> +Contact: Stanislav Nijnikov 
> +Description: This file shows indication of the device life time
> + (method b). This is one of the UFS health descriptor
> + parameters. The full information about the descriptor
> + could be found at UFS specifications 2.1.
> + The file is read only.
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
> index e439e92..ce6d27e 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -248,10 +248,30 @@ static const struct attribute_group 
> ufs_sysfs_geometry_descriptor_group = {
>   .attrs = ufs_sysfs_geometry_descriptor,
>  };
>  
> +#define UFS_HEALTH_DESC_PARAM(_name, _uname, _size) \
> + UFS_DESC_PARAM(_name, _uname, HEALTH, _size)
> +
> +UFS_HEALTH_DESC_PARAM(eol_info, EOL_INFO, BYTE);
> +UFS_HEALTH_DESC_PARAM(life_time_estimation_a, LIFE_TIME_EST_A, BYTE);
> +UFS_HEALTH_DESC_PARAM(life_time_estimation_b, LIFE_TIME_EST_B, BYTE);
> +
> +static struct attribute *ufs_sysfs_health_descriptor[] = {
> + _attr_eol_info.attr,
> + _attr_life_time_estimation_a.attr,
> + _attr_life_time_estimation_b.attr,
> + NULL,
> +};
> +
> +static const struct attribute_group ufs_sysfs_health_descriptor_group = {
> + .name = "health_descriptor",
> + .attrs = ufs_sysfs_health_descriptor,
> +};
> +
>  static const struct attribute_group *ufs_sysfs_groups[] = {
>   _sysfs_device_descriptor_group,
>   _sysfs_interconnect_descriptor_group,
>   _sysfs_geometry_descriptor_group,
> + _sysfs_health_descriptor_group,
>   NULL,
>  };
>  
> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
> index 04d41c8..6bfeedb 100644
> --- a/drivers/scsi/ufs/ufs.h
> +++ b/drivers/scsi/ufs/ufs.h
> @@ -154,6 +154,7 @@ enum desc_idn {
>   QUERY_DESC_IDN_RFU_1= 0x6,
>   QUERY_DESC_IDN_GEOMETRY = 0x7,
>   QUERY_DESC_IDN_POWER= 0x8,
> + QUERY_DESC_IDN_HEALTH   = 0x9,
>   QUERY_DESC_IDN_MAX,
>  };
>  
> @@ -169,6 +170,7 @@ enum ufs_desc_def_size {
>   QUERY_DESC_INTERCONNECT_DEF_SIZE= 0x06,
>   QUERY_DESC_GEOMETRY_DEF_SIZE= 0x44,
>   QUERY_DESC_POWER_DEF_SIZE   = 0x62,

Re: [PATCH v3 1/9] ufs: sysfs: device descriptor

2017-12-28 Thread Jaegeuk Kim
On 12/28, Stanislav Nijnikov wrote:
> This patch introduces a sysfs group entry for the UFS device descriptor
> parameters. The group adds "device_descriptor" folder under the UFS driver
> sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown
> as hexadecimal numbers. The full information about the parameters could be
> found at UFS specifications 2.1.
> 
> Signed-off-by: Stanislav Nijnikov 
> ---
>  Documentation/ABI/testing/sysfs-driver-ufs | 223 
> +
>  drivers/scsi/ufs/Makefile  |   3 +-
>  drivers/scsi/ufs/ufs-sysfs.c   | 170 ++
>  drivers/scsi/ufs/ufs-sysfs.h   |  25 
>  drivers/scsi/ufs/ufs.h |   8 ++
>  drivers/scsi/ufs/ufshcd.c  |  12 +-
>  drivers/scsi/ufs/ufshcd.h  |   4 +
>  7 files changed, 439 insertions(+), 6 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-driver-ufs
>  create mode 100644 drivers/scsi/ufs/ufs-sysfs.c
>  create mode 100644 drivers/scsi/ufs/ufs-sysfs.h
> 
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs 
> b/Documentation/ABI/testing/sysfs-driver-ufs
> new file mode 100644
> index 000..17cc4aa
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs

[snip]

> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
> index 9310c6c..918f579 100644
> --- a/drivers/scsi/ufs/Makefile
> +++ b/drivers/scsi/ufs/Makefile
> @@ -3,6 +3,7 @@
>  obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o 
> tc-dwc-g210.o
>  obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o 
> tc-dwc-g210.o
>  obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
> -obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
> +obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o
> +ufshcd-core-objs := ufshcd.o ufs-sysfs.o

Why not just adding ufs-sysfs.o in the existing configuration?

>  obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
>  obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
> new file mode 100644
> index 000..1c685f3
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -0,0 +1,170 @@
> +/*
> +* UFS Device Management sysfs
> +*
> +* Copyright (C) 2017 Western Digital Corporation
> +*
> +* This program is free software; you can redistribute it and/or
> +* modify it under the terms of the GNU General Public License version
> +* 2 as published by the Free Software Foundation.
> +*
> +* This program is distributed in the hope that it will be useful, but
> +* WITHOUT ANY WARRANTY; without even the implied warranty of
> +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +* General Public License for more details.
> +*
> +*/
> +
> +#include 
> +#include 
> +
> +#include "ufs.h"
> +#include "ufs-sysfs.h"
> +/* collision between the device descriptor parameter and the definition */
> +#undef DEVICE_CLASS

Does this make sense? How about attaching "_" for all the macro like
_DEVICE_CLASS below?

> +
> +enum ufs_desc_param_size {
> + UFS_PARAM_BYTE_SIZE = 1,
> + UFS_PARAM_WORD_SIZE = 2,
> + UFS_PARAM_DWORD_SIZE= 4,
> + UFS_PARAM_QWORD_SIZE= 8,
> +};
> +
> +static inline ssize_t ufs_sysfs_read_desc_param(
> + struct ufs_hba *hba, u8 desc_idn, u8 index, char *buf, u8 off,
> + enum ufs_desc_param_size param_size)
> +{
> + int desc_len;
> + int ret;
> + u8 *desc_buf;
> +
> + if (ufshcd_map_desc_id_to_length(hba, desc_idn, _len) ||
> + off >= desc_len)
> + return -EINVAL;
> + desc_buf = kzalloc(desc_len, GFP_ATOMIC);
> + if (!desc_buf)
> + return -ENOMEM;
> + ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
> + desc_idn, index, 0, desc_buf, _len);
> + if (ret)

Should free desc_buf here.

> + return -EINVAL;
> + switch (param_size) {
> + case UFS_PARAM_BYTE_SIZE:
> + ret = sprintf(buf, "0x%02X\n", desc_buf[off]);
> + break;
> + case UFS_PARAM_WORD_SIZE:
> + ret = sprintf(buf, "0x%04X\n",
> + be16_to_cpu(*((u16 *)(desc_buf + off;
> + break;
> + case UFS_PARAM_DWORD_SIZE:
> + ret = sprintf(buf, "0x%08X\n",
> + be32_to_cpu(*((u32 *)(desc_buf + off;
> + break;
> + case UFS_PARAM_QWORD_SIZE:
> + ret = sprintf(buf, "0x%016llX\n",
> + be64_to_cpu(*((u64 *)(desc_buf + off;
> + break;
> + }
> + kfree(desc_buf);
> +
> + return ret;
> +}
> +
> +#define ufs_sysfs_desc_param_show(_name, _puname, _duname, _size)
>  \
> +static ssize_t _name##_show(struct device *dev,  
>  \
> + struct device_attribute *attr, char *buf) \
> +{ 

[PATCH v3 1/9] ufs: sysfs: device descriptor

2017-12-28 Thread Stanislav Nijnikov
This patch introduces a sysfs group entry for the UFS device descriptor
parameters. The group adds "device_descriptor" folder under the UFS driver
sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown
as hexadecimal numbers. The full information about the parameters could be
found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov 
---
 Documentation/ABI/testing/sysfs-driver-ufs | 223 +
 drivers/scsi/ufs/Makefile  |   3 +-
 drivers/scsi/ufs/ufs-sysfs.c   | 170 ++
 drivers/scsi/ufs/ufs-sysfs.h   |  25 
 drivers/scsi/ufs/ufs.h |   8 ++
 drivers/scsi/ufs/ufshcd.c  |  12 +-
 drivers/scsi/ufs/ufshcd.h  |   4 +
 7 files changed, 439 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-ufs
 create mode 100644 drivers/scsi/ufs/ufs-sysfs.c
 create mode 100644 drivers/scsi/ufs/ufs-sysfs.h

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs 
b/Documentation/ABI/testing/sysfs-driver-ufs
new file mode 100644
index 000..17cc4aa
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -0,0 +1,223 @@
+What:  /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_type
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the device type. This is one of the UFS
+   device descriptor parameters. The full information about
+   the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_class
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the device class. This is one of the UFS
+   device descriptor parameters. The full information about
+   the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_sub_class
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the UFS storage subclass. This is one of
+   the UFS device descriptor parameters. The full information
+   about the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/bus/platform/drivers/ufshcd/*/device_descriptor/protocol
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the protocol supported by an UFS device.
+   This is one of the UFS device descriptor parameters.
+   The full information about the descriptor could be found
+   at UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/device_descriptor/number_of_luns
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows number of logical units. This is one of
+   the UFS device descriptor parameters. The full information
+   about the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/device_descriptor/number_of_wluns
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows number of well known logical units.
+   This is one of the UFS device descriptor parameters.
+   The full information about the descriptor could be found
+   at UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/bus/platform/drivers/ufshcd/*/device_descriptor/boot_enable
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows value that indicates whether the device is
+   enabled for boot. This is one of the UFS device descriptor
+   parameters. The full information about the descriptor could
+   be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/device_descriptor/descriptor_access_enable
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows value that indicates whether the device
+   descriptor could be read after partial initialization phase
+   of the boot sequence. This is one of the UFS device descriptor
+   parameters. The full information about the descriptor could
+   be found at UFS 

[PATCH v3 3/9] ufs: sysfs: geometry descriptor

2017-12-28 Thread Stanislav Nijnikov
This patch introduces a sysfs group entry for the UFS geometry descriptor
parameters. The group adds "geometry_descriptor" folder under the UFS
driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters
are shown as hexadecimal numbers. The full information about the parameters
could be found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov 

Reviewed-by: Greg Kroah-Hartman 
Signed-off-by: Stanislav Nijnikov 
---
 Documentation/ABI/testing/sysfs-driver-ufs | 173 +
 drivers/scsi/ufs/ufs-sysfs.c   |  84 ++
 drivers/scsi/ufs/ufs.h |  36 ++
 3 files changed, 293 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs 
b/Documentation/ABI/testing/sysfs-driver-ufs
index f982e46..55134d3 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -240,3 +240,176 @@ Description:  This file shows the MIPI M-PHY version 
number in BCD format.
The full information about the descriptor could be found at
UFS specifications 2.1.
The file is read only.
+
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/raw_device_capacity
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the total memory quantity available to
+   the user to configure the device logical units. This is one
+   of the UFS geometry descriptor parameters. The full
+   information about the descriptor could be found at
+   UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_number_of_luns
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the maximum number of logical units
+   supported by the UFS device. This is one of the UFS
+   geometry descriptor parameters. The full information about
+   the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/segment_size
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the segment size. This is one of the UFS
+   geometry descriptor parameters. The full information about
+   the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/allocation_unit_size
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the allocation unit size. This is one of
+   the UFS geometry descriptor parameters. The full information
+   about the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/min_addressable_block_size
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the minimum addressable block size. This
+   is one of the UFS geometry descriptor parameters. The full
+   information about the descriptor could be found at UFS
+   specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/optimal_read_block_size
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the optimal read block size. This is one
+   of the UFS geometry descriptor parameters. The full
+   information about the descriptor could be found at UFS
+   specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/optimal_write_block_size
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the optimal write block size. This is one
+   of the UFS geometry descriptor parameters. The full
+   information about the descriptor could be found at UFS
+   specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_in_buffer_size
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the maximum data-in buffer size. This
+   is one of the UFS geometry descriptor parameters. The full
+ 

[PATCH v3 4/9] ufs: sysfs: health descriptor

2017-12-28 Thread Stanislav Nijnikov
This patch introduces a sysfs group entry for the UFS health descriptor
parameters. The group adds "health_descriptor" folder under the UFS driver
sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown
as hexadecimal numbers. The full information about the parameters could be
found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov 

Reviewed-by: Greg Kroah-Hartman 
Signed-off-by: Stanislav Nijnikov 
---
 Documentation/ABI/testing/sysfs-driver-ufs | 28 
 drivers/scsi/ufs/ufs-sysfs.c   | 20 
 drivers/scsi/ufs/ufs.h | 11 +++
 drivers/scsi/ufs/ufshcd.c  |  8 
 drivers/scsi/ufs/ufshcd.h  |  1 +
 5 files changed, 68 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs 
b/Documentation/ABI/testing/sysfs-driver-ufs
index 55134d3..6ba0f4d 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -413,3 +413,31 @@ Description:   This file shows the memory capacity 
adjustment factor for
descriptor parameters. The full information about the
descriptor could be found at UFS specifications 2.1.
The file is read only.
+
+
+What:  /sys/bus/platform/drivers/ufshcd/*/health_descriptor/eol_info
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows preend of life information. This is one
+   of the UFS health descriptor parameters. The full
+   information about the descriptor could be found at
+   UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/health_descriptor/life_time_estimation_a
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows indication of the device life time
+   (method a). This is one of the UFS health descriptor
+   parameters. The full information about the descriptor
+   could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/health_descriptor/life_time_estimation_b
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows indication of the device life time
+   (method b). This is one of the UFS health descriptor
+   parameters. The full information about the descriptor
+   could be found at UFS specifications 2.1.
+   The file is read only.
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index e439e92..ce6d27e 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -248,10 +248,30 @@ static const struct attribute_group 
ufs_sysfs_geometry_descriptor_group = {
.attrs = ufs_sysfs_geometry_descriptor,
 };
 
+#define UFS_HEALTH_DESC_PARAM(_name, _uname, _size) \
+   UFS_DESC_PARAM(_name, _uname, HEALTH, _size)
+
+UFS_HEALTH_DESC_PARAM(eol_info, EOL_INFO, BYTE);
+UFS_HEALTH_DESC_PARAM(life_time_estimation_a, LIFE_TIME_EST_A, BYTE);
+UFS_HEALTH_DESC_PARAM(life_time_estimation_b, LIFE_TIME_EST_B, BYTE);
+
+static struct attribute *ufs_sysfs_health_descriptor[] = {
+   _attr_eol_info.attr,
+   _attr_life_time_estimation_a.attr,
+   _attr_life_time_estimation_b.attr,
+   NULL,
+};
+
+static const struct attribute_group ufs_sysfs_health_descriptor_group = {
+   .name = "health_descriptor",
+   .attrs = ufs_sysfs_health_descriptor,
+};
+
 static const struct attribute_group *ufs_sysfs_groups[] = {
_sysfs_device_descriptor_group,
_sysfs_interconnect_descriptor_group,
_sysfs_geometry_descriptor_group,
+   _sysfs_health_descriptor_group,
NULL,
 };
 
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 04d41c8..6bfeedb 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -154,6 +154,7 @@ enum desc_idn {
QUERY_DESC_IDN_RFU_1= 0x6,
QUERY_DESC_IDN_GEOMETRY = 0x7,
QUERY_DESC_IDN_POWER= 0x8,
+   QUERY_DESC_IDN_HEALTH   = 0x9,
QUERY_DESC_IDN_MAX,
 };
 
@@ -169,6 +170,7 @@ enum ufs_desc_def_size {
QUERY_DESC_INTERCONNECT_DEF_SIZE= 0x06,
QUERY_DESC_GEOMETRY_DEF_SIZE= 0x44,
QUERY_DESC_POWER_DEF_SIZE   = 0x62,
+   QUERY_DESC_HEALTH_DEF_SIZE  = 0x25,
 };
 
 /* Unit descriptor parameters offsets in bytes*/
@@ -274,6 +276,15 @@ enum geometry_desc_param {
GEOMETRY_DESC_PARAM_OPT_LOG_BLK_SIZE= 0x44,
 };
 
+/* Health descriptor parameters offsets in bytes*/
+enum 

[PATCH v3 7/9] ufs: sysfs: unit descriptor

2017-12-28 Thread Stanislav Nijnikov
This patch introduces a sysfs group entry for the UFS unit descriptor
parameters. The group adds "unit_descriptor" folder under the corresponding
SCSI device sysfs entry (/sys/class/scsi_device/*/device/). The parameters
are shown as hexadecimal numbers. The full information about the parameters
could be found at UFS specifications 2.1.
In addition the patch presents an additional field in the
scsi_host_template structure - struct attribute_group **sdev_group.
This field allows to define groups of attributes. It will provide an
ability to use binary attributes in addition to device attributes and
to group them under subfolders if necessary.

Signed-off-by: Stanislav Nijnikov 

Reviewed-by: Greg Kroah-Hartman 
Signed-off-by: Stanislav Nijnikov 
---
 Documentation/ABI/testing/sysfs-driver-ufs | 108 +
 drivers/scsi/scsi_sysfs.c  |  14 
 drivers/scsi/ufs/ufs-sysfs.c   |  57 +++
 drivers/scsi/ufs/ufs-sysfs.h   |   3 +
 drivers/scsi/ufs/ufs.h |  11 +++
 drivers/scsi/ufs/ufshcd.c  |  23 ++
 drivers/scsi/ufs/ufshcd.h  |  15 
 include/scsi/scsi_host.h   |   6 ++
 8 files changed, 221 insertions(+), 16 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs 
b/Documentation/ABI/testing/sysfs-driver-ufs
index ff292127..e5f66e3 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -490,3 +490,111 @@ Description:  This file contains a product revision 
string. The full
information about the descriptor could be found at
UFS specifications 2.1.
The file is read only.
+
+
+What:  /sys/class/scsi_device/*/device/unit_descriptor/boot_lun_id
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows boot LUN information. This is one of
+   the UFS unit descriptor parameters. The full information
+   about the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/class/scsi_device/*/device/unit_descriptor/lun_write_protect
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows LUN write protection status. This is one of
+   the UFS unit descriptor parameters. The full information
+   about the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/class/scsi_device/*/device/unit_descriptor/lun_queue_depth
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows LUN queue depth. This is one of the UFS
+   unit descriptor parameters. The full information about
+   the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/class/scsi_device/*/device/unit_descriptor/psa_sensitive
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows PSA sensitivity. This is one of the UFS
+   unit descriptor parameters. The full information about
+   the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/class/scsi_device/*/device/unit_descriptor/lun_memory_type
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows LUN memory type. This is one of the UFS
+   unit descriptor parameters. The full information about
+   the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/class/scsi_device/*/device/unit_descriptor/data_reliability
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file defines the device behavior when a power failure
+   occurs during a write operation. This is one of the UFS
+   unit descriptor parameters. The full information about
+   the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/class/scsi_device/*/device/unit_descriptor/logical_block_size
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the size of addressable logical blocks
+   (calculated as an exponent with base 2). This is one of
+   the UFS unit descriptor parameters. The full information about
+   the descriptor could be found at UFS specifications 2.1.
+

[PATCH v3 6/9] ufs: sysfs: string descriptors

2017-12-28 Thread Stanislav Nijnikov
This patch introduces a sysfs group entry for the UFS string descriptors.
The group adds "string_descriptors" folder under the UFS driver
sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The folder will contain
5 files that will show string values defined by the UFS spec:
a manufacturer name, a product name, an OEM id, a serial number and a
product revision.  The full information about the string descriptors
could be found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov 

Reviewed-by: Greg Kroah-Hartman 
Signed-off-by: Stanislav Nijnikov 
---
 Documentation/ABI/testing/sysfs-driver-ufs | 39 
 drivers/scsi/ufs/ufs-sysfs.c   | 58 ++
 drivers/scsi/ufs/ufshcd.c  |  4 +--
 drivers/scsi/ufs/ufshcd.h  |  3 ++
 4 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs 
b/Documentation/ABI/testing/sysfs-driver-ufs
index 48cd49c..ff292127 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -451,3 +451,42 @@ Description:   This file shows maximum VCC, VCCQ and 
VCCQ2 value for
power descriptor parameters. The full information about
the descriptor could be found at UFS specifications 2.1.
The file is read only.
+
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/string_descriptors/manufacturer_name
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file contains a device manufactureer name string.
+   The full information about the descriptor could be found at
+   UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/string_descriptors/product_name
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file contains a product name string. The full information
+   about the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/bus/platform/drivers/ufshcd/*/string_descriptors/oem_id
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file contains a OEM ID string. The full information
+   about the descriptor could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/string_descriptors/serial_number
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file contains a device serial number string. The full
+   information about the descriptor could be found at
+   UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/string_descriptors/product_revision
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file contains a product revision string. The full
+   information about the descriptor could be found at
+   UFS specifications 2.1.
+   The file is read only.
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 0db4bed..f3ef281 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -387,12 +387,70 @@ static const struct attribute_group 
ufs_sysfs_power_descriptor_group = {
.attrs = ufs_sysfs_power_descriptor,
 };
 
+#define ufs_sysfs_string_descriptor_show(_name, _pname)   \
+static ssize_t _name##_show(struct device *dev,   \
+   struct device_attribute *attr, char *buf) \
+{ \
+   u8 index; \
+   struct ufs_hba *hba = dev_get_drvdata(dev);   \
+   int ret;  \
+   int desc_len = QUERY_DESC_MAX_SIZE;   \
+   u8 *desc_buf; \
+   desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC);  \
+   if (!desc_buf)\
+   return -ENOMEM;   \
+   ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC, \
+   QUERY_DESC_IDN_DEVICE, 0, 0, desc_buf, _len);\
+   if (ret) {\
+   ret = -EINVAL;

[PATCH v3 8/9] ufs: sysfs: flags

2017-12-28 Thread Stanislav Nijnikov
This patch introduces a sysfs group entry for the UFS flags. The group adds
"flags" folder under the UFS driver sysfs entry
(/sys/bus/platform/drivers/ufshcd/*). The flags are shown as boolean value
("true" or "false"). The full information about the UFS flags could be
found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov 
---
 Documentation/ABI/testing/sysfs-driver-ufs | 65 ++
 drivers/scsi/ufs/ufs-sysfs.c   | 42 +++
 drivers/scsi/ufs/ufs.h | 14 +--
 3 files changed, 118 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs 
b/Documentation/ABI/testing/sysfs-driver-ufs
index e5f66e3..90f8574 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -598,3 +598,68 @@ Description:   This file shows the granularity of the 
LUN. This is one of
the UFS unit descriptor parameters. The full information
about the descriptor could be found at UFS specifications 2.1.
The file is read only.
+
+
+What:  /sys/bus/platform/drivers/ufshcd/*/flags/device_init
+Date:  August 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the device init status. The full information
+   about the flag could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/bus/platform/drivers/ufshcd/*/flags/permanent_wpe
+Date:  August 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows whether permanent write protection is enabled.
+   The full information about the flag could be found at
+   UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/bus/platform/drivers/ufshcd/*/flags/power_on_wpe
+Date:  August 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows whether write protection is enabled on all
+   logical units configured as power on write protected. The
+   full information about the flag could be found at
+   UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/bus/platform/drivers/ufshcd/*/flags/bkops_enable
+Date:  August 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows whether the device background operations are
+   enabled. The full information about the flag could be
+   found at UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/bus/platform/drivers/ufshcd/*/flags/life_span_mode_enable
+Date:  August 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows whether the device life span mode is enabled.
+   The full information about the flag could be found at
+   UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/bus/platform/drivers/ufshcd/*/flags/phy_resource_removal
+Date:  August 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows whether physical resource removal is enable.
+   The full information about the flag could be found at
+   UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/bus/platform/drivers/ufshcd/*/flags/busy_rtc
+Date:  August 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows whether the device is executing internal
+   operation related to real time clock. The full information
+   about the flag could be found at UFS specifications 2.1.
+   The file is read only.
+
+What:  /sys/bus/platform/drivers/ufshcd/*/flags/disable_fw_update
+Date:  August 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows whether the device FW update is permanently
+   disabled. The full information about the flag could be found
+   at UFS specifications 2.1.
+   The file is read only.
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 3d08abf..2095124 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -443,6 +443,47 @@ static const struct attribute_group 
ufs_sysfs_string_descriptors_group = {
.attrs = ufs_sysfs_string_descriptors,
 };
 
+#define ufs_sysfs_flag_show(_name, _uname)\
+static ssize_t _name##_show(struct device *dev,   \
+   struct device_attribute *attr, char *buf) \
+{   

[PATCH v3 2/9] ufs: sysfs: interconnect descriptor

2017-12-28 Thread Stanislav Nijnikov
This patch introduces a sysfs group entry for the UFS interconnect
descriptor parameters. The group adds "interconnect_descriptor" folder
under the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*).
The parameters are shown as hexadecimal numbers. The full information
about the parameters could be found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov 

Reviewed-by: Greg Kroah-Hartman 
Signed-off-by: Stanislav Nijnikov 
---
 Documentation/ABI/testing/sysfs-driver-ufs | 19 +++
 drivers/scsi/ufs/ufs-sysfs.c   | 18 ++
 drivers/scsi/ufs/ufs.h |  8 
 3 files changed, 45 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs 
b/Documentation/ABI/testing/sysfs-driver-ufs
index 17cc4aa..f982e46 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -221,3 +221,22 @@ Description:   This file shows the command maximum 
timeout for a change
parameters. The full information about the descriptor could
be found at UFS specifications 2.1.
The file is read only.
+
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/interconnect_descriptor/unipro_version
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the MIPI UniPro version number in BCD format.
+   This is one of the UFS interconnect descriptor parameters.
+   The full information about the descriptor could be found at
+   UFS specifications 2.1.
+   The file is read only.
+
+What:  
/sys/bus/platform/drivers/ufshcd/*/interconnect_descriptor/mphy_version
+Date:  December 2017
+Contact:   Stanislav Nijnikov 
+Description:   This file shows the MIPI M-PHY version number in BCD format.
+   This is one of the UFS interconnect descriptor parameters.
+   The full information about the descriptor could be found at
+   UFS specifications 2.1.
+   The file is read only.
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 1c685f3..9f7627e 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -148,8 +148,26 @@ static const struct attribute_group 
ufs_sysfs_device_descriptor_group = {
.attrs = ufs_sysfs_device_descriptor,
 };
 
+#define UFS_INTERCONNECT_DESC_PARAM(_name, _uname, _size) \
+   UFS_DESC_PARAM(_name, _uname, INTERCONNECT, _size)
+
+UFS_INTERCONNECT_DESC_PARAM(unipro_version, UNIPRO_VER, WORD);
+UFS_INTERCONNECT_DESC_PARAM(mphy_version, MPHY_VER, WORD);
+
+static struct attribute *ufs_sysfs_interconnect_descriptor[] = {
+   _attr_unipro_version.attr,
+   _attr_mphy_version.attr,
+   NULL,
+};
+
+static const struct attribute_group ufs_sysfs_interconnect_descriptor_group = {
+   .name = "interconnect_descriptor",
+   .attrs = ufs_sysfs_interconnect_descriptor,
+};
+
 static const struct attribute_group *ufs_sysfs_groups[] = {
_sysfs_device_descriptor_group,
+   _sysfs_interconnect_descriptor_group,
NULL,
 };
 
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 6ae1e08..773c049 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -230,6 +230,14 @@ enum device_desc_param {
DEVICE_DESC_PARAM_PRDCT_REV = 0x2A,
 };
 
+/* Interconnect descriptor parameters offsets in bytes*/
+enum interconnect_desc_param {
+   INTERCONNECT_DESC_PARAM_LEN = 0x0,
+   INTERCONNECT_DESC_PARAM_TYPE= 0x1,
+   INTERCONNECT_DESC_PARAM_UNIPRO_VER  = 0x2,
+   INTERCONNECT_DESC_PARAM_MPHY_VER= 0x4,
+};
+
 /*
  * Logical Unit Write Protect
  * 00h: LU not write protected
-- 
2.7.4



[PATCH v3 0/9] ufs: sysfs: read-only access to device descriptors, attributes and flags

2017-12-28 Thread Stanislav Nijnikov
This patch introduces sysfs entries that will provide read-only access to
device management data that could be received with UFS query requests.
User-space applications will be able to read UFS device descriptors,
flags and attributes. This will allow to get full UFS device configuration
and its status. The descriptors are provided as set of files representing
its parameters. The flags are using "true"/"false" representation of
their value. The attributes are shown as hexadecimal value. The
descriptors, attributes and flags are placed in separate subfolders under
the UFS device sysfs entry (/sys/bus/platform/drivers/ufshcd/*/). The
string descriptor subfolder contains five string descriptors defined by
UFS specification 2.1. The LUN specific descriptor and attribute are 
placed under corresponding SCSI device sysfs entries
(/sys/class/scsi_device/*/device/).
In addition the patch presents an additional field in the
scsi_host_template structure - struct attribute_group **sdev_group.
This field allows to define groups of attributes. It will provide an
ability to use binary attributes in addition to device attributes and
to group them under subfolders if necessary.

Changelog:
v2 -> v3
The Makefile is updated to make ufs-sysfs.c part of the ufshcd module.
The unnecessary EXPORT_SYMBOL were removed
Added a legal info header to the new files
The date in Documentation/ABI/testing/sysfs-driver-ufs was updated.

v1 -> v2
Provided additional description for the changes

Stanislav Nijnikov (9):
  ufs: sysfs: device descriptor
  ufs: sysfs: interconnect descriptor
  ufs: sysfs: geometry descriptor
  ufs: sysfs: health descriptor
  ufs: sysfs: power descriptor
  ufs: sysfs: string descriptors
  ufs: sysfs: unit descriptor
  ufs: sysfs: flags
  ufs: sysfs: attributes

 Documentation/ABI/testing/sysfs-driver-ufs | 804 +
 drivers/scsi/scsi_sysfs.c  |  14 +
 drivers/scsi/ufs/Makefile  |   3 +-
 drivers/scsi/ufs/ufs-sysfs.c   | 659 +++
 drivers/scsi/ufs/ufs-sysfs.h   |  29 ++
 drivers/scsi/ufs/ufs.h | 115 -
 drivers/scsi/ufs/ufshcd.c  |  52 +-
 drivers/scsi/ufs/ufshcd.h  |  25 +
 include/scsi/scsi_host.h   |   6 +
 9 files changed, 1674 insertions(+), 33 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-ufs
 create mode 100644 drivers/scsi/ufs/ufs-sysfs.c
 create mode 100644 drivers/scsi/ufs/ufs-sysfs.h

-- 
2.7.4



[PATCH v3 9/9] ufs: sysfs: attributes

2017-12-28 Thread Stanislav Nijnikov
This patch introduces a sysfs group entry for the UFS attributes. The
group adds "attributes" folder under the UFS driver sysfs entry
(/sys/bus/platform/drivers/ufshcd/*). The attributes are shown
as hexadecimal numbers. The full information about the attributes could
be found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov 
---
 Documentation/ABI/testing/sysfs-driver-ufs | 155 +++--
 drivers/scsi/ufs/ufs-sysfs.c   |  89 +
 drivers/scsi/ufs/ufs-sysfs.h   |   1 +
 drivers/scsi/ufs/ufs.h |  27 -
 drivers/scsi/ufs/ufshcd.c  |   5 +-
 drivers/scsi/ufs/ufshcd.h  |   2 +
 6 files changed, 265 insertions(+), 14 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs 
b/Documentation/ABI/testing/sysfs-driver-ufs
index 90f8574..f2c3679 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -601,14 +601,14 @@ Description:  This file shows the granularity of the 
LUN. This is one of
 
 
 What:  /sys/bus/platform/drivers/ufshcd/*/flags/device_init
-Date:  August 2017
+Date:  December 2017
 Contact:   Stanislav Nijnikov 
 Description:   This file shows the device init status. The full information
about the flag could be found at UFS specifications 2.1.
The file is read only.
 
 What:  /sys/bus/platform/drivers/ufshcd/*/flags/permanent_wpe
-Date:  August 2017
+Date:  December 2017
 Contact:   Stanislav Nijnikov 
 Description:   This file shows whether permanent write protection is enabled.
The full information about the flag could be found at
@@ -616,7 +616,7 @@ Description:This file shows whether permanent write 
protection is enabled.
The file is read only.
 
 What:  /sys/bus/platform/drivers/ufshcd/*/flags/power_on_wpe
-Date:  August 2017
+Date:  December 2017
 Contact:   Stanislav Nijnikov 
 Description:   This file shows whether write protection is enabled on all
logical units configured as power on write protected. The
@@ -625,7 +625,7 @@ Description:This file shows whether write 
protection is enabled on all
The file is read only.
 
 What:  /sys/bus/platform/drivers/ufshcd/*/flags/bkops_enable
-Date:  August 2017
+Date:  December 2017
 Contact:   Stanislav Nijnikov 
 Description:   This file shows whether the device background operations are
enabled. The full information about the flag could be
@@ -633,7 +633,7 @@ Description:This file shows whether the device 
background operations are
The file is read only.
 
 What:  /sys/bus/platform/drivers/ufshcd/*/flags/life_span_mode_enable
-Date:  August 2017
+Date:  December 2017
 Contact:   Stanislav Nijnikov 
 Description:   This file shows whether the device life span mode is enabled.
The full information about the flag could be found at
@@ -641,7 +641,7 @@ Description:This file shows whether the device life 
span mode is enabled.
The file is read only.
 
 What:  /sys/bus/platform/drivers/ufshcd/*/flags/phy_resource_removal
-Date:  August 2017
+Date:  December 2017
 Contact:   Stanislav Nijnikov 
 Description:   This file shows whether physical resource removal is enable.
The full information about the flag could be found at
@@ -649,7 +649,7 @@ Description:This file shows whether physical 
resource removal is enable.
The file is read only.
 
 What:  /sys/bus/platform/drivers/ufshcd/*/flags/busy_rtc
-Date:  August 2017
+Date:  December 2017
 Contact:   Stanislav Nijnikov 
 Description:   This file shows whether the device is executing internal
operation related to real time clock. The full information
@@ -657,9 +657,148 @@ Description:  This file shows whether the device is 
executing internal
The file is read only.
 
 What:  /sys/bus/platform/drivers/ufshcd/*/flags/disable_fw_update
-Date:  August 2017
+Date:  December 2017
 Contact:   Stanislav Nijnikov 
 Description:   This file shows whether the device FW update is permanently
disabled. The full information about the flag could be found
at UFS specifications 2.1.
The file is read only.
+
+
+What:  /sys/bus/platform/drivers/ufshcd/*/attributes/boot_lun_enabled
+Date:  December 2017
+Contact:   Stanislav Nijnikov 

[PATCH 2/2] scsi: hisi_sas: Change frame type for SET MAX commands

2017-12-28 Thread chenxiang
According to ATA protocol, SET MAX commands belong to different frame types.
So judge features field of SET MAX commands to decide which frame type they
belongs to.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  3 ++-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 20 ++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  2 +-
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  2 +-
 4 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index cc05029..4000de4 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -441,7 +441,8 @@ struct hisi_sas_slot_buf_table {
 extern void hisi_sas_init_add(struct hisi_hba *hisi_hba);
 extern int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost);
 extern void hisi_sas_free(struct hisi_hba *hisi_hba);
-extern u8 hisi_sas_get_ata_protocol(u8 cmd, int direction);
+extern u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis,
+   int direction);
 extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port);
 extern void hisi_sas_sata_done(struct sas_task *task,
struct hisi_sas_slot *slot);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 04e1172b..6792c1a 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -25,9 +25,9 @@ static int hisi_sas_debug_issue_ssp_tmf(struct domain_device 
*device,
 static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func 
func,
void *funcdata);
 
-u8 hisi_sas_get_ata_protocol(u8 cmd, int direction)
+u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
 {
-   switch (cmd) {
+   switch (fis->command) {
case ATA_CMD_FPDMA_WRITE:
case ATA_CMD_FPDMA_READ:
case ATA_CMD_FPDMA_RECV:
@@ -79,10 +79,26 @@ u8 hisi_sas_get_ata_protocol(u8 cmd, int direction)
case ATA_CMD_ZAC_MGMT_OUT:
return HISI_SAS_SATA_PROTOCOL_NONDATA;
default:
+   {
+   if (fis->command == ATA_CMD_SET_MAX) {
+   switch (fis->features) {
+   case ATA_SET_MAX_PASSWD:
+   case ATA_SET_MAX_LOCK:
+   return HISI_SAS_SATA_PROTOCOL_PIO;
+
+   case ATA_SET_MAX_PASSWD_DMA:
+   case ATA_SET_MAX_UNLOCK_DMA:
+   return HISI_SAS_SATA_PROTOCOL_DMA;
+
+   default:
+   return HISI_SAS_SATA_PROTOCOL_NONDATA;
+   }
+   }
if (direction == DMA_NONE)
return HISI_SAS_SATA_PROTOCOL_NONDATA;
return HISI_SAS_SATA_PROTOCOL_PIO;
}
+   }
 }
 EXPORT_SYMBOL_GPL(hisi_sas_get_ata_protocol);
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index b8fe08d..ebee2e4 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2539,7 +2539,7 @@ static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
dw1 |= 1 << CMD_HDR_RESET_OFF;
 
dw1 |= (hisi_sas_get_ata_protocol(
-   task->ata_task.fis.command, task->data_dir))
+   >ata_task.fis, task->data_dir))
<< CMD_HDR_FRAME_TYPE_OFF;
dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;
hdr->dw1 = cpu_to_le32(dw1);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 6a408d2..a1f1868 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -1047,7 +1047,7 @@ static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
dw1 |= 1 << CMD_HDR_RESET_OFF;
 
dw1 |= (hisi_sas_get_ata_protocol(
-   task->ata_task.fis.command, task->data_dir))
+   >ata_task.fis, task->data_dir))
<< CMD_HDR_FRAME_TYPE_OFF;
dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;
 
-- 
1.9.1



[PATCH 1/2] ata: enhance the definition of SET MAX feature field value

2017-12-28 Thread chenxiang
There are two other values for SET MAX feature field according to ata
protocol. So definite them.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 include/linux/ata.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/ata.h b/include/linux/ata.h
index c7a3538..40d150a 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -448,6 +448,8 @@ enum {
ATA_SET_MAX_LOCK= 0x02,
ATA_SET_MAX_UNLOCK  = 0x03,
ATA_SET_MAX_FREEZE_LOCK = 0x04,
+   ATA_SET_MAX_PASSWD_DMA  = 0x05,
+   ATA_SET_MAX_UNLOCK_DMA  = 0x06,
 
/* feature values for DEVICE CONFIGURATION OVERLAY */
ATA_DCO_RESTORE = 0xC0,
-- 
1.9.1



[PATCH 0/2] Change frame type for SET MAX commands

2017-12-28 Thread chenxiang
According to ATA protocol, there are two other values for SET MAX commands' 
feature field. So definite them. Also those SET MAX commands belong to 
different frame types,and judge feature field of SET MAX commands to decide
which frame type they belongs to.

chenxiang (2):
  ata: enhance the definition of SET MAX feature field value
  scsi: hisi_sas: Change frame type for SET MAX commands

 drivers/scsi/hisi_sas/hisi_sas.h   |  3 ++-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 20 ++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  2 +-
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  2 +-
 include/linux/ata.h|  2 ++
 5 files changed, 24 insertions(+), 5 deletions(-)

-- 
1.9.1