hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/scsi/scsi_transport_fc.c
....@@ -1,29 +1,12 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * FiberChannel transport specific attributes exported to sysfs.
34 *
45 * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved.
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with this program; if not, write to the Free Software
18
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
- *
20
- * ========
21
- *
226 * Copyright (C) 2004-2007 James Smart, Emulex Corporation
237 * Rewrite for host, target, device, and remote port attributes,
248 * statistics, and service functions...
259 * Add vports, etc
26
- *
2710 */
2811 #include <linux/module.h>
2912 #include <linux/init.h>
....@@ -147,6 +130,7 @@
147130 { FCH_EVT_PORT_OFFLINE, "port_offline" },
148131 { FCH_EVT_PORT_FABRIC, "port_fabric" },
149132 { FCH_EVT_LINK_UNKNOWN, "link_unknown" },
133
+ { FCH_EVT_LINK_FPIN, "link_FPIN" },
150134 { FCH_EVT_VENDOR_UNIQUE, "vendor_unique" },
151135 };
152136 fc_enum_name_search(host_event_code, fc_host_event_code,
....@@ -269,6 +253,7 @@
269253 { FC_PORTSPEED_25GBIT, "25 Gbit" },
270254 { FC_PORTSPEED_64GBIT, "64 Gbit" },
271255 { FC_PORTSPEED_128GBIT, "128 Gbit" },
256
+ { FC_PORTSPEED_256GBIT, "256 Gbit" },
272257 { FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" },
273258 };
274259 fc_bitfield_name_search(port_speed, fc_port_speed_names)
....@@ -295,6 +280,9 @@
295280 { FC_PORT_ROLE_FCP_INITIATOR, "FCP Initiator" },
296281 { FC_PORT_ROLE_IP_PORT, "IP Port" },
297282 { FC_PORT_ROLE_FCP_DUMMY_INITIATOR, "FCP Dummy Initiator" },
283
+ { FC_PORT_ROLE_NVME_INITIATOR, "NVMe Initiator" },
284
+ { FC_PORT_ROLE_NVME_TARGET, "NVMe Target" },
285
+ { FC_PORT_ROLE_NVME_DISCOVERY, "NVMe Discovery" },
298286 };
299287 fc_bitfield_name_search(port_roles, fc_port_role_names)
300288
....@@ -523,20 +511,23 @@
523511 }
524512 EXPORT_SYMBOL(fc_get_event_number);
525513
526
-
527514 /**
528
- * fc_host_post_event - called to post an even on an fc_host.
515
+ * fc_host_post_fc_event - routine to do the work of posting an event
516
+ * on an fc_host.
529517 * @shost: host the event occurred on
530518 * @event_number: fc event number obtained from get_fc_event_number()
531519 * @event_code: fc_host event being posted
532
- * @event_data: 32bits of data for the event being posted
520
+ * @data_len: amount, in bytes, of event data
521
+ * @data_buf: pointer to event data
522
+ * @vendor_id: value for Vendor id
533523 *
534524 * Notes:
535525 * This routine assumes no locks are held on entry.
536526 */
537527 void
538
-fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
539
- enum fc_host_event_code event_code, u32 event_data)
528
+fc_host_post_fc_event(struct Scsi_Host *shost, u32 event_number,
529
+ enum fc_host_event_code event_code,
530
+ u32 data_len, char *data_buf, u64 vendor_id)
540531 {
541532 struct sk_buff *skb;
542533 struct nlmsghdr *nlh;
....@@ -545,12 +536,15 @@
545536 u32 len;
546537 int err;
547538
539
+ if (!data_buf || data_len < 4)
540
+ data_len = 0;
541
+
548542 if (!scsi_nl_sock) {
549543 err = -ENOENT;
550544 goto send_fail;
551545 }
552546
553
- len = FC_NL_MSGALIGN(sizeof(*event));
547
+ len = FC_NL_MSGALIGN(sizeof(*event) + data_len);
554548
555549 skb = nlmsg_new(len, GFP_KERNEL);
556550 if (!skb) {
....@@ -568,12 +562,13 @@
568562 INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,
569563 FC_NL_ASYNC_EVENT, len);
570564 event->seconds = ktime_get_real_seconds();
571
- event->vendor_id = 0;
565
+ event->vendor_id = vendor_id;
572566 event->host_no = shost->host_no;
573
- event->event_datalen = sizeof(u32); /* bytes */
567
+ event->event_datalen = data_len; /* bytes */
574568 event->event_num = event_number;
575569 event->event_code = event_code;
576
- event->event_data = event_data;
570
+ if (data_len)
571
+ memcpy(&event->event_data, data_buf, data_len);
577572
578573 nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS,
579574 GFP_KERNEL);
....@@ -586,14 +581,35 @@
586581 printk(KERN_WARNING
587582 "%s: Dropped Event : host %d %s data 0x%08x - err %d\n",
588583 __func__, shost->host_no,
589
- (name) ? name : "<unknown>", event_data, err);
584
+ (name) ? name : "<unknown>",
585
+ (data_len) ? *((u32 *)data_buf) : 0xFFFFFFFF, err);
590586 return;
587
+}
588
+EXPORT_SYMBOL(fc_host_post_fc_event);
589
+
590
+/**
591
+ * fc_host_post_event - called to post an even on an fc_host.
592
+ * @shost: host the event occurred on
593
+ * @event_number: fc event number obtained from get_fc_event_number()
594
+ * @event_code: fc_host event being posted
595
+ * @event_data: 32bits of data for the event being posted
596
+ *
597
+ * Notes:
598
+ * This routine assumes no locks are held on entry.
599
+ */
600
+void
601
+fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
602
+ enum fc_host_event_code event_code, u32 event_data)
603
+{
604
+ fc_host_post_fc_event(shost, event_number, event_code,
605
+ (u32)sizeof(u32), (char *)&event_data, 0);
591606 }
592607 EXPORT_SYMBOL(fc_host_post_event);
593608
594609
595610 /**
596
- * fc_host_post_vendor_event - called to post a vendor unique event on an fc_host
611
+ * fc_host_post_vendor_event - called to post a vendor unique event
612
+ * on an fc_host
597613 * @shost: host the event occurred on
598614 * @event_number: fc event number obtained from get_fc_event_number()
599615 * @data_len: amount, in bytes, of vendor unique data
....@@ -607,56 +623,27 @@
607623 fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
608624 u32 data_len, char * data_buf, u64 vendor_id)
609625 {
610
- struct sk_buff *skb;
611
- struct nlmsghdr *nlh;
612
- struct fc_nl_event *event;
613
- u32 len;
614
- int err;
615
-
616
- if (!scsi_nl_sock) {
617
- err = -ENOENT;
618
- goto send_vendor_fail;
619
- }
620
-
621
- len = FC_NL_MSGALIGN(sizeof(*event) + data_len);
622
-
623
- skb = nlmsg_new(len, GFP_KERNEL);
624
- if (!skb) {
625
- err = -ENOBUFS;
626
- goto send_vendor_fail;
627
- }
628
-
629
- nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, len, 0);
630
- if (!nlh) {
631
- err = -ENOBUFS;
632
- goto send_vendor_fail_skb;
633
- }
634
- event = nlmsg_data(nlh);
635
-
636
- INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,
637
- FC_NL_ASYNC_EVENT, len);
638
- event->seconds = ktime_get_real_seconds();
639
- event->vendor_id = vendor_id;
640
- event->host_no = shost->host_no;
641
- event->event_datalen = data_len; /* bytes */
642
- event->event_num = event_number;
643
- event->event_code = FCH_EVT_VENDOR_UNIQUE;
644
- memcpy(&event->event_data, data_buf, data_len);
645
-
646
- nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS,
647
- GFP_KERNEL);
648
- return;
649
-
650
-send_vendor_fail_skb:
651
- kfree_skb(skb);
652
-send_vendor_fail:
653
- printk(KERN_WARNING
654
- "%s: Dropped Event : host %d vendor_unique - err %d\n",
655
- __func__, shost->host_no, err);
656
- return;
626
+ fc_host_post_fc_event(shost, event_number, FCH_EVT_VENDOR_UNIQUE,
627
+ data_len, data_buf, vendor_id);
657628 }
658629 EXPORT_SYMBOL(fc_host_post_vendor_event);
659630
631
+/**
632
+ * fc_host_rcv_fpin - routine to process a received FPIN.
633
+ * @shost: host the FPIN was received on
634
+ * @fpin_len: length of FPIN payload, in bytes
635
+ * @fpin_buf: pointer to FPIN payload
636
+ *
637
+ * Notes:
638
+ * This routine assumes no locks are held on entry.
639
+ */
640
+void
641
+fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf)
642
+{
643
+ fc_host_post_fc_event(shost, fc_get_event_number(),
644
+ FCH_EVT_LINK_FPIN, fpin_len, fpin_buf, 0);
645
+}
646
+EXPORT_SYMBOL(fc_host_fpin_rcv);
660647
661648
662649 static __init int fc_transport_init(void)
....@@ -3592,7 +3579,7 @@
35923579
35933580 /* the blk_end_sync_io() doesn't check the error */
35943581 if (inflight)
3595
- __blk_complete_request(req);
3582
+ blk_mq_end_request(req, BLK_STS_IOERR);
35963583 return BLK_EH_DONE;
35973584 }
35983585
....@@ -3684,14 +3671,9 @@
36843671 fc_bsg_goose_queue(struct fc_rport *rport)
36853672 {
36863673 struct request_queue *q = rport->rqst_q;
3687
- unsigned long flags;
36883674
3689
- if (!q)
3690
- return;
3691
-
3692
- spin_lock_irqsave(q->queue_lock, flags);
3693
- blk_run_queue_async(q);
3694
- spin_unlock_irqrestore(q->queue_lock, flags);
3675
+ if (q)
3676
+ blk_mq_run_hw_queues(q, true);
36953677 }
36963678
36973679 /**
....@@ -3759,6 +3741,37 @@
37593741 return fc_bsg_host_dispatch(shost, job);
37603742 }
37613743
3744
+static blk_status_t fc_bsg_rport_prep(struct fc_rport *rport)
3745
+{
3746
+ if (rport->port_state == FC_PORTSTATE_BLOCKED &&
3747
+ !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT))
3748
+ return BLK_STS_RESOURCE;
3749
+
3750
+ if (rport->port_state != FC_PORTSTATE_ONLINE)
3751
+ return BLK_STS_IOERR;
3752
+
3753
+ return BLK_STS_OK;
3754
+}
3755
+
3756
+
3757
+static int fc_bsg_dispatch_prep(struct bsg_job *job)
3758
+{
3759
+ struct fc_rport *rport = fc_bsg_to_rport(job);
3760
+ blk_status_t ret;
3761
+
3762
+ ret = fc_bsg_rport_prep(rport);
3763
+ switch (ret) {
3764
+ case BLK_STS_OK:
3765
+ break;
3766
+ case BLK_STS_RESOURCE:
3767
+ return -EAGAIN;
3768
+ default:
3769
+ return -EIO;
3770
+ }
3771
+
3772
+ return fc_bsg_dispatch(job);
3773
+}
3774
+
37623775 /**
37633776 * fc_bsg_hostadd - Create and add the bsg hooks so we can receive requests
37643777 * @shost: shost for fc_host
....@@ -3780,7 +3793,8 @@
37803793 snprintf(bsg_name, sizeof(bsg_name),
37813794 "fc_host%d", shost->host_no);
37823795
3783
- q = bsg_setup_queue(dev, bsg_name, fc_bsg_dispatch, i->f->dd_bsg_size);
3796
+ q = bsg_setup_queue(dev, bsg_name, fc_bsg_dispatch, fc_bsg_job_timeout,
3797
+ i->f->dd_bsg_size);
37843798 if (IS_ERR(q)) {
37853799 dev_err(dev,
37863800 "fc_host%d: bsg interface failed to initialize - setup queue\n",
....@@ -3788,24 +3802,9 @@
37883802 return PTR_ERR(q);
37893803 }
37903804 __scsi_init_queue(shost, q);
3791
- blk_queue_rq_timed_out(q, fc_bsg_job_timeout);
37923805 blk_queue_rq_timeout(q, FC_DEFAULT_BSG_TIMEOUT);
37933806 fc_host->rqst_q = q;
37943807 return 0;
3795
-}
3796
-
3797
-static int fc_bsg_rport_prep(struct request_queue *q, struct request *req)
3798
-{
3799
- struct fc_rport *rport = dev_to_rport(q->queuedata);
3800
-
3801
- if (rport->port_state == FC_PORTSTATE_BLOCKED &&
3802
- !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT))
3803
- return BLKPREP_DEFER;
3804
-
3805
- if (rport->port_state != FC_PORTSTATE_ONLINE)
3806
- return BLKPREP_KILL;
3807
-
3808
- return BLKPREP_OK;
38093808 }
38103809
38113810 /**
....@@ -3825,15 +3824,13 @@
38253824 if (!i->f->bsg_request)
38263825 return -ENOTSUPP;
38273826
3828
- q = bsg_setup_queue(dev, dev_name(dev), fc_bsg_dispatch,
3829
- i->f->dd_bsg_size);
3827
+ q = bsg_setup_queue(dev, dev_name(dev), fc_bsg_dispatch_prep,
3828
+ fc_bsg_job_timeout, i->f->dd_bsg_size);
38303829 if (IS_ERR(q)) {
38313830 dev_err(dev, "failed to setup bsg queue\n");
38323831 return PTR_ERR(q);
38333832 }
38343833 __scsi_init_queue(shost, q);
3835
- blk_queue_prep_rq(q, fc_bsg_rport_prep);
3836
- blk_queue_rq_timed_out(q, fc_bsg_job_timeout);
38373834 blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
38383835 rport->rqst_q = q;
38393836 return 0;
....@@ -3852,10 +3849,7 @@
38523849 static void
38533850 fc_bsg_remove(struct request_queue *q)
38543851 {
3855
- if (q) {
3856
- bsg_unregister_queue(q);
3857
- blk_cleanup_queue(q);
3858
- }
3852
+ bsg_remove_queue(q);
38593853 }
38603854
38613855