.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * FiberChannel transport specific attributes exported to sysfs. |
---|
3 | 4 | * |
---|
4 | 5 | * 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 | | - * |
---|
22 | 6 | * Copyright (C) 2004-2007 James Smart, Emulex Corporation |
---|
23 | 7 | * Rewrite for host, target, device, and remote port attributes, |
---|
24 | 8 | * statistics, and service functions... |
---|
25 | 9 | * Add vports, etc |
---|
26 | | - * |
---|
27 | 10 | */ |
---|
28 | 11 | #include <linux/module.h> |
---|
29 | 12 | #include <linux/init.h> |
---|
.. | .. |
---|
147 | 130 | { FCH_EVT_PORT_OFFLINE, "port_offline" }, |
---|
148 | 131 | { FCH_EVT_PORT_FABRIC, "port_fabric" }, |
---|
149 | 132 | { FCH_EVT_LINK_UNKNOWN, "link_unknown" }, |
---|
| 133 | + { FCH_EVT_LINK_FPIN, "link_FPIN" }, |
---|
150 | 134 | { FCH_EVT_VENDOR_UNIQUE, "vendor_unique" }, |
---|
151 | 135 | }; |
---|
152 | 136 | fc_enum_name_search(host_event_code, fc_host_event_code, |
---|
.. | .. |
---|
269 | 253 | { FC_PORTSPEED_25GBIT, "25 Gbit" }, |
---|
270 | 254 | { FC_PORTSPEED_64GBIT, "64 Gbit" }, |
---|
271 | 255 | { FC_PORTSPEED_128GBIT, "128 Gbit" }, |
---|
| 256 | + { FC_PORTSPEED_256GBIT, "256 Gbit" }, |
---|
272 | 257 | { FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" }, |
---|
273 | 258 | }; |
---|
274 | 259 | fc_bitfield_name_search(port_speed, fc_port_speed_names) |
---|
.. | .. |
---|
295 | 280 | { FC_PORT_ROLE_FCP_INITIATOR, "FCP Initiator" }, |
---|
296 | 281 | { FC_PORT_ROLE_IP_PORT, "IP Port" }, |
---|
297 | 282 | { 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" }, |
---|
298 | 286 | }; |
---|
299 | 287 | fc_bitfield_name_search(port_roles, fc_port_role_names) |
---|
300 | 288 | |
---|
.. | .. |
---|
523 | 511 | } |
---|
524 | 512 | EXPORT_SYMBOL(fc_get_event_number); |
---|
525 | 513 | |
---|
526 | | - |
---|
527 | 514 | /** |
---|
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. |
---|
529 | 517 | * @shost: host the event occurred on |
---|
530 | 518 | * @event_number: fc event number obtained from get_fc_event_number() |
---|
531 | 519 | * @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 |
---|
533 | 523 | * |
---|
534 | 524 | * Notes: |
---|
535 | 525 | * This routine assumes no locks are held on entry. |
---|
536 | 526 | */ |
---|
537 | 527 | 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) |
---|
540 | 531 | { |
---|
541 | 532 | struct sk_buff *skb; |
---|
542 | 533 | struct nlmsghdr *nlh; |
---|
.. | .. |
---|
545 | 536 | u32 len; |
---|
546 | 537 | int err; |
---|
547 | 538 | |
---|
| 539 | + if (!data_buf || data_len < 4) |
---|
| 540 | + data_len = 0; |
---|
| 541 | + |
---|
548 | 542 | if (!scsi_nl_sock) { |
---|
549 | 543 | err = -ENOENT; |
---|
550 | 544 | goto send_fail; |
---|
551 | 545 | } |
---|
552 | 546 | |
---|
553 | | - len = FC_NL_MSGALIGN(sizeof(*event)); |
---|
| 547 | + len = FC_NL_MSGALIGN(sizeof(*event) + data_len); |
---|
554 | 548 | |
---|
555 | 549 | skb = nlmsg_new(len, GFP_KERNEL); |
---|
556 | 550 | if (!skb) { |
---|
.. | .. |
---|
568 | 562 | INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC, |
---|
569 | 563 | FC_NL_ASYNC_EVENT, len); |
---|
570 | 564 | event->seconds = ktime_get_real_seconds(); |
---|
571 | | - event->vendor_id = 0; |
---|
| 565 | + event->vendor_id = vendor_id; |
---|
572 | 566 | event->host_no = shost->host_no; |
---|
573 | | - event->event_datalen = sizeof(u32); /* bytes */ |
---|
| 567 | + event->event_datalen = data_len; /* bytes */ |
---|
574 | 568 | event->event_num = event_number; |
---|
575 | 569 | event->event_code = event_code; |
---|
576 | | - event->event_data = event_data; |
---|
| 570 | + if (data_len) |
---|
| 571 | + memcpy(&event->event_data, data_buf, data_len); |
---|
577 | 572 | |
---|
578 | 573 | nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS, |
---|
579 | 574 | GFP_KERNEL); |
---|
.. | .. |
---|
586 | 581 | printk(KERN_WARNING |
---|
587 | 582 | "%s: Dropped Event : host %d %s data 0x%08x - err %d\n", |
---|
588 | 583 | __func__, shost->host_no, |
---|
589 | | - (name) ? name : "<unknown>", event_data, err); |
---|
| 584 | + (name) ? name : "<unknown>", |
---|
| 585 | + (data_len) ? *((u32 *)data_buf) : 0xFFFFFFFF, err); |
---|
590 | 586 | 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); |
---|
591 | 606 | } |
---|
592 | 607 | EXPORT_SYMBOL(fc_host_post_event); |
---|
593 | 608 | |
---|
594 | 609 | |
---|
595 | 610 | /** |
---|
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 |
---|
597 | 613 | * @shost: host the event occurred on |
---|
598 | 614 | * @event_number: fc event number obtained from get_fc_event_number() |
---|
599 | 615 | * @data_len: amount, in bytes, of vendor unique data |
---|
.. | .. |
---|
607 | 623 | fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number, |
---|
608 | 624 | u32 data_len, char * data_buf, u64 vendor_id) |
---|
609 | 625 | { |
---|
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); |
---|
657 | 628 | } |
---|
658 | 629 | EXPORT_SYMBOL(fc_host_post_vendor_event); |
---|
659 | 630 | |
---|
| 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); |
---|
660 | 647 | |
---|
661 | 648 | |
---|
662 | 649 | static __init int fc_transport_init(void) |
---|
.. | .. |
---|
3592 | 3579 | |
---|
3593 | 3580 | /* the blk_end_sync_io() doesn't check the error */ |
---|
3594 | 3581 | if (inflight) |
---|
3595 | | - __blk_complete_request(req); |
---|
| 3582 | + blk_mq_end_request(req, BLK_STS_IOERR); |
---|
3596 | 3583 | return BLK_EH_DONE; |
---|
3597 | 3584 | } |
---|
3598 | 3585 | |
---|
.. | .. |
---|
3684 | 3671 | fc_bsg_goose_queue(struct fc_rport *rport) |
---|
3685 | 3672 | { |
---|
3686 | 3673 | struct request_queue *q = rport->rqst_q; |
---|
3687 | | - unsigned long flags; |
---|
3688 | 3674 | |
---|
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); |
---|
3695 | 3677 | } |
---|
3696 | 3678 | |
---|
3697 | 3679 | /** |
---|
.. | .. |
---|
3759 | 3741 | return fc_bsg_host_dispatch(shost, job); |
---|
3760 | 3742 | } |
---|
3761 | 3743 | |
---|
| 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 | + |
---|
3762 | 3775 | /** |
---|
3763 | 3776 | * fc_bsg_hostadd - Create and add the bsg hooks so we can receive requests |
---|
3764 | 3777 | * @shost: shost for fc_host |
---|
.. | .. |
---|
3780 | 3793 | snprintf(bsg_name, sizeof(bsg_name), |
---|
3781 | 3794 | "fc_host%d", shost->host_no); |
---|
3782 | 3795 | |
---|
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); |
---|
3784 | 3798 | if (IS_ERR(q)) { |
---|
3785 | 3799 | dev_err(dev, |
---|
3786 | 3800 | "fc_host%d: bsg interface failed to initialize - setup queue\n", |
---|
.. | .. |
---|
3788 | 3802 | return PTR_ERR(q); |
---|
3789 | 3803 | } |
---|
3790 | 3804 | __scsi_init_queue(shost, q); |
---|
3791 | | - blk_queue_rq_timed_out(q, fc_bsg_job_timeout); |
---|
3792 | 3805 | blk_queue_rq_timeout(q, FC_DEFAULT_BSG_TIMEOUT); |
---|
3793 | 3806 | fc_host->rqst_q = q; |
---|
3794 | 3807 | 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; |
---|
3809 | 3808 | } |
---|
3810 | 3809 | |
---|
3811 | 3810 | /** |
---|
.. | .. |
---|
3825 | 3824 | if (!i->f->bsg_request) |
---|
3826 | 3825 | return -ENOTSUPP; |
---|
3827 | 3826 | |
---|
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); |
---|
3830 | 3829 | if (IS_ERR(q)) { |
---|
3831 | 3830 | dev_err(dev, "failed to setup bsg queue\n"); |
---|
3832 | 3831 | return PTR_ERR(q); |
---|
3833 | 3832 | } |
---|
3834 | 3833 | __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); |
---|
3837 | 3834 | blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT); |
---|
3838 | 3835 | rport->rqst_q = q; |
---|
3839 | 3836 | return 0; |
---|
.. | .. |
---|
3852 | 3849 | static void |
---|
3853 | 3850 | fc_bsg_remove(struct request_queue *q) |
---|
3854 | 3851 | { |
---|
3855 | | - if (q) { |
---|
3856 | | - bsg_unregister_queue(q); |
---|
3857 | | - blk_cleanup_queue(q); |
---|
3858 | | - } |
---|
| 3852 | + bsg_remove_queue(q); |
---|
3859 | 3853 | } |
---|
3860 | 3854 | |
---|
3861 | 3855 | |
---|