162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * zfcp device driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Debug traces for zfcp. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright IBM Corp. 2002, 2023 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define KMSG_COMPONENT "zfcp" 1162306a36Sopenharmony_ci#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/ctype.h> 1562306a36Sopenharmony_ci#include <linux/slab.h> 1662306a36Sopenharmony_ci#include <asm/debug.h> 1762306a36Sopenharmony_ci#include "zfcp_dbf.h" 1862306a36Sopenharmony_ci#include "zfcp_ext.h" 1962306a36Sopenharmony_ci#include "zfcp_fc.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic u32 dbfsize = 4; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cimodule_param(dbfsize, uint, 0400); 2462306a36Sopenharmony_ciMODULE_PARM_DESC(dbfsize, 2562306a36Sopenharmony_ci "number of pages for each debug feature area (default 4)"); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic u32 dbflevel = 3; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cimodule_param(dbflevel, uint, 0400); 3062306a36Sopenharmony_ciMODULE_PARM_DESC(dbflevel, 3162306a36Sopenharmony_ci "log level for each debug feature area " 3262306a36Sopenharmony_ci "(default 3, range 0..6)"); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic inline unsigned int zfcp_dbf_plen(unsigned int offset) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci return sizeof(struct zfcp_dbf_pay) + offset - ZFCP_DBF_PAY_MAX_REC; 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic inline 4062306a36Sopenharmony_civoid zfcp_dbf_pl_write(struct zfcp_dbf *dbf, void *data, u16 length, char *area, 4162306a36Sopenharmony_ci u64 req_id) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci struct zfcp_dbf_pay *pl = &dbf->pay_buf; 4462306a36Sopenharmony_ci u16 offset = 0, rec_length; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci spin_lock(&dbf->pay_lock); 4762306a36Sopenharmony_ci memset(pl, 0, sizeof(*pl)); 4862306a36Sopenharmony_ci pl->fsf_req_id = req_id; 4962306a36Sopenharmony_ci memcpy(pl->area, area, ZFCP_DBF_TAG_LEN); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci while (offset < length) { 5262306a36Sopenharmony_ci rec_length = min((u16) ZFCP_DBF_PAY_MAX_REC, 5362306a36Sopenharmony_ci (u16) (length - offset)); 5462306a36Sopenharmony_ci memcpy(pl->data, data + offset, rec_length); 5562306a36Sopenharmony_ci debug_event(dbf->pay, 1, pl, zfcp_dbf_plen(rec_length)); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci offset += rec_length; 5862306a36Sopenharmony_ci pl->counter++; 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci spin_unlock(&dbf->pay_lock); 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/** 6562306a36Sopenharmony_ci * zfcp_dbf_hba_fsf_res - trace event for fsf responses 6662306a36Sopenharmony_ci * @tag: tag indicating which kind of FSF response has been received 6762306a36Sopenharmony_ci * @level: trace level to be used for event 6862306a36Sopenharmony_ci * @req: request for which a response was received 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_civoid zfcp_dbf_hba_fsf_res(char *tag, int level, struct zfcp_fsf_req *req) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci struct zfcp_dbf *dbf = req->adapter->dbf; 7362306a36Sopenharmony_ci struct fsf_qtcb_prefix *q_pref = &req->qtcb->prefix; 7462306a36Sopenharmony_ci struct fsf_qtcb_header *q_head = &req->qtcb->header; 7562306a36Sopenharmony_ci struct zfcp_dbf_hba *rec = &dbf->hba_buf; 7662306a36Sopenharmony_ci unsigned long flags; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci spin_lock_irqsave(&dbf->hba_lock, flags); 7962306a36Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); 8262306a36Sopenharmony_ci rec->id = ZFCP_DBF_HBA_RES; 8362306a36Sopenharmony_ci rec->fsf_req_id = req->req_id; 8462306a36Sopenharmony_ci rec->fsf_req_status = req->status; 8562306a36Sopenharmony_ci rec->fsf_cmd = q_head->fsf_command; 8662306a36Sopenharmony_ci rec->fsf_seq_no = q_pref->req_seq_no; 8762306a36Sopenharmony_ci rec->u.res.req_issued = req->issued; 8862306a36Sopenharmony_ci rec->u.res.prot_status = q_pref->prot_status; 8962306a36Sopenharmony_ci rec->u.res.fsf_status = q_head->fsf_status; 9062306a36Sopenharmony_ci rec->u.res.port_handle = q_head->port_handle; 9162306a36Sopenharmony_ci rec->u.res.lun_handle = q_head->lun_handle; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci memcpy(rec->u.res.prot_status_qual, &q_pref->prot_status_qual, 9462306a36Sopenharmony_ci FSF_PROT_STATUS_QUAL_SIZE); 9562306a36Sopenharmony_ci memcpy(rec->u.res.fsf_status_qual, &q_head->fsf_status_qual, 9662306a36Sopenharmony_ci FSF_STATUS_QUALIFIER_SIZE); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci rec->pl_len = q_head->log_length; 9962306a36Sopenharmony_ci zfcp_dbf_pl_write(dbf, (char *)q_pref + q_head->log_start, 10062306a36Sopenharmony_ci rec->pl_len, "fsf_res", req->req_id); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci debug_event(dbf->hba, level, rec, sizeof(*rec)); 10362306a36Sopenharmony_ci spin_unlock_irqrestore(&dbf->hba_lock, flags); 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci/** 10762306a36Sopenharmony_ci * zfcp_dbf_hba_fsf_fces - trace event for fsf responses related to 10862306a36Sopenharmony_ci * FC Endpoint Security (FCES) 10962306a36Sopenharmony_ci * @tag: tag indicating which kind of FC Endpoint Security event has occurred 11062306a36Sopenharmony_ci * @req: request for which a response was received 11162306a36Sopenharmony_ci * @wwpn: remote port or ZFCP_DBF_INVALID_WWPN 11262306a36Sopenharmony_ci * @fc_security_old: old FC Endpoint Security of FCP device or connection 11362306a36Sopenharmony_ci * @fc_security_new: new FC Endpoint Security of FCP device or connection 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_civoid zfcp_dbf_hba_fsf_fces(char *tag, const struct zfcp_fsf_req *req, u64 wwpn, 11662306a36Sopenharmony_ci u32 fc_security_old, u32 fc_security_new) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci struct zfcp_dbf *dbf = req->adapter->dbf; 11962306a36Sopenharmony_ci struct fsf_qtcb_prefix *q_pref = &req->qtcb->prefix; 12062306a36Sopenharmony_ci struct fsf_qtcb_header *q_head = &req->qtcb->header; 12162306a36Sopenharmony_ci struct zfcp_dbf_hba *rec = &dbf->hba_buf; 12262306a36Sopenharmony_ci static int const level = 3; 12362306a36Sopenharmony_ci unsigned long flags; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci if (unlikely(!debug_level_enabled(dbf->hba, level))) 12662306a36Sopenharmony_ci return; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci spin_lock_irqsave(&dbf->hba_lock, flags); 12962306a36Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); 13262306a36Sopenharmony_ci rec->id = ZFCP_DBF_HBA_FCES; 13362306a36Sopenharmony_ci rec->fsf_req_id = req->req_id; 13462306a36Sopenharmony_ci rec->fsf_req_status = req->status; 13562306a36Sopenharmony_ci rec->fsf_cmd = q_head->fsf_command; 13662306a36Sopenharmony_ci rec->fsf_seq_no = q_pref->req_seq_no; 13762306a36Sopenharmony_ci rec->u.fces.req_issued = req->issued; 13862306a36Sopenharmony_ci rec->u.fces.fsf_status = q_head->fsf_status; 13962306a36Sopenharmony_ci rec->u.fces.port_handle = q_head->port_handle; 14062306a36Sopenharmony_ci rec->u.fces.wwpn = wwpn; 14162306a36Sopenharmony_ci rec->u.fces.fc_security_old = fc_security_old; 14262306a36Sopenharmony_ci rec->u.fces.fc_security_new = fc_security_new; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci debug_event(dbf->hba, level, rec, sizeof(*rec)); 14562306a36Sopenharmony_ci spin_unlock_irqrestore(&dbf->hba_lock, flags); 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/** 14962306a36Sopenharmony_ci * zfcp_dbf_hba_fsf_reqid - trace only the tag and a request ID 15062306a36Sopenharmony_ci * @tag: tag documenting the source 15162306a36Sopenharmony_ci * @level: trace level 15262306a36Sopenharmony_ci * @adapter: adapter instance the request ID belongs to 15362306a36Sopenharmony_ci * @req_id: the request ID to trace 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_civoid zfcp_dbf_hba_fsf_reqid(const char *const tag, const int level, 15662306a36Sopenharmony_ci struct zfcp_adapter *const adapter, 15762306a36Sopenharmony_ci const u64 req_id) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci struct zfcp_dbf *const dbf = adapter->dbf; 16062306a36Sopenharmony_ci struct zfcp_dbf_hba *const rec = &dbf->hba_buf; 16162306a36Sopenharmony_ci struct zfcp_dbf_hba_res *const res = &rec->u.res; 16262306a36Sopenharmony_ci unsigned long flags; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci if (unlikely(!debug_level_enabled(dbf->hba, level))) 16562306a36Sopenharmony_ci return; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci spin_lock_irqsave(&dbf->hba_lock, flags); 16862306a36Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci rec->id = ZFCP_DBF_HBA_RES; 17362306a36Sopenharmony_ci rec->fsf_req_id = req_id; 17462306a36Sopenharmony_ci rec->fsf_req_status = ~0u; 17562306a36Sopenharmony_ci rec->fsf_cmd = ~0u; 17662306a36Sopenharmony_ci rec->fsf_seq_no = ~0u; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci res->req_issued = ~0ull; 17962306a36Sopenharmony_ci res->prot_status = ~0u; 18062306a36Sopenharmony_ci memset(res->prot_status_qual, 0xff, sizeof(res->prot_status_qual)); 18162306a36Sopenharmony_ci res->fsf_status = ~0u; 18262306a36Sopenharmony_ci memset(res->fsf_status_qual, 0xff, sizeof(res->fsf_status_qual)); 18362306a36Sopenharmony_ci res->port_handle = ~0u; 18462306a36Sopenharmony_ci res->lun_handle = ~0u; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci debug_event(dbf->hba, level, rec, sizeof(*rec)); 18762306a36Sopenharmony_ci spin_unlock_irqrestore(&dbf->hba_lock, flags); 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci/** 19162306a36Sopenharmony_ci * zfcp_dbf_hba_fsf_uss - trace event for an unsolicited status buffer 19262306a36Sopenharmony_ci * @tag: tag indicating which kind of unsolicited status has been received 19362306a36Sopenharmony_ci * @req: request providing the unsolicited status 19462306a36Sopenharmony_ci */ 19562306a36Sopenharmony_civoid zfcp_dbf_hba_fsf_uss(char *tag, struct zfcp_fsf_req *req) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci struct zfcp_dbf *dbf = req->adapter->dbf; 19862306a36Sopenharmony_ci struct fsf_status_read_buffer *srb = req->data; 19962306a36Sopenharmony_ci struct zfcp_dbf_hba *rec = &dbf->hba_buf; 20062306a36Sopenharmony_ci static int const level = 2; 20162306a36Sopenharmony_ci unsigned long flags; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (unlikely(!debug_level_enabled(dbf->hba, level))) 20462306a36Sopenharmony_ci return; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci spin_lock_irqsave(&dbf->hba_lock, flags); 20762306a36Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); 21062306a36Sopenharmony_ci rec->id = ZFCP_DBF_HBA_USS; 21162306a36Sopenharmony_ci rec->fsf_req_id = req->req_id; 21262306a36Sopenharmony_ci rec->fsf_req_status = req->status; 21362306a36Sopenharmony_ci rec->fsf_cmd = FSF_QTCB_UNSOLICITED_STATUS; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci if (!srb) 21662306a36Sopenharmony_ci goto log; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci rec->u.uss.status_type = srb->status_type; 21962306a36Sopenharmony_ci rec->u.uss.status_subtype = srb->status_subtype; 22062306a36Sopenharmony_ci rec->u.uss.d_id = ntoh24(srb->d_id); 22162306a36Sopenharmony_ci rec->u.uss.lun = srb->fcp_lun; 22262306a36Sopenharmony_ci memcpy(&rec->u.uss.queue_designator, &srb->queue_designator, 22362306a36Sopenharmony_ci sizeof(rec->u.uss.queue_designator)); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* status read buffer payload length */ 22662306a36Sopenharmony_ci rec->pl_len = (!srb->length) ? 0 : srb->length - 22762306a36Sopenharmony_ci offsetof(struct fsf_status_read_buffer, payload); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci if (rec->pl_len) 23062306a36Sopenharmony_ci zfcp_dbf_pl_write(dbf, srb->payload.data, rec->pl_len, 23162306a36Sopenharmony_ci "fsf_uss", req->req_id); 23262306a36Sopenharmony_cilog: 23362306a36Sopenharmony_ci debug_event(dbf->hba, level, rec, sizeof(*rec)); 23462306a36Sopenharmony_ci spin_unlock_irqrestore(&dbf->hba_lock, flags); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/** 23862306a36Sopenharmony_ci * zfcp_dbf_hba_bit_err - trace event for bit error conditions 23962306a36Sopenharmony_ci * @tag: tag indicating which kind of bit error unsolicited status was received 24062306a36Sopenharmony_ci * @req: request which caused the bit_error condition 24162306a36Sopenharmony_ci */ 24262306a36Sopenharmony_civoid zfcp_dbf_hba_bit_err(char *tag, struct zfcp_fsf_req *req) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci struct zfcp_dbf *dbf = req->adapter->dbf; 24562306a36Sopenharmony_ci struct zfcp_dbf_hba *rec = &dbf->hba_buf; 24662306a36Sopenharmony_ci struct fsf_status_read_buffer *sr_buf = req->data; 24762306a36Sopenharmony_ci static int const level = 1; 24862306a36Sopenharmony_ci unsigned long flags; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci if (unlikely(!debug_level_enabled(dbf->hba, level))) 25162306a36Sopenharmony_ci return; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci spin_lock_irqsave(&dbf->hba_lock, flags); 25462306a36Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); 25762306a36Sopenharmony_ci rec->id = ZFCP_DBF_HBA_BIT; 25862306a36Sopenharmony_ci rec->fsf_req_id = req->req_id; 25962306a36Sopenharmony_ci rec->fsf_req_status = req->status; 26062306a36Sopenharmony_ci rec->fsf_cmd = FSF_QTCB_UNSOLICITED_STATUS; 26162306a36Sopenharmony_ci memcpy(&rec->u.be, &sr_buf->payload.bit_error, 26262306a36Sopenharmony_ci sizeof(struct fsf_bit_error_payload)); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci debug_event(dbf->hba, level, rec, sizeof(*rec)); 26562306a36Sopenharmony_ci spin_unlock_irqrestore(&dbf->hba_lock, flags); 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci/** 26962306a36Sopenharmony_ci * zfcp_dbf_hba_def_err - trace event for deferred error messages 27062306a36Sopenharmony_ci * @adapter: pointer to struct zfcp_adapter 27162306a36Sopenharmony_ci * @req_id: request id which caused the deferred error message 27262306a36Sopenharmony_ci * @scount: number of sbals incl. the signaling sbal 27362306a36Sopenharmony_ci * @pl: array of all involved sbals 27462306a36Sopenharmony_ci */ 27562306a36Sopenharmony_civoid zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount, 27662306a36Sopenharmony_ci void **pl) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci struct zfcp_dbf *dbf = adapter->dbf; 27962306a36Sopenharmony_ci struct zfcp_dbf_pay *payload = &dbf->pay_buf; 28062306a36Sopenharmony_ci unsigned long flags; 28162306a36Sopenharmony_ci static int const level = 1; 28262306a36Sopenharmony_ci u16 length; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (unlikely(!debug_level_enabled(dbf->pay, level))) 28562306a36Sopenharmony_ci return; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci if (!pl) 28862306a36Sopenharmony_ci return; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci spin_lock_irqsave(&dbf->pay_lock, flags); 29162306a36Sopenharmony_ci memset(payload, 0, sizeof(*payload)); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci memcpy(payload->area, "def_err", 7); 29462306a36Sopenharmony_ci payload->fsf_req_id = req_id; 29562306a36Sopenharmony_ci payload->counter = 0; 29662306a36Sopenharmony_ci length = min((u16)sizeof(struct qdio_buffer), 29762306a36Sopenharmony_ci (u16)ZFCP_DBF_PAY_MAX_REC); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci while (payload->counter < scount && (char *)pl[payload->counter]) { 30062306a36Sopenharmony_ci memcpy(payload->data, (char *)pl[payload->counter], length); 30162306a36Sopenharmony_ci debug_event(dbf->pay, level, payload, zfcp_dbf_plen(length)); 30262306a36Sopenharmony_ci payload->counter++; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci spin_unlock_irqrestore(&dbf->pay_lock, flags); 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, 30962306a36Sopenharmony_ci struct zfcp_adapter *adapter, 31062306a36Sopenharmony_ci struct zfcp_port *port, 31162306a36Sopenharmony_ci struct scsi_device *sdev) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci rec->adapter_status = atomic_read(&adapter->status); 31462306a36Sopenharmony_ci if (port) { 31562306a36Sopenharmony_ci rec->port_status = atomic_read(&port->status); 31662306a36Sopenharmony_ci rec->wwpn = port->wwpn; 31762306a36Sopenharmony_ci rec->d_id = port->d_id; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci if (sdev) { 32062306a36Sopenharmony_ci rec->lun_status = atomic_read(&sdev_to_zfcp(sdev)->status); 32162306a36Sopenharmony_ci rec->lun = zfcp_scsi_dev_lun(sdev); 32262306a36Sopenharmony_ci } else 32362306a36Sopenharmony_ci rec->lun = ZFCP_DBF_INVALID_LUN; 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci/** 32762306a36Sopenharmony_ci * zfcp_dbf_rec_trig - trace event related to triggered recovery 32862306a36Sopenharmony_ci * @tag: identifier for event 32962306a36Sopenharmony_ci * @adapter: adapter on which the erp_action should run 33062306a36Sopenharmony_ci * @port: remote port involved in the erp_action 33162306a36Sopenharmony_ci * @sdev: scsi device involved in the erp_action 33262306a36Sopenharmony_ci * @want: wanted erp_action 33362306a36Sopenharmony_ci * @need: required erp_action 33462306a36Sopenharmony_ci * 33562306a36Sopenharmony_ci * The adapter->erp_lock has to be held. 33662306a36Sopenharmony_ci */ 33762306a36Sopenharmony_civoid zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter, 33862306a36Sopenharmony_ci struct zfcp_port *port, struct scsi_device *sdev, 33962306a36Sopenharmony_ci u8 want, u8 need) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci struct zfcp_dbf *dbf = adapter->dbf; 34262306a36Sopenharmony_ci struct zfcp_dbf_rec *rec = &dbf->rec_buf; 34362306a36Sopenharmony_ci static int const level = 1; 34462306a36Sopenharmony_ci struct list_head *entry; 34562306a36Sopenharmony_ci unsigned long flags; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci lockdep_assert_held(&adapter->erp_lock); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (unlikely(!debug_level_enabled(dbf->rec, level))) 35062306a36Sopenharmony_ci return; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci spin_lock_irqsave(&dbf->rec_lock, flags); 35362306a36Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci rec->id = ZFCP_DBF_REC_TRIG; 35662306a36Sopenharmony_ci memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); 35762306a36Sopenharmony_ci zfcp_dbf_set_common(rec, adapter, port, sdev); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci list_for_each(entry, &adapter->erp_ready_head) 36062306a36Sopenharmony_ci rec->u.trig.ready++; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci list_for_each(entry, &adapter->erp_running_head) 36362306a36Sopenharmony_ci rec->u.trig.running++; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci rec->u.trig.want = want; 36662306a36Sopenharmony_ci rec->u.trig.need = need; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci debug_event(dbf->rec, level, rec, sizeof(*rec)); 36962306a36Sopenharmony_ci spin_unlock_irqrestore(&dbf->rec_lock, flags); 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci/** 37362306a36Sopenharmony_ci * zfcp_dbf_rec_trig_lock - trace event related to triggered recovery with lock 37462306a36Sopenharmony_ci * @tag: identifier for event 37562306a36Sopenharmony_ci * @adapter: adapter on which the erp_action should run 37662306a36Sopenharmony_ci * @port: remote port involved in the erp_action 37762306a36Sopenharmony_ci * @sdev: scsi device involved in the erp_action 37862306a36Sopenharmony_ci * @want: wanted erp_action 37962306a36Sopenharmony_ci * @need: required erp_action 38062306a36Sopenharmony_ci * 38162306a36Sopenharmony_ci * The adapter->erp_lock must not be held. 38262306a36Sopenharmony_ci */ 38362306a36Sopenharmony_civoid zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter, 38462306a36Sopenharmony_ci struct zfcp_port *port, struct scsi_device *sdev, 38562306a36Sopenharmony_ci u8 want, u8 need) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci unsigned long flags; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci read_lock_irqsave(&adapter->erp_lock, flags); 39062306a36Sopenharmony_ci zfcp_dbf_rec_trig(tag, adapter, port, sdev, want, need); 39162306a36Sopenharmony_ci read_unlock_irqrestore(&adapter->erp_lock, flags); 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci/** 39562306a36Sopenharmony_ci * zfcp_dbf_rec_run_lvl - trace event related to running recovery 39662306a36Sopenharmony_ci * @level: trace level to be used for event 39762306a36Sopenharmony_ci * @tag: identifier for event 39862306a36Sopenharmony_ci * @erp: erp_action running 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_civoid zfcp_dbf_rec_run_lvl(int level, char *tag, struct zfcp_erp_action *erp) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci struct zfcp_dbf *dbf = erp->adapter->dbf; 40362306a36Sopenharmony_ci struct zfcp_dbf_rec *rec = &dbf->rec_buf; 40462306a36Sopenharmony_ci unsigned long flags; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci if (!debug_level_enabled(dbf->rec, level)) 40762306a36Sopenharmony_ci return; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci spin_lock_irqsave(&dbf->rec_lock, flags); 41062306a36Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci rec->id = ZFCP_DBF_REC_RUN; 41362306a36Sopenharmony_ci memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); 41462306a36Sopenharmony_ci zfcp_dbf_set_common(rec, erp->adapter, erp->port, erp->sdev); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci rec->u.run.fsf_req_id = erp->fsf_req_id; 41762306a36Sopenharmony_ci rec->u.run.rec_status = erp->status; 41862306a36Sopenharmony_ci rec->u.run.rec_step = erp->step; 41962306a36Sopenharmony_ci rec->u.run.rec_action = erp->type; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci if (erp->sdev) 42262306a36Sopenharmony_ci rec->u.run.rec_count = 42362306a36Sopenharmony_ci atomic_read(&sdev_to_zfcp(erp->sdev)->erp_counter); 42462306a36Sopenharmony_ci else if (erp->port) 42562306a36Sopenharmony_ci rec->u.run.rec_count = atomic_read(&erp->port->erp_counter); 42662306a36Sopenharmony_ci else 42762306a36Sopenharmony_ci rec->u.run.rec_count = atomic_read(&erp->adapter->erp_counter); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci debug_event(dbf->rec, level, rec, sizeof(*rec)); 43062306a36Sopenharmony_ci spin_unlock_irqrestore(&dbf->rec_lock, flags); 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci/** 43462306a36Sopenharmony_ci * zfcp_dbf_rec_run - trace event related to running recovery 43562306a36Sopenharmony_ci * @tag: identifier for event 43662306a36Sopenharmony_ci * @erp: erp_action running 43762306a36Sopenharmony_ci */ 43862306a36Sopenharmony_civoid zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp) 43962306a36Sopenharmony_ci{ 44062306a36Sopenharmony_ci zfcp_dbf_rec_run_lvl(1, tag, erp); 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci/** 44462306a36Sopenharmony_ci * zfcp_dbf_rec_run_wka - trace wka port event with info like running recovery 44562306a36Sopenharmony_ci * @tag: identifier for event 44662306a36Sopenharmony_ci * @wka_port: well known address port 44762306a36Sopenharmony_ci * @req_id: request ID to correlate with potential HBA trace record 44862306a36Sopenharmony_ci */ 44962306a36Sopenharmony_civoid zfcp_dbf_rec_run_wka(char *tag, struct zfcp_fc_wka_port *wka_port, 45062306a36Sopenharmony_ci u64 req_id) 45162306a36Sopenharmony_ci{ 45262306a36Sopenharmony_ci struct zfcp_dbf *dbf = wka_port->adapter->dbf; 45362306a36Sopenharmony_ci struct zfcp_dbf_rec *rec = &dbf->rec_buf; 45462306a36Sopenharmony_ci static int const level = 1; 45562306a36Sopenharmony_ci unsigned long flags; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci if (unlikely(!debug_level_enabled(dbf->rec, level))) 45862306a36Sopenharmony_ci return; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci spin_lock_irqsave(&dbf->rec_lock, flags); 46162306a36Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci rec->id = ZFCP_DBF_REC_RUN; 46462306a36Sopenharmony_ci memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); 46562306a36Sopenharmony_ci rec->port_status = wka_port->status; 46662306a36Sopenharmony_ci rec->d_id = wka_port->d_id; 46762306a36Sopenharmony_ci rec->lun = ZFCP_DBF_INVALID_LUN; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci rec->u.run.fsf_req_id = req_id; 47062306a36Sopenharmony_ci rec->u.run.rec_status = ~0; 47162306a36Sopenharmony_ci rec->u.run.rec_step = ~0; 47262306a36Sopenharmony_ci rec->u.run.rec_action = ~0; 47362306a36Sopenharmony_ci rec->u.run.rec_count = ~0; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci debug_event(dbf->rec, level, rec, sizeof(*rec)); 47662306a36Sopenharmony_ci spin_unlock_irqrestore(&dbf->rec_lock, flags); 47762306a36Sopenharmony_ci} 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci#define ZFCP_DBF_SAN_LEVEL 1 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_cistatic inline 48262306a36Sopenharmony_civoid zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf, 48362306a36Sopenharmony_ci char *paytag, struct scatterlist *sg, u8 id, u16 len, 48462306a36Sopenharmony_ci u64 req_id, u32 d_id, u16 cap_len) 48562306a36Sopenharmony_ci{ 48662306a36Sopenharmony_ci struct zfcp_dbf_san *rec = &dbf->san_buf; 48762306a36Sopenharmony_ci u16 rec_len; 48862306a36Sopenharmony_ci unsigned long flags; 48962306a36Sopenharmony_ci struct zfcp_dbf_pay *payload = &dbf->pay_buf; 49062306a36Sopenharmony_ci u16 pay_sum = 0; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci spin_lock_irqsave(&dbf->san_lock, flags); 49362306a36Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci rec->id = id; 49662306a36Sopenharmony_ci rec->fsf_req_id = req_id; 49762306a36Sopenharmony_ci rec->d_id = d_id; 49862306a36Sopenharmony_ci memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); 49962306a36Sopenharmony_ci rec->pl_len = len; /* full length even if we cap pay below */ 50062306a36Sopenharmony_ci if (!sg) 50162306a36Sopenharmony_ci goto out; 50262306a36Sopenharmony_ci rec_len = min_t(unsigned int, sg->length, ZFCP_DBF_SAN_MAX_PAYLOAD); 50362306a36Sopenharmony_ci memcpy(rec->payload, sg_virt(sg), rec_len); /* part of 1st sg entry */ 50462306a36Sopenharmony_ci if (len <= rec_len) 50562306a36Sopenharmony_ci goto out; /* skip pay record if full content in rec->payload */ 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci /* if (len > rec_len): 50862306a36Sopenharmony_ci * dump data up to cap_len ignoring small duplicate in rec->payload 50962306a36Sopenharmony_ci */ 51062306a36Sopenharmony_ci spin_lock(&dbf->pay_lock); 51162306a36Sopenharmony_ci memset(payload, 0, sizeof(*payload)); 51262306a36Sopenharmony_ci memcpy(payload->area, paytag, ZFCP_DBF_TAG_LEN); 51362306a36Sopenharmony_ci payload->fsf_req_id = req_id; 51462306a36Sopenharmony_ci payload->counter = 0; 51562306a36Sopenharmony_ci for (; sg && pay_sum < cap_len; sg = sg_next(sg)) { 51662306a36Sopenharmony_ci u16 pay_len, offset = 0; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci while (offset < sg->length && pay_sum < cap_len) { 51962306a36Sopenharmony_ci pay_len = min((u16)ZFCP_DBF_PAY_MAX_REC, 52062306a36Sopenharmony_ci (u16)(sg->length - offset)); 52162306a36Sopenharmony_ci /* cap_len <= pay_sum < cap_len+ZFCP_DBF_PAY_MAX_REC */ 52262306a36Sopenharmony_ci memcpy(payload->data, sg_virt(sg) + offset, pay_len); 52362306a36Sopenharmony_ci debug_event(dbf->pay, ZFCP_DBF_SAN_LEVEL, payload, 52462306a36Sopenharmony_ci zfcp_dbf_plen(pay_len)); 52562306a36Sopenharmony_ci payload->counter++; 52662306a36Sopenharmony_ci offset += pay_len; 52762306a36Sopenharmony_ci pay_sum += pay_len; 52862306a36Sopenharmony_ci } 52962306a36Sopenharmony_ci } 53062306a36Sopenharmony_ci spin_unlock(&dbf->pay_lock); 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ciout: 53362306a36Sopenharmony_ci debug_event(dbf->san, ZFCP_DBF_SAN_LEVEL, rec, sizeof(*rec)); 53462306a36Sopenharmony_ci spin_unlock_irqrestore(&dbf->san_lock, flags); 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci/** 53862306a36Sopenharmony_ci * zfcp_dbf_san_req - trace event for issued SAN request 53962306a36Sopenharmony_ci * @tag: identifier for event 54062306a36Sopenharmony_ci * @fsf: request containing issued CT or ELS data 54162306a36Sopenharmony_ci * @d_id: N_Port_ID where SAN request is sent to 54262306a36Sopenharmony_ci * d_id: destination ID 54362306a36Sopenharmony_ci */ 54462306a36Sopenharmony_civoid zfcp_dbf_san_req(char *tag, struct zfcp_fsf_req *fsf, u32 d_id) 54562306a36Sopenharmony_ci{ 54662306a36Sopenharmony_ci struct zfcp_dbf *dbf = fsf->adapter->dbf; 54762306a36Sopenharmony_ci struct zfcp_fsf_ct_els *ct_els = fsf->data; 54862306a36Sopenharmony_ci u16 length; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci if (unlikely(!debug_level_enabled(dbf->san, ZFCP_DBF_SAN_LEVEL))) 55162306a36Sopenharmony_ci return; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci length = (u16)zfcp_qdio_real_bytes(ct_els->req); 55462306a36Sopenharmony_ci zfcp_dbf_san(tag, dbf, "san_req", ct_els->req, ZFCP_DBF_SAN_REQ, 55562306a36Sopenharmony_ci length, fsf->req_id, d_id, length); 55662306a36Sopenharmony_ci} 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_cistatic u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag, 55962306a36Sopenharmony_ci struct zfcp_fsf_req *fsf, 56062306a36Sopenharmony_ci u16 len) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci struct zfcp_fsf_ct_els *ct_els = fsf->data; 56362306a36Sopenharmony_ci struct fc_ct_hdr *reqh = sg_virt(ct_els->req); 56462306a36Sopenharmony_ci struct fc_ns_gid_ft *reqn = (struct fc_ns_gid_ft *)(reqh + 1); 56562306a36Sopenharmony_ci struct scatterlist *resp_entry = ct_els->resp; 56662306a36Sopenharmony_ci struct fc_ct_hdr *resph; 56762306a36Sopenharmony_ci struct fc_gpn_ft_resp *acc; 56862306a36Sopenharmony_ci int max_entries, x, last = 0; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci if (!(memcmp(tag, "fsscth2", 7) == 0 57162306a36Sopenharmony_ci && ct_els->d_id == FC_FID_DIR_SERV 57262306a36Sopenharmony_ci && reqh->ct_rev == FC_CT_REV 57362306a36Sopenharmony_ci && reqh->ct_in_id[0] == 0 57462306a36Sopenharmony_ci && reqh->ct_in_id[1] == 0 57562306a36Sopenharmony_ci && reqh->ct_in_id[2] == 0 57662306a36Sopenharmony_ci && reqh->ct_fs_type == FC_FST_DIR 57762306a36Sopenharmony_ci && reqh->ct_fs_subtype == FC_NS_SUBTYPE 57862306a36Sopenharmony_ci && reqh->ct_options == 0 57962306a36Sopenharmony_ci && reqh->_ct_resvd1 == 0 58062306a36Sopenharmony_ci && reqh->ct_cmd == cpu_to_be16(FC_NS_GPN_FT) 58162306a36Sopenharmony_ci /* reqh->ct_mr_size can vary so do not match but read below */ 58262306a36Sopenharmony_ci && reqh->_ct_resvd2 == 0 58362306a36Sopenharmony_ci && reqh->ct_reason == 0 58462306a36Sopenharmony_ci && reqh->ct_explan == 0 58562306a36Sopenharmony_ci && reqh->ct_vendor == 0 58662306a36Sopenharmony_ci && reqn->fn_resvd == 0 58762306a36Sopenharmony_ci && reqn->fn_domain_id_scope == 0 58862306a36Sopenharmony_ci && reqn->fn_area_id_scope == 0 58962306a36Sopenharmony_ci && reqn->fn_fc4_type == FC_TYPE_FCP)) 59062306a36Sopenharmony_ci return len; /* not GPN_FT response so do not cap */ 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci acc = sg_virt(resp_entry); 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci /* cap all but accept CT responses to at least the CT header */ 59562306a36Sopenharmony_ci resph = (struct fc_ct_hdr *)acc; 59662306a36Sopenharmony_ci if ((ct_els->status) || 59762306a36Sopenharmony_ci (resph->ct_cmd != cpu_to_be16(FC_FS_ACC))) 59862306a36Sopenharmony_ci return max(FC_CT_HDR_LEN, ZFCP_DBF_SAN_MAX_PAYLOAD); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci max_entries = (be16_to_cpu(reqh->ct_mr_size) * 4 / 60162306a36Sopenharmony_ci sizeof(struct fc_gpn_ft_resp)) 60262306a36Sopenharmony_ci + 1 /* zfcp_fc_scan_ports: bytes correct, entries off-by-one 60362306a36Sopenharmony_ci * to account for header as 1st pseudo "entry" */; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci /* the basic CT_IU preamble is the same size as one entry in the GPN_FT 60662306a36Sopenharmony_ci * response, allowing us to skip special handling for it - just skip it 60762306a36Sopenharmony_ci */ 60862306a36Sopenharmony_ci for (x = 1; x < max_entries && !last; x++) { 60962306a36Sopenharmony_ci if (x % (ZFCP_FC_GPN_FT_ENT_PAGE + 1)) 61062306a36Sopenharmony_ci acc++; 61162306a36Sopenharmony_ci else 61262306a36Sopenharmony_ci acc = sg_virt(++resp_entry); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci last = acc->fp_flags & FC_NS_FID_LAST; 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci len = min(len, (u16)(x * sizeof(struct fc_gpn_ft_resp))); 61762306a36Sopenharmony_ci return len; /* cap after last entry */ 61862306a36Sopenharmony_ci} 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci/** 62162306a36Sopenharmony_ci * zfcp_dbf_san_res - trace event for received SAN request 62262306a36Sopenharmony_ci * @tag: identifier for event 62362306a36Sopenharmony_ci * @fsf: request containing received CT or ELS data 62462306a36Sopenharmony_ci */ 62562306a36Sopenharmony_civoid zfcp_dbf_san_res(char *tag, struct zfcp_fsf_req *fsf) 62662306a36Sopenharmony_ci{ 62762306a36Sopenharmony_ci struct zfcp_dbf *dbf = fsf->adapter->dbf; 62862306a36Sopenharmony_ci struct zfcp_fsf_ct_els *ct_els = fsf->data; 62962306a36Sopenharmony_ci u16 length; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci if (unlikely(!debug_level_enabled(dbf->san, ZFCP_DBF_SAN_LEVEL))) 63262306a36Sopenharmony_ci return; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci length = (u16)zfcp_qdio_real_bytes(ct_els->resp); 63562306a36Sopenharmony_ci zfcp_dbf_san(tag, dbf, "san_res", ct_els->resp, ZFCP_DBF_SAN_RES, 63662306a36Sopenharmony_ci length, fsf->req_id, ct_els->d_id, 63762306a36Sopenharmony_ci zfcp_dbf_san_res_cap_len_if_gpn_ft(tag, fsf, length)); 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci/** 64162306a36Sopenharmony_ci * zfcp_dbf_san_in_els - trace event for incoming ELS 64262306a36Sopenharmony_ci * @tag: identifier for event 64362306a36Sopenharmony_ci * @fsf: request containing received ELS data 64462306a36Sopenharmony_ci */ 64562306a36Sopenharmony_civoid zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf) 64662306a36Sopenharmony_ci{ 64762306a36Sopenharmony_ci struct zfcp_dbf *dbf = fsf->adapter->dbf; 64862306a36Sopenharmony_ci struct fsf_status_read_buffer *srb = 64962306a36Sopenharmony_ci (struct fsf_status_read_buffer *) fsf->data; 65062306a36Sopenharmony_ci u16 length; 65162306a36Sopenharmony_ci struct scatterlist sg; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci if (unlikely(!debug_level_enabled(dbf->san, ZFCP_DBF_SAN_LEVEL))) 65462306a36Sopenharmony_ci return; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci length = (u16)(srb->length - 65762306a36Sopenharmony_ci offsetof(struct fsf_status_read_buffer, payload)); 65862306a36Sopenharmony_ci sg_init_one(&sg, srb->payload.data, length); 65962306a36Sopenharmony_ci zfcp_dbf_san(tag, dbf, "san_els", &sg, ZFCP_DBF_SAN_ELS, length, 66062306a36Sopenharmony_ci fsf->req_id, ntoh24(srb->d_id), length); 66162306a36Sopenharmony_ci} 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci/** 66462306a36Sopenharmony_ci * zfcp_dbf_scsi_common() - Common trace event helper for scsi. 66562306a36Sopenharmony_ci * @tag: Identifier for event. 66662306a36Sopenharmony_ci * @level: trace level of event. 66762306a36Sopenharmony_ci * @sdev: Pointer to SCSI device as context for this event. 66862306a36Sopenharmony_ci * @sc: Pointer to SCSI command, or NULL with task management function (TMF). 66962306a36Sopenharmony_ci * @fsf: Pointer to FSF request, or NULL. 67062306a36Sopenharmony_ci */ 67162306a36Sopenharmony_civoid zfcp_dbf_scsi_common(char *tag, int level, struct scsi_device *sdev, 67262306a36Sopenharmony_ci struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf) 67362306a36Sopenharmony_ci{ 67462306a36Sopenharmony_ci struct zfcp_adapter *adapter = 67562306a36Sopenharmony_ci (struct zfcp_adapter *) sdev->host->hostdata[0]; 67662306a36Sopenharmony_ci struct zfcp_dbf *dbf = adapter->dbf; 67762306a36Sopenharmony_ci struct zfcp_dbf_scsi *rec = &dbf->scsi_buf; 67862306a36Sopenharmony_ci struct fcp_resp_with_ext *fcp_rsp; 67962306a36Sopenharmony_ci struct fcp_resp_rsp_info *fcp_rsp_info; 68062306a36Sopenharmony_ci unsigned long flags; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci spin_lock_irqsave(&dbf->scsi_lock, flags); 68362306a36Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); 68662306a36Sopenharmony_ci rec->id = ZFCP_DBF_SCSI_CMND; 68762306a36Sopenharmony_ci if (sc) { 68862306a36Sopenharmony_ci rec->scsi_result = sc->result; 68962306a36Sopenharmony_ci rec->scsi_retries = sc->retries; 69062306a36Sopenharmony_ci rec->scsi_allowed = sc->allowed; 69162306a36Sopenharmony_ci rec->scsi_id = sc->device->id; 69262306a36Sopenharmony_ci rec->scsi_lun = (u32)sc->device->lun; 69362306a36Sopenharmony_ci rec->scsi_lun_64_hi = (u32)(sc->device->lun >> 32); 69462306a36Sopenharmony_ci rec->host_scribble = (u64)sc->host_scribble; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci memcpy(rec->scsi_opcode, sc->cmnd, 69762306a36Sopenharmony_ci min_t(int, sc->cmd_len, ZFCP_DBF_SCSI_OPCODE)); 69862306a36Sopenharmony_ci } else { 69962306a36Sopenharmony_ci rec->scsi_result = ~0; 70062306a36Sopenharmony_ci rec->scsi_retries = ~0; 70162306a36Sopenharmony_ci rec->scsi_allowed = ~0; 70262306a36Sopenharmony_ci rec->scsi_id = sdev->id; 70362306a36Sopenharmony_ci rec->scsi_lun = (u32)sdev->lun; 70462306a36Sopenharmony_ci rec->scsi_lun_64_hi = (u32)(sdev->lun >> 32); 70562306a36Sopenharmony_ci rec->host_scribble = ~0; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci memset(rec->scsi_opcode, 0xff, ZFCP_DBF_SCSI_OPCODE); 70862306a36Sopenharmony_ci } 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci if (fsf) { 71162306a36Sopenharmony_ci rec->fsf_req_id = fsf->req_id; 71262306a36Sopenharmony_ci rec->pl_len = FCP_RESP_WITH_EXT; 71362306a36Sopenharmony_ci fcp_rsp = &(fsf->qtcb->bottom.io.fcp_rsp.iu); 71462306a36Sopenharmony_ci /* mandatory parts of FCP_RSP IU in this SCSI record */ 71562306a36Sopenharmony_ci memcpy(&rec->fcp_rsp, fcp_rsp, FCP_RESP_WITH_EXT); 71662306a36Sopenharmony_ci if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) { 71762306a36Sopenharmony_ci fcp_rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; 71862306a36Sopenharmony_ci rec->fcp_rsp_info = fcp_rsp_info->rsp_code; 71962306a36Sopenharmony_ci rec->pl_len += be32_to_cpu(fcp_rsp->ext.fr_rsp_len); 72062306a36Sopenharmony_ci } 72162306a36Sopenharmony_ci if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) { 72262306a36Sopenharmony_ci rec->pl_len += be32_to_cpu(fcp_rsp->ext.fr_sns_len); 72362306a36Sopenharmony_ci } 72462306a36Sopenharmony_ci /* complete FCP_RSP IU in associated PAYload record 72562306a36Sopenharmony_ci * but only if there are optional parts 72662306a36Sopenharmony_ci */ 72762306a36Sopenharmony_ci if (fcp_rsp->resp.fr_flags != 0) 72862306a36Sopenharmony_ci zfcp_dbf_pl_write( 72962306a36Sopenharmony_ci dbf, fcp_rsp, 73062306a36Sopenharmony_ci /* at least one full PAY record 73162306a36Sopenharmony_ci * but not beyond hardware response field 73262306a36Sopenharmony_ci */ 73362306a36Sopenharmony_ci min_t(u16, max_t(u16, rec->pl_len, 73462306a36Sopenharmony_ci ZFCP_DBF_PAY_MAX_REC), 73562306a36Sopenharmony_ci FSF_FCP_RSP_SIZE), 73662306a36Sopenharmony_ci "fcp_riu", fsf->req_id); 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci debug_event(dbf->scsi, level, rec, sizeof(*rec)); 74062306a36Sopenharmony_ci spin_unlock_irqrestore(&dbf->scsi_lock, flags); 74162306a36Sopenharmony_ci} 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci/** 74462306a36Sopenharmony_ci * zfcp_dbf_scsi_eh() - Trace event for special cases of scsi_eh callbacks. 74562306a36Sopenharmony_ci * @tag: Identifier for event. 74662306a36Sopenharmony_ci * @adapter: Pointer to zfcp adapter as context for this event. 74762306a36Sopenharmony_ci * @scsi_id: SCSI ID/target to indicate scope of task management function (TMF). 74862306a36Sopenharmony_ci * @ret: Return value of calling function. 74962306a36Sopenharmony_ci * 75062306a36Sopenharmony_ci * This SCSI trace variant does not depend on any of: 75162306a36Sopenharmony_ci * scsi_cmnd, zfcp_fsf_req, scsi_device. 75262306a36Sopenharmony_ci */ 75362306a36Sopenharmony_civoid zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter, 75462306a36Sopenharmony_ci unsigned int scsi_id, int ret) 75562306a36Sopenharmony_ci{ 75662306a36Sopenharmony_ci struct zfcp_dbf *dbf = adapter->dbf; 75762306a36Sopenharmony_ci struct zfcp_dbf_scsi *rec = &dbf->scsi_buf; 75862306a36Sopenharmony_ci unsigned long flags; 75962306a36Sopenharmony_ci static int const level = 1; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci if (unlikely(!debug_level_enabled(adapter->dbf->scsi, level))) 76262306a36Sopenharmony_ci return; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci spin_lock_irqsave(&dbf->scsi_lock, flags); 76562306a36Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); 76862306a36Sopenharmony_ci rec->id = ZFCP_DBF_SCSI_CMND; 76962306a36Sopenharmony_ci rec->scsi_result = ret; /* re-use field, int is 4 bytes and fits */ 77062306a36Sopenharmony_ci rec->scsi_retries = ~0; 77162306a36Sopenharmony_ci rec->scsi_allowed = ~0; 77262306a36Sopenharmony_ci rec->fcp_rsp_info = ~0; 77362306a36Sopenharmony_ci rec->scsi_id = scsi_id; 77462306a36Sopenharmony_ci rec->scsi_lun = (u32)ZFCP_DBF_INVALID_LUN; 77562306a36Sopenharmony_ci rec->scsi_lun_64_hi = (u32)(ZFCP_DBF_INVALID_LUN >> 32); 77662306a36Sopenharmony_ci rec->host_scribble = ~0; 77762306a36Sopenharmony_ci memset(rec->scsi_opcode, 0xff, ZFCP_DBF_SCSI_OPCODE); 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci debug_event(dbf->scsi, level, rec, sizeof(*rec)); 78062306a36Sopenharmony_ci spin_unlock_irqrestore(&dbf->scsi_lock, flags); 78162306a36Sopenharmony_ci} 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_cistatic debug_info_t *zfcp_dbf_reg(const char *name, int size, int rec_size) 78462306a36Sopenharmony_ci{ 78562306a36Sopenharmony_ci struct debug_info *d; 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci d = debug_register(name, size, 1, rec_size); 78862306a36Sopenharmony_ci if (!d) 78962306a36Sopenharmony_ci return NULL; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci debug_register_view(d, &debug_hex_ascii_view); 79262306a36Sopenharmony_ci debug_set_level(d, dbflevel); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci return d; 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic void zfcp_dbf_unregister(struct zfcp_dbf *dbf) 79862306a36Sopenharmony_ci{ 79962306a36Sopenharmony_ci if (!dbf) 80062306a36Sopenharmony_ci return; 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci debug_unregister(dbf->scsi); 80362306a36Sopenharmony_ci debug_unregister(dbf->san); 80462306a36Sopenharmony_ci debug_unregister(dbf->hba); 80562306a36Sopenharmony_ci debug_unregister(dbf->pay); 80662306a36Sopenharmony_ci debug_unregister(dbf->rec); 80762306a36Sopenharmony_ci kfree(dbf); 80862306a36Sopenharmony_ci} 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci/** 81162306a36Sopenharmony_ci * zfcp_dbf_adapter_register - registers debug feature for an adapter 81262306a36Sopenharmony_ci * @adapter: pointer to adapter for which debug features should be registered 81362306a36Sopenharmony_ci * return: -ENOMEM on error, 0 otherwise 81462306a36Sopenharmony_ci */ 81562306a36Sopenharmony_ciint zfcp_dbf_adapter_register(struct zfcp_adapter *adapter) 81662306a36Sopenharmony_ci{ 81762306a36Sopenharmony_ci char name[DEBUG_MAX_NAME_LEN]; 81862306a36Sopenharmony_ci struct zfcp_dbf *dbf; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci dbf = kzalloc(sizeof(struct zfcp_dbf), GFP_KERNEL); 82162306a36Sopenharmony_ci if (!dbf) 82262306a36Sopenharmony_ci return -ENOMEM; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci spin_lock_init(&dbf->pay_lock); 82562306a36Sopenharmony_ci spin_lock_init(&dbf->hba_lock); 82662306a36Sopenharmony_ci spin_lock_init(&dbf->san_lock); 82762306a36Sopenharmony_ci spin_lock_init(&dbf->scsi_lock); 82862306a36Sopenharmony_ci spin_lock_init(&dbf->rec_lock); 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci /* debug feature area which records recovery activity */ 83162306a36Sopenharmony_ci sprintf(name, "zfcp_%s_rec", dev_name(&adapter->ccw_device->dev)); 83262306a36Sopenharmony_ci dbf->rec = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_rec)); 83362306a36Sopenharmony_ci if (!dbf->rec) 83462306a36Sopenharmony_ci goto err_out; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci /* debug feature area which records HBA (FSF and QDIO) conditions */ 83762306a36Sopenharmony_ci sprintf(name, "zfcp_%s_hba", dev_name(&adapter->ccw_device->dev)); 83862306a36Sopenharmony_ci dbf->hba = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_hba)); 83962306a36Sopenharmony_ci if (!dbf->hba) 84062306a36Sopenharmony_ci goto err_out; 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci /* debug feature area which records payload info */ 84362306a36Sopenharmony_ci sprintf(name, "zfcp_%s_pay", dev_name(&adapter->ccw_device->dev)); 84462306a36Sopenharmony_ci dbf->pay = zfcp_dbf_reg(name, dbfsize * 2, sizeof(struct zfcp_dbf_pay)); 84562306a36Sopenharmony_ci if (!dbf->pay) 84662306a36Sopenharmony_ci goto err_out; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci /* debug feature area which records SAN command failures and recovery */ 84962306a36Sopenharmony_ci sprintf(name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev)); 85062306a36Sopenharmony_ci dbf->san = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_san)); 85162306a36Sopenharmony_ci if (!dbf->san) 85262306a36Sopenharmony_ci goto err_out; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci /* debug feature area which records SCSI command failures and recovery */ 85562306a36Sopenharmony_ci sprintf(name, "zfcp_%s_scsi", dev_name(&adapter->ccw_device->dev)); 85662306a36Sopenharmony_ci dbf->scsi = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_scsi)); 85762306a36Sopenharmony_ci if (!dbf->scsi) 85862306a36Sopenharmony_ci goto err_out; 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci adapter->dbf = dbf; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci return 0; 86362306a36Sopenharmony_cierr_out: 86462306a36Sopenharmony_ci zfcp_dbf_unregister(dbf); 86562306a36Sopenharmony_ci return -ENOMEM; 86662306a36Sopenharmony_ci} 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci/** 86962306a36Sopenharmony_ci * zfcp_dbf_adapter_unregister - unregisters debug feature for an adapter 87062306a36Sopenharmony_ci * @adapter: pointer to adapter for which debug features should be unregistered 87162306a36Sopenharmony_ci */ 87262306a36Sopenharmony_civoid zfcp_dbf_adapter_unregister(struct zfcp_adapter *adapter) 87362306a36Sopenharmony_ci{ 87462306a36Sopenharmony_ci struct zfcp_dbf *dbf = adapter->dbf; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci adapter->dbf = NULL; 87762306a36Sopenharmony_ci zfcp_dbf_unregister(dbf); 87862306a36Sopenharmony_ci} 87962306a36Sopenharmony_ci 880