forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/scsi/lpfc/lpfc_bsg.c
....@@ -1,7 +1,7 @@
11 /*******************************************************************
22 * This file is part of the Emulex Linux Device Driver for *
33 * Fibre Channel Host Bus Adapters. *
4
- * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
4
+ * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
55 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
66 * Copyright (C) 2009-2015 Emulex. All rights reserved. *
77 * EMULEX and SLI are trademarks of Emulex. *
....@@ -27,6 +27,7 @@
2727 #include <linux/delay.h>
2828 #include <linux/list.h>
2929 #include <linux/bsg-lib.h>
30
+#include <linux/vmalloc.h>
3031
3132 #include <scsi/scsi.h>
3233 #include <scsi/scsi_host.h>
....@@ -1039,7 +1040,7 @@
10391040 if (!dmabuf) {
10401041 lpfc_printf_log(phba, KERN_ERR,
10411042 LOG_LIBDFC, "2616 No dmabuf "
1042
- "found for iocbq 0x%p\n",
1043
+ "found for iocbq x%px\n",
10431044 iocbq);
10441045 kfree(evt_dat->data);
10451046 kfree(evt_dat);
....@@ -1275,9 +1276,7 @@
12751276 return 0; /* call job done later */
12761277
12771278 job_error:
1278
- if (dd_data != NULL)
1279
- kfree(dd_data);
1280
-
1279
+ kfree(dd_data);
12811280 job->dd_data = NULL;
12821281 return rc;
12831282 }
....@@ -1570,7 +1569,6 @@
15701569 "2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n",
15711570 icmd->ulpContext, icmd->ulpIoTag, tag, phba->link_state);
15721571
1573
- ctiocb->iocb_cmpl = NULL;
15741572 ctiocb->iocb_flag |= LPFC_IO_LIBDFC;
15751573 ctiocb->vport = phba->pport;
15761574 ctiocb->context1 = dd_data;
....@@ -1967,14 +1965,17 @@
19671965 }
19681966
19691967 /**
1970
- * lpfc_sli4_bsg_set_internal_loopback - set sli4 internal loopback diagnostic
1968
+ * lpfc_sli4_bsg_set_loopback_mode - set sli4 internal loopback diagnostic
19711969 * @phba: Pointer to HBA context object.
1970
+ * @mode: loopback mode to set
1971
+ * @link_no: link number for loopback mode to set
19721972 *
19731973 * This function is responsible for issuing a sli4 mailbox command for setting
1974
- * up internal loopback diagnostic.
1974
+ * up loopback diagnostic for a link.
19751975 */
19761976 static int
1977
-lpfc_sli4_bsg_set_internal_loopback(struct lpfc_hba *phba)
1977
+lpfc_sli4_bsg_set_loopback_mode(struct lpfc_hba *phba, int mode,
1978
+ uint32_t link_no)
19781979 {
19791980 LPFC_MBOXQ_t *pmboxq;
19801981 uint32_t req_len, alloc_len;
....@@ -1995,11 +1996,19 @@
19951996 }
19961997 link_diag_loopback = &pmboxq->u.mqe.un.link_diag_loopback;
19971998 bf_set(lpfc_mbx_set_diag_state_link_num,
1998
- &link_diag_loopback->u.req, phba->sli4_hba.lnk_info.lnk_no);
1999
- bf_set(lpfc_mbx_set_diag_state_link_type,
2000
- &link_diag_loopback->u.req, phba->sli4_hba.lnk_info.lnk_tp);
1999
+ &link_diag_loopback->u.req, link_no);
2000
+
2001
+ if (phba->sli4_hba.conf_trunk & (1 << link_no)) {
2002
+ bf_set(lpfc_mbx_set_diag_state_link_type,
2003
+ &link_diag_loopback->u.req, LPFC_LNK_FC_TRUNKED);
2004
+ } else {
2005
+ bf_set(lpfc_mbx_set_diag_state_link_type,
2006
+ &link_diag_loopback->u.req,
2007
+ phba->sli4_hba.lnk_info.lnk_tp);
2008
+ }
2009
+
20012010 bf_set(lpfc_mbx_set_diag_lpbk_type, &link_diag_loopback->u.req,
2002
- LPFC_DIAG_LOOPBACK_TYPE_INTERNAL);
2011
+ mode);
20032012
20042013 mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO);
20052014 if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) {
....@@ -2053,7 +2062,7 @@
20532062 struct fc_bsg_request *bsg_request = job->request;
20542063 struct fc_bsg_reply *bsg_reply = job->reply;
20552064 struct diag_mode_set *loopback_mode;
2056
- uint32_t link_flags, timeout;
2065
+ uint32_t link_flags, timeout, link_no;
20572066 int i, rc = 0;
20582067
20592068 /* no data to return just the return code */
....@@ -2068,12 +2077,39 @@
20682077 (int)(sizeof(struct fc_bsg_request) +
20692078 sizeof(struct diag_mode_set)));
20702079 rc = -EINVAL;
2071
- goto job_error;
2080
+ goto job_done;
2081
+ }
2082
+
2083
+ loopback_mode = (struct diag_mode_set *)
2084
+ bsg_request->rqst_data.h_vendor.vendor_cmd;
2085
+ link_flags = loopback_mode->type;
2086
+ timeout = loopback_mode->timeout * 100;
2087
+
2088
+ if (loopback_mode->physical_link == -1)
2089
+ link_no = phba->sli4_hba.lnk_info.lnk_no;
2090
+ else
2091
+ link_no = loopback_mode->physical_link;
2092
+
2093
+ if (link_flags == DISABLE_LOOP_BACK) {
2094
+ rc = lpfc_sli4_bsg_set_loopback_mode(phba,
2095
+ LPFC_DIAG_LOOPBACK_TYPE_DISABLE,
2096
+ link_no);
2097
+ if (!rc) {
2098
+ /* Unset the need disable bit */
2099
+ phba->sli4_hba.conf_trunk &= ~((1 << link_no) << 4);
2100
+ }
2101
+ goto job_done;
2102
+ } else {
2103
+ /* Check if we need to disable the loopback state */
2104
+ if (phba->sli4_hba.conf_trunk & ((1 << link_no) << 4)) {
2105
+ rc = -EPERM;
2106
+ goto job_done;
2107
+ }
20722108 }
20732109
20742110 rc = lpfc_bsg_diag_mode_enter(phba);
20752111 if (rc)
2076
- goto job_error;
2112
+ goto job_done;
20772113
20782114 /* indicate we are in loobpack diagnostic mode */
20792115 spin_lock_irq(&phba->hbalock);
....@@ -2083,15 +2119,11 @@
20832119 /* reset port to start frome scratch */
20842120 rc = lpfc_selective_reset(phba);
20852121 if (rc)
2086
- goto job_error;
2122
+ goto job_done;
20872123
20882124 /* bring the link to diagnostic mode */
20892125 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
20902126 "3129 Bring link to diagnostic state.\n");
2091
- loopback_mode = (struct diag_mode_set *)
2092
- bsg_request->rqst_data.h_vendor.vendor_cmd;
2093
- link_flags = loopback_mode->type;
2094
- timeout = loopback_mode->timeout * 100;
20952127
20962128 rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1);
20972129 if (rc) {
....@@ -2119,13 +2151,54 @@
21192151 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
21202152 "3132 Set up loopback mode:x%x\n", link_flags);
21212153
2122
- if (link_flags == INTERNAL_LOOP_BACK)
2123
- rc = lpfc_sli4_bsg_set_internal_loopback(phba);
2124
- else if (link_flags == EXTERNAL_LOOP_BACK)
2125
- rc = lpfc_hba_init_link_fc_topology(phba,
2126
- FLAGS_TOPOLOGY_MODE_PT_PT,
2127
- MBX_NOWAIT);
2128
- else {
2154
+ switch (link_flags) {
2155
+ case INTERNAL_LOOP_BACK:
2156
+ if (phba->sli4_hba.conf_trunk & (1 << link_no)) {
2157
+ rc = lpfc_sli4_bsg_set_loopback_mode(phba,
2158
+ LPFC_DIAG_LOOPBACK_TYPE_INTERNAL,
2159
+ link_no);
2160
+ } else {
2161
+ /* Trunk is configured, but link is not in this trunk */
2162
+ if (phba->sli4_hba.conf_trunk) {
2163
+ rc = -ELNRNG;
2164
+ goto loopback_mode_exit;
2165
+ }
2166
+
2167
+ rc = lpfc_sli4_bsg_set_loopback_mode(phba,
2168
+ LPFC_DIAG_LOOPBACK_TYPE_INTERNAL,
2169
+ link_no);
2170
+ }
2171
+
2172
+ if (!rc) {
2173
+ /* Set the need disable bit */
2174
+ phba->sli4_hba.conf_trunk |= (1 << link_no) << 4;
2175
+ }
2176
+
2177
+ break;
2178
+ case EXTERNAL_LOOP_BACK:
2179
+ if (phba->sli4_hba.conf_trunk & (1 << link_no)) {
2180
+ rc = lpfc_sli4_bsg_set_loopback_mode(phba,
2181
+ LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL_TRUNKED,
2182
+ link_no);
2183
+ } else {
2184
+ /* Trunk is configured, but link is not in this trunk */
2185
+ if (phba->sli4_hba.conf_trunk) {
2186
+ rc = -ELNRNG;
2187
+ goto loopback_mode_exit;
2188
+ }
2189
+
2190
+ rc = lpfc_sli4_bsg_set_loopback_mode(phba,
2191
+ LPFC_DIAG_LOOPBACK_TYPE_SERDES,
2192
+ link_no);
2193
+ }
2194
+
2195
+ if (!rc) {
2196
+ /* Set the need disable bit */
2197
+ phba->sli4_hba.conf_trunk |= (1 << link_no) << 4;
2198
+ }
2199
+
2200
+ break;
2201
+ default:
21292202 rc = -EINVAL;
21302203 lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
21312204 "3141 Loopback mode:x%x not supported\n",
....@@ -2184,7 +2257,7 @@
21842257 }
21852258 lpfc_bsg_diag_mode_exit(phba);
21862259
2187
-job_error:
2260
+job_done:
21882261 /* make error code available to userspace */
21892262 bsg_reply->result = rc;
21902263 /* complete the job back to userspace if no error */
....@@ -2331,33 +2404,27 @@
23312404 union lpfc_sli4_cfg_shdr *shdr;
23322405 uint32_t shdr_status, shdr_add_status;
23332406 struct diag_status *diag_status_reply;
2334
- int mbxstatus, rc = 0;
2407
+ int mbxstatus, rc = -ENODEV, rc1 = 0;
23352408
23362409 shost = fc_bsg_to_shost(job);
2337
- if (!shost) {
2338
- rc = -ENODEV;
2410
+ if (!shost)
23392411 goto job_error;
2340
- }
2341
- vport = shost_priv(shost);
2342
- if (!vport) {
2343
- rc = -ENODEV;
2344
- goto job_error;
2345
- }
2346
- phba = vport->phba;
2347
- if (!phba) {
2348
- rc = -ENODEV;
2349
- goto job_error;
2350
- }
23512412
2352
- if (phba->sli_rev < LPFC_SLI_REV4) {
2353
- rc = -ENODEV;
2413
+ vport = shost_priv(shost);
2414
+ if (!vport)
23542415 goto job_error;
2355
- }
2416
+
2417
+ phba = vport->phba;
2418
+ if (!phba)
2419
+ goto job_error;
2420
+
2421
+
2422
+ if (phba->sli_rev < LPFC_SLI_REV4)
2423
+ goto job_error;
2424
+
23562425 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <
2357
- LPFC_SLI_INTF_IF_TYPE_2) {
2358
- rc = -ENODEV;
2426
+ LPFC_SLI_INTF_IF_TYPE_2)
23592427 goto job_error;
2360
- }
23612428
23622429 if (job->request_len < sizeof(struct fc_bsg_request) +
23632430 sizeof(struct sli4_link_diag)) {
....@@ -2392,8 +2459,10 @@
23922459 alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
23932460 LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE,
23942461 req_len, LPFC_SLI4_MBX_EMBED);
2395
- if (alloc_len != req_len)
2462
+ if (alloc_len != req_len) {
2463
+ rc = -ENOMEM;
23962464 goto link_diag_test_exit;
2465
+ }
23972466
23982467 run_link_diag_test = &pmboxq->u.mqe.un.link_diag_test;
23992468 bf_set(lpfc_mbx_run_diag_test_link_num, &run_link_diag_test->u.req,
....@@ -2425,13 +2494,12 @@
24252494 diag_status_reply = (struct diag_status *)
24262495 bsg_reply->reply_data.vendor_reply.vendor_rsp;
24272496
2428
- if (job->reply_len <
2429
- sizeof(struct fc_bsg_request) + sizeof(struct diag_status)) {
2497
+ if (job->reply_len < sizeof(*bsg_reply) + sizeof(*diag_status_reply)) {
24302498 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
24312499 "3012 Received Run link diag test reply "
24322500 "below minimum size (%d): reply_len:%d\n",
2433
- (int)(sizeof(struct fc_bsg_request) +
2434
- sizeof(struct diag_status)),
2501
+ (int)(sizeof(*bsg_reply) +
2502
+ sizeof(*diag_status_reply)),
24352503 job->reply_len);
24362504 rc = -EINVAL;
24372505 goto job_error;
....@@ -2442,7 +2510,7 @@
24422510 diag_status_reply->shdr_add_status = shdr_add_status;
24432511
24442512 link_diag_test_exit:
2445
- rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0);
2513
+ rc1 = lpfc_sli4_bsg_set_link_diag_state(phba, 0);
24462514
24472515 if (pmboxq)
24482516 mempool_free(pmboxq, phba->mbox_mem_pool);
....@@ -2451,6 +2519,8 @@
24512519
24522520 job_error:
24532521 /* make error code available to userspace */
2522
+ if (rc1 && !rc)
2523
+ rc = rc1;
24542524 bsg_reply->result = rc;
24552525 /* complete the job back to userspace if no error */
24562526 if (rc == 0)
....@@ -2500,9 +2570,9 @@
25002570 return -ENOMEM;
25012571 }
25022572
2503
- dmabuff = (struct lpfc_dmabuf *) mbox->context1;
2504
- mbox->context1 = NULL;
2505
- mbox->context2 = NULL;
2573
+ dmabuff = (struct lpfc_dmabuf *)mbox->ctx_buf;
2574
+ mbox->ctx_buf = NULL;
2575
+ mbox->ctx_ndlp = NULL;
25062576 status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
25072577
25082578 if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {
....@@ -2729,8 +2799,8 @@
27292799 INIT_LIST_HEAD(&dmabuf->list);
27302800
27312801 /* now, allocate dma buffer */
2732
- dmabuf->virt = dma_zalloc_coherent(&pcidev->dev, BSG_MBOX_SIZE,
2733
- &(dmabuf->phys), GFP_KERNEL);
2802
+ dmabuf->virt = dma_alloc_coherent(&pcidev->dev, BSG_MBOX_SIZE,
2803
+ &(dmabuf->phys), GFP_KERNEL);
27342804
27352805 if (!dmabuf->virt) {
27362806 kfree(dmabuf);
....@@ -2843,9 +2913,6 @@
28432913
28442914 if (nocopydata) {
28452915 bpl->tus.f.bdeFlags = 0;
2846
- pci_dma_sync_single_for_device(phba->pcidev,
2847
- dmp->dma.phys, LPFC_BPL_SIZE, PCI_DMA_TODEVICE);
2848
-
28492916 } else {
28502917 memset((uint8_t *)dmp->dma.virt, 0, cnt);
28512918 bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
....@@ -2949,7 +3016,7 @@
29493016 cmd->un.cont64[i].addrLow = putPaddrLow(mp[i]->phys);
29503017 cmd->un.cont64[i].tus.f.bdeSize =
29513018 ((struct lpfc_dmabufext *)mp[i])->size;
2952
- cmd->ulpBdeCount = ++i;
3019
+ cmd->ulpBdeCount = ++i;
29533020
29543021 if ((--num_bde > 0) && (i < 2))
29553022 continue;
....@@ -3350,8 +3417,7 @@
33503417 event_reply = (struct get_mgmt_rev_reply *)
33513418 bsg_reply->reply_data.vendor_reply.vendor_rsp;
33523419
3353
- if (job->reply_len <
3354
- sizeof(struct fc_bsg_request) + sizeof(struct get_mgmt_rev_reply)) {
3420
+ if (job->reply_len < sizeof(*bsg_reply) + sizeof(*event_reply)) {
33553421 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
33563422 "2741 Received GET_DFC_REV reply below "
33573423 "minimum size\n");
....@@ -3390,7 +3456,7 @@
33903456 unsigned long flags;
33913457 uint8_t *pmb, *pmb_buf;
33923458
3393
- dd_data = pmboxq->context1;
3459
+ dd_data = pmboxq->ctx_ndlp;
33943460
33953461 /*
33963462 * The outgoing buffer is readily referred from the dma buffer,
....@@ -3575,7 +3641,7 @@
35753641 struct lpfc_sli_config_mbox *sli_cfg_mbx;
35763642 uint8_t *pmbx;
35773643
3578
- dd_data = pmboxq->context1;
3644
+ dd_data = pmboxq->ctx_buf;
35793645
35803646 /* Determine if job has been aborted */
35813647 spin_lock_irqsave(&phba->ct_ev_lock, flags);
....@@ -3962,7 +4028,7 @@
39624028 pmboxq->mbox_cmpl = lpfc_bsg_issue_read_mbox_ext_cmpl;
39634029
39644030 /* context fields to callback function */
3965
- pmboxq->context1 = dd_data;
4031
+ pmboxq->ctx_buf = dd_data;
39664032 dd_data->type = TYPE_MBOX;
39674033 dd_data->set_job = job;
39684034 dd_data->context_un.mbox.pmboxq = pmboxq;
....@@ -4133,7 +4199,7 @@
41334199 pmboxq->mbox_cmpl = lpfc_bsg_issue_write_mbox_ext_cmpl;
41344200
41354201 /* context fields to callback function */
4136
- pmboxq->context1 = dd_data;
4202
+ pmboxq->ctx_buf = dd_data;
41374203 dd_data->type = TYPE_MBOX;
41384204 dd_data->set_job = job;
41394205 dd_data->context_un.mbox.pmboxq = pmboxq;
....@@ -4236,6 +4302,7 @@
42364302 case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES:
42374303 case COMN_OPCODE_GET_CNTL_ATTRIBUTES:
42384304 case COMN_OPCODE_GET_PROFILE_CONFIG:
4305
+ case COMN_OPCODE_SET_FEATURES:
42394306 lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
42404307 "3106 Handled SLI_CONFIG "
42414308 "subsys_comn, opcode:x%x\n",
....@@ -4479,7 +4546,7 @@
44794546 pmboxq->mbox_cmpl = lpfc_bsg_issue_write_mbox_ext_cmpl;
44804547
44814548 /* context fields to callback function */
4482
- pmboxq->context1 = dd_data;
4549
+ pmboxq->ctx_buf = dd_data;
44834550 dd_data->type = TYPE_MBOX;
44844551 dd_data->set_job = job;
44854552 dd_data->context_un.mbox.pmboxq = pmboxq;
....@@ -4687,7 +4754,7 @@
46874754 * Don't allow mailbox commands to be sent when blocked or when in
46884755 * the middle of discovery
46894756 */
4690
- if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
4757
+ if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
46914758 rc = -EAGAIN;
46924759 goto job_done;
46934760 }
....@@ -4766,7 +4833,7 @@
47664833 if (mbox_req->inExtWLen || mbox_req->outExtWLen) {
47674834 from = pmbx;
47684835 ext = from + sizeof(MAILBOX_t);
4769
- pmboxq->context2 = ext;
4836
+ pmboxq->ctx_buf = ext;
47704837 pmboxq->in_ext_byte_len =
47714838 mbox_req->inExtWLen * sizeof(uint32_t);
47724839 pmboxq->out_ext_byte_len =
....@@ -4894,7 +4961,7 @@
48944961 pmboxq->mbox_cmpl = lpfc_bsg_issue_mbox_cmpl;
48954962
48964963 /* setup context field to pass wait_queue pointer to wake function */
4897
- pmboxq->context1 = dd_data;
4964
+ pmboxq->ctx_ndlp = dd_data;
48984965 dd_data->type = TYPE_MBOX;
48994966 dd_data->set_job = job;
49004967 dd_data->context_un.mbox.pmboxq = pmboxq;
....@@ -5133,8 +5200,8 @@
51335200 goto no_dd_data;
51345201 }
51355202
5136
- if (job->reply_len <
5137
- sizeof(struct fc_bsg_request) + sizeof(struct menlo_response)) {
5203
+ if (job->reply_len < sizeof(*bsg_reply) +
5204
+ sizeof(struct menlo_response)) {
51385205 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
51395206 "2785 Received MENLO_CMD reply below "
51405207 "minimum size\n");
....@@ -5290,9 +5357,7 @@
52905357 forced_reply = (struct forced_link_speed_support_reply *)
52915358 bsg_reply->reply_data.vendor_reply.vendor_rsp;
52925359
5293
- if (job->reply_len <
5294
- sizeof(struct fc_bsg_request) +
5295
- sizeof(struct forced_link_speed_support_reply)) {
5360
+ if (job->reply_len < sizeof(*bsg_reply) + sizeof(*forced_reply)) {
52965361 lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
52975362 "0049 Received FORCED_LINK_SPEED reply below "
52985363 "minimum size\n");
....@@ -5309,6 +5374,392 @@
53095374 bsg_job_done(job, bsg_reply->result,
53105375 bsg_reply->reply_payload_rcv_len);
53115376 return rc;
5377
+}
5378
+
5379
+/**
5380
+ * lpfc_check_fwlog_support: Check FW log support on the adapter
5381
+ * @phba: Pointer to HBA context object.
5382
+ *
5383
+ * Check if FW Logging support by the adapter
5384
+ **/
5385
+int
5386
+lpfc_check_fwlog_support(struct lpfc_hba *phba)
5387
+{
5388
+ struct lpfc_ras_fwlog *ras_fwlog = NULL;
5389
+
5390
+ ras_fwlog = &phba->ras_fwlog;
5391
+
5392
+ if (ras_fwlog->ras_hwsupport == false)
5393
+ return -EACCES;
5394
+ else if (ras_fwlog->ras_enabled == false)
5395
+ return -EPERM;
5396
+ else
5397
+ return 0;
5398
+}
5399
+
5400
+/**
5401
+ * lpfc_bsg_get_ras_config: Get RAS configuration settings
5402
+ * @job: fc_bsg_job to handle
5403
+ *
5404
+ * Get RAS configuration values set.
5405
+ **/
5406
+static int
5407
+lpfc_bsg_get_ras_config(struct bsg_job *job)
5408
+{
5409
+ struct Scsi_Host *shost = fc_bsg_to_shost(job);
5410
+ struct lpfc_vport *vport = shost_priv(shost);
5411
+ struct fc_bsg_reply *bsg_reply = job->reply;
5412
+ struct lpfc_hba *phba = vport->phba;
5413
+ struct lpfc_bsg_get_ras_config_reply *ras_reply;
5414
+ struct lpfc_ras_fwlog *ras_fwlog = &phba->ras_fwlog;
5415
+ int rc = 0;
5416
+
5417
+ if (job->request_len <
5418
+ sizeof(struct fc_bsg_request) +
5419
+ sizeof(struct lpfc_bsg_ras_req)) {
5420
+ lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
5421
+ "6192 FW_LOG request received "
5422
+ "below minimum size\n");
5423
+ rc = -EINVAL;
5424
+ goto ras_job_error;
5425
+ }
5426
+
5427
+ /* Check FW log status */
5428
+ rc = lpfc_check_fwlog_support(phba);
5429
+ if (rc)
5430
+ goto ras_job_error;
5431
+
5432
+ ras_reply = (struct lpfc_bsg_get_ras_config_reply *)
5433
+ bsg_reply->reply_data.vendor_reply.vendor_rsp;
5434
+
5435
+ /* Current logging state */
5436
+ spin_lock_irq(&phba->hbalock);
5437
+ if (ras_fwlog->state == ACTIVE)
5438
+ ras_reply->state = LPFC_RASLOG_STATE_RUNNING;
5439
+ else
5440
+ ras_reply->state = LPFC_RASLOG_STATE_STOPPED;
5441
+ spin_unlock_irq(&phba->hbalock);
5442
+
5443
+ ras_reply->log_level = phba->ras_fwlog.fw_loglevel;
5444
+ ras_reply->log_buff_sz = phba->cfg_ras_fwlog_buffsize;
5445
+
5446
+ras_job_error:
5447
+ /* make error code available to userspace */
5448
+ bsg_reply->result = rc;
5449
+
5450
+ /* complete the job back to userspace */
5451
+ if (!rc)
5452
+ bsg_job_done(job, bsg_reply->result,
5453
+ bsg_reply->reply_payload_rcv_len);
5454
+ return rc;
5455
+}
5456
+
5457
+/**
5458
+ * lpfc_bsg_set_ras_config: Set FW logging parameters
5459
+ * @job: fc_bsg_job to handle
5460
+ *
5461
+ * Set log-level parameters for FW-logging in host memory
5462
+ **/
5463
+static int
5464
+lpfc_bsg_set_ras_config(struct bsg_job *job)
5465
+{
5466
+ struct Scsi_Host *shost = fc_bsg_to_shost(job);
5467
+ struct lpfc_vport *vport = shost_priv(shost);
5468
+ struct lpfc_hba *phba = vport->phba;
5469
+ struct lpfc_bsg_set_ras_config_req *ras_req;
5470
+ struct fc_bsg_request *bsg_request = job->request;
5471
+ struct lpfc_ras_fwlog *ras_fwlog = &phba->ras_fwlog;
5472
+ struct fc_bsg_reply *bsg_reply = job->reply;
5473
+ uint8_t action = 0, log_level = 0;
5474
+ int rc = 0, action_status = 0;
5475
+
5476
+ if (job->request_len <
5477
+ sizeof(struct fc_bsg_request) +
5478
+ sizeof(struct lpfc_bsg_set_ras_config_req)) {
5479
+ lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
5480
+ "6182 Received RAS_LOG request "
5481
+ "below minimum size\n");
5482
+ rc = -EINVAL;
5483
+ goto ras_job_error;
5484
+ }
5485
+
5486
+ /* Check FW log status */
5487
+ rc = lpfc_check_fwlog_support(phba);
5488
+ if (rc)
5489
+ goto ras_job_error;
5490
+
5491
+ ras_req = (struct lpfc_bsg_set_ras_config_req *)
5492
+ bsg_request->rqst_data.h_vendor.vendor_cmd;
5493
+ action = ras_req->action;
5494
+ log_level = ras_req->log_level;
5495
+
5496
+ if (action == LPFC_RASACTION_STOP_LOGGING) {
5497
+ /* Check if already disabled */
5498
+ spin_lock_irq(&phba->hbalock);
5499
+ if (ras_fwlog->state != ACTIVE) {
5500
+ spin_unlock_irq(&phba->hbalock);
5501
+ rc = -ESRCH;
5502
+ goto ras_job_error;
5503
+ }
5504
+ spin_unlock_irq(&phba->hbalock);
5505
+
5506
+ /* Disable logging */
5507
+ lpfc_ras_stop_fwlog(phba);
5508
+ } else {
5509
+ /*action = LPFC_RASACTION_START_LOGGING*/
5510
+
5511
+ /* Even though FW-logging is active re-initialize
5512
+ * FW-logging with new log-level. Return status
5513
+ * "Logging already Running" to caller.
5514
+ **/
5515
+ spin_lock_irq(&phba->hbalock);
5516
+ if (ras_fwlog->state != INACTIVE)
5517
+ action_status = -EINPROGRESS;
5518
+ spin_unlock_irq(&phba->hbalock);
5519
+
5520
+ /* Enable logging */
5521
+ rc = lpfc_sli4_ras_fwlog_init(phba, log_level,
5522
+ LPFC_RAS_ENABLE_LOGGING);
5523
+ if (rc) {
5524
+ rc = -EINVAL;
5525
+ goto ras_job_error;
5526
+ }
5527
+
5528
+ /* Check if FW-logging is re-initialized */
5529
+ if (action_status == -EINPROGRESS)
5530
+ rc = action_status;
5531
+ }
5532
+ras_job_error:
5533
+ /* make error code available to userspace */
5534
+ bsg_reply->result = rc;
5535
+
5536
+ /* complete the job back to userspace */
5537
+ if (!rc)
5538
+ bsg_job_done(job, bsg_reply->result,
5539
+ bsg_reply->reply_payload_rcv_len);
5540
+
5541
+ return rc;
5542
+}
5543
+
5544
+/**
5545
+ * lpfc_bsg_get_ras_lwpd: Get log write position data
5546
+ * @job: fc_bsg_job to handle
5547
+ *
5548
+ * Get Offset/Wrap count of the log message written
5549
+ * in host memory
5550
+ **/
5551
+static int
5552
+lpfc_bsg_get_ras_lwpd(struct bsg_job *job)
5553
+{
5554
+ struct Scsi_Host *shost = fc_bsg_to_shost(job);
5555
+ struct lpfc_vport *vport = shost_priv(shost);
5556
+ struct lpfc_bsg_get_ras_lwpd *ras_reply;
5557
+ struct lpfc_hba *phba = vport->phba;
5558
+ struct lpfc_ras_fwlog *ras_fwlog = &phba->ras_fwlog;
5559
+ struct fc_bsg_reply *bsg_reply = job->reply;
5560
+ u32 *lwpd_ptr = NULL;
5561
+ int rc = 0;
5562
+
5563
+ rc = lpfc_check_fwlog_support(phba);
5564
+ if (rc)
5565
+ goto ras_job_error;
5566
+
5567
+ if (job->request_len <
5568
+ sizeof(struct fc_bsg_request) +
5569
+ sizeof(struct lpfc_bsg_ras_req)) {
5570
+ lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
5571
+ "6183 Received RAS_LOG request "
5572
+ "below minimum size\n");
5573
+ rc = -EINVAL;
5574
+ goto ras_job_error;
5575
+ }
5576
+
5577
+ ras_reply = (struct lpfc_bsg_get_ras_lwpd *)
5578
+ bsg_reply->reply_data.vendor_reply.vendor_rsp;
5579
+
5580
+ if (!ras_fwlog->lwpd.virt) {
5581
+ lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
5582
+ "6193 Restart FW Logging\n");
5583
+ rc = -EINVAL;
5584
+ goto ras_job_error;
5585
+ }
5586
+
5587
+ /* Get lwpd offset */
5588
+ lwpd_ptr = (uint32_t *)(ras_fwlog->lwpd.virt);
5589
+ ras_reply->offset = be32_to_cpu(*lwpd_ptr & 0xffffffff);
5590
+
5591
+ /* Get wrap count */
5592
+ ras_reply->wrap_count = be32_to_cpu(*(++lwpd_ptr) & 0xffffffff);
5593
+
5594
+ras_job_error:
5595
+ /* make error code available to userspace */
5596
+ bsg_reply->result = rc;
5597
+
5598
+ /* complete the job back to userspace */
5599
+ if (!rc)
5600
+ bsg_job_done(job, bsg_reply->result,
5601
+ bsg_reply->reply_payload_rcv_len);
5602
+
5603
+ return rc;
5604
+}
5605
+
5606
+/**
5607
+ * lpfc_bsg_get_ras_fwlog: Read FW log
5608
+ * @job: fc_bsg_job to handle
5609
+ *
5610
+ * Copy the FW log into the passed buffer.
5611
+ **/
5612
+static int
5613
+lpfc_bsg_get_ras_fwlog(struct bsg_job *job)
5614
+{
5615
+ struct Scsi_Host *shost = fc_bsg_to_shost(job);
5616
+ struct lpfc_vport *vport = shost_priv(shost);
5617
+ struct lpfc_hba *phba = vport->phba;
5618
+ struct fc_bsg_request *bsg_request = job->request;
5619
+ struct fc_bsg_reply *bsg_reply = job->reply;
5620
+ struct lpfc_bsg_get_fwlog_req *ras_req;
5621
+ u32 rd_offset, rd_index, offset;
5622
+ void *src, *fwlog_buff;
5623
+ struct lpfc_ras_fwlog *ras_fwlog = NULL;
5624
+ struct lpfc_dmabuf *dmabuf, *next;
5625
+ int rc = 0;
5626
+
5627
+ ras_fwlog = &phba->ras_fwlog;
5628
+
5629
+ rc = lpfc_check_fwlog_support(phba);
5630
+ if (rc)
5631
+ goto ras_job_error;
5632
+
5633
+ /* Logging to be stopped before reading */
5634
+ spin_lock_irq(&phba->hbalock);
5635
+ if (ras_fwlog->state == ACTIVE) {
5636
+ spin_unlock_irq(&phba->hbalock);
5637
+ rc = -EINPROGRESS;
5638
+ goto ras_job_error;
5639
+ }
5640
+ spin_unlock_irq(&phba->hbalock);
5641
+
5642
+ if (job->request_len <
5643
+ sizeof(struct fc_bsg_request) +
5644
+ sizeof(struct lpfc_bsg_get_fwlog_req)) {
5645
+ lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
5646
+ "6184 Received RAS_LOG request "
5647
+ "below minimum size\n");
5648
+ rc = -EINVAL;
5649
+ goto ras_job_error;
5650
+ }
5651
+
5652
+ ras_req = (struct lpfc_bsg_get_fwlog_req *)
5653
+ bsg_request->rqst_data.h_vendor.vendor_cmd;
5654
+ rd_offset = ras_req->read_offset;
5655
+
5656
+ /* Allocate memory to read fw log*/
5657
+ fwlog_buff = vmalloc(ras_req->read_size);
5658
+ if (!fwlog_buff) {
5659
+ rc = -ENOMEM;
5660
+ goto ras_job_error;
5661
+ }
5662
+
5663
+ rd_index = (rd_offset / LPFC_RAS_MAX_ENTRY_SIZE);
5664
+ offset = (rd_offset % LPFC_RAS_MAX_ENTRY_SIZE);
5665
+
5666
+ list_for_each_entry_safe(dmabuf, next,
5667
+ &ras_fwlog->fwlog_buff_list, list) {
5668
+
5669
+ if (dmabuf->buffer_tag < rd_index)
5670
+ continue;
5671
+
5672
+ src = dmabuf->virt + offset;
5673
+ memcpy(fwlog_buff, src, ras_req->read_size);
5674
+ break;
5675
+ }
5676
+
5677
+ bsg_reply->reply_payload_rcv_len =
5678
+ sg_copy_from_buffer(job->reply_payload.sg_list,
5679
+ job->reply_payload.sg_cnt,
5680
+ fwlog_buff, ras_req->read_size);
5681
+
5682
+ vfree(fwlog_buff);
5683
+
5684
+ras_job_error:
5685
+ bsg_reply->result = rc;
5686
+ if (!rc)
5687
+ bsg_job_done(job, bsg_reply->result,
5688
+ bsg_reply->reply_payload_rcv_len);
5689
+
5690
+ return rc;
5691
+}
5692
+
5693
+static int
5694
+lpfc_get_trunk_info(struct bsg_job *job)
5695
+{
5696
+ struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
5697
+ struct lpfc_hba *phba = vport->phba;
5698
+ struct fc_bsg_reply *bsg_reply = job->reply;
5699
+ struct lpfc_trunk_info *event_reply;
5700
+ int rc = 0;
5701
+
5702
+ if (job->request_len <
5703
+ sizeof(struct fc_bsg_request) + sizeof(struct get_trunk_info_req)) {
5704
+ lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
5705
+ "2744 Received GET TRUNK _INFO request below "
5706
+ "minimum size\n");
5707
+ rc = -EINVAL;
5708
+ goto job_error;
5709
+ }
5710
+
5711
+ event_reply = (struct lpfc_trunk_info *)
5712
+ bsg_reply->reply_data.vendor_reply.vendor_rsp;
5713
+
5714
+ if (job->reply_len < sizeof(*bsg_reply) + sizeof(*event_reply)) {
5715
+ lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
5716
+ "2728 Received GET TRUNK _INFO reply below "
5717
+ "minimum size\n");
5718
+ rc = -EINVAL;
5719
+ goto job_error;
5720
+ }
5721
+ if (event_reply == NULL) {
5722
+ rc = -EINVAL;
5723
+ goto job_error;
5724
+ }
5725
+
5726
+ bsg_bf_set(lpfc_trunk_info_link_status, event_reply,
5727
+ (phba->link_state >= LPFC_LINK_UP) ? 1 : 0);
5728
+
5729
+ bsg_bf_set(lpfc_trunk_info_trunk_active0, event_reply,
5730
+ (phba->trunk_link.link0.state == LPFC_LINK_UP) ? 1 : 0);
5731
+
5732
+ bsg_bf_set(lpfc_trunk_info_trunk_active1, event_reply,
5733
+ (phba->trunk_link.link1.state == LPFC_LINK_UP) ? 1 : 0);
5734
+
5735
+ bsg_bf_set(lpfc_trunk_info_trunk_active2, event_reply,
5736
+ (phba->trunk_link.link2.state == LPFC_LINK_UP) ? 1 : 0);
5737
+
5738
+ bsg_bf_set(lpfc_trunk_info_trunk_active3, event_reply,
5739
+ (phba->trunk_link.link3.state == LPFC_LINK_UP) ? 1 : 0);
5740
+
5741
+ bsg_bf_set(lpfc_trunk_info_trunk_config0, event_reply,
5742
+ bf_get(lpfc_conf_trunk_port0, &phba->sli4_hba));
5743
+
5744
+ bsg_bf_set(lpfc_trunk_info_trunk_config1, event_reply,
5745
+ bf_get(lpfc_conf_trunk_port1, &phba->sli4_hba));
5746
+
5747
+ bsg_bf_set(lpfc_trunk_info_trunk_config2, event_reply,
5748
+ bf_get(lpfc_conf_trunk_port2, &phba->sli4_hba));
5749
+
5750
+ bsg_bf_set(lpfc_trunk_info_trunk_config3, event_reply,
5751
+ bf_get(lpfc_conf_trunk_port3, &phba->sli4_hba));
5752
+
5753
+ event_reply->port_speed = phba->sli4_hba.link_state.speed / 1000;
5754
+ event_reply->logical_speed =
5755
+ phba->sli4_hba.link_state.logical_speed / 1000;
5756
+job_error:
5757
+ bsg_reply->result = rc;
5758
+ if (!rc)
5759
+ bsg_job_done(job, bsg_reply->result,
5760
+ bsg_reply->reply_payload_rcv_len);
5761
+ return rc;
5762
+
53125763 }
53135764
53145765 /**
....@@ -5358,6 +5809,21 @@
53585809 case LPFC_BSG_VENDOR_FORCED_LINK_SPEED:
53595810 rc = lpfc_forced_link_speed(job);
53605811 break;
5812
+ case LPFC_BSG_VENDOR_RAS_GET_LWPD:
5813
+ rc = lpfc_bsg_get_ras_lwpd(job);
5814
+ break;
5815
+ case LPFC_BSG_VENDOR_RAS_GET_FWLOG:
5816
+ rc = lpfc_bsg_get_ras_fwlog(job);
5817
+ break;
5818
+ case LPFC_BSG_VENDOR_RAS_GET_CONFIG:
5819
+ rc = lpfc_bsg_get_ras_config(job);
5820
+ break;
5821
+ case LPFC_BSG_VENDOR_RAS_SET_CONFIG:
5822
+ rc = lpfc_bsg_set_ras_config(job);
5823
+ break;
5824
+ case LPFC_BSG_VENDOR_GET_TRUNK_INFO:
5825
+ rc = lpfc_get_trunk_info(job);
5826
+ break;
53615827 default:
53625828 rc = -EINVAL;
53635829 bsg_reply->reply_payload_rcv_len = 0;
....@@ -5371,7 +5837,7 @@
53715837
53725838 /**
53735839 * lpfc_bsg_request - handle a bsg request from the FC transport
5374
- * @job: fc_bsg_job to handle
5840
+ * @job: bsg_job to handle
53755841 **/
53765842 int
53775843 lpfc_bsg_request(struct bsg_job *job)
....@@ -5405,7 +5871,7 @@
54055871
54065872 /**
54075873 * lpfc_bsg_timeout - handle timeout of a bsg request from the FC transport
5408
- * @job: fc_bsg_job that has timed out
5874
+ * @job: bsg_job that has timed out
54095875 *
54105876 * This function just aborts the job's IOCB. The aborted IOCB will return to
54115877 * the waiting function which will handle passing the error back to userspace