diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_fc.c')
| -rw-r--r-- | drivers/scsi/scsi_transport_fc.c | 147 |
1 files changed, 77 insertions, 70 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index f59d4a05ecd..521f5838594 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -35,7 +35,6 @@ #include <scsi/scsi_transport.h> #include <scsi/scsi_transport_fc.h> #include <scsi/scsi_cmnd.h> -#include <linux/netlink.h> #include <net/netlink.h> #include <scsi/scsi_netlink_fc.h> #include <scsi/scsi_bsg_fc.h> @@ -262,6 +261,7 @@ static const struct { { FC_PORTSPEED_10GBIT, "10 Gbit" }, { FC_PORTSPEED_8GBIT, "8 Gbit" }, { FC_PORTSPEED_16GBIT, "16 Gbit" }, + { FC_PORTSPEED_32GBIT, "32 Gbit" }, { FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" }, }; fc_bitfield_name_search(port_speed, fc_port_speed_names) @@ -313,7 +313,7 @@ static void fc_scsi_scan_rport(struct work_struct *work); #define FC_STARGET_NUM_ATTRS 3 #define FC_RPORT_NUM_ATTRS 10 #define FC_VPORT_NUM_ATTRS 9 -#define FC_HOST_NUM_ATTRS 22 +#define FC_HOST_NUM_ATTRS 29 struct fc_internal { struct scsi_transport_template t; @@ -399,6 +399,20 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, fc_host->max_npiv_vports = 0; memset(fc_host->serial_number, 0, sizeof(fc_host->serial_number)); + memset(fc_host->manufacturer, 0, + sizeof(fc_host->manufacturer)); + memset(fc_host->model, 0, + sizeof(fc_host->model)); + memset(fc_host->model_description, 0, + sizeof(fc_host->model_description)); + memset(fc_host->hardware_version, 0, + sizeof(fc_host->hardware_version)); + memset(fc_host->driver_version, 0, + sizeof(fc_host->driver_version)); + memset(fc_host->firmware_version, 0, + sizeof(fc_host->firmware_version)); + memset(fc_host->optionrom_version, 0, + sizeof(fc_host->optionrom_version)); fc_host->port_id = -1; fc_host->port_type = FC_PORTTYPE_UNKNOWN; @@ -422,7 +436,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, snprintf(fc_host->work_q_name, sizeof(fc_host->work_q_name), "fc_wq_%d", shost->host_no); - fc_host->work_q = alloc_workqueue(fc_host->work_q_name, 0, 0); + fc_host->work_q = alloc_workqueue("%s", 0, 0, fc_host->work_q_name); if (!fc_host->work_q) return -ENOMEM; @@ -430,8 +444,8 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, snprintf(fc_host->devloss_work_q_name, sizeof(fc_host->devloss_work_q_name), "fc_dl_%d", shost->host_no); - fc_host->devloss_work_q = - alloc_workqueue(fc_host->devloss_work_q_name, 0, 0); + fc_host->devloss_work_q = alloc_workqueue("%s", 0, 0, + fc_host->devloss_work_q_name); if (!fc_host->devloss_work_q) { destroy_workqueue(fc_host->work_q); fc_host->work_q = NULL; @@ -520,7 +534,7 @@ fc_host_post_event(struct Scsi_Host *shost, u32 event_number, struct nlmsghdr *nlh; struct fc_nl_event *event; const char *name; - u32 len, skblen; + u32 len; int err; if (!scsi_nl_sock) { @@ -529,21 +543,19 @@ fc_host_post_event(struct Scsi_Host *shost, u32 event_number, } len = FC_NL_MSGALIGN(sizeof(*event)); - skblen = NLMSG_SPACE(len); - skb = alloc_skb(skblen, GFP_KERNEL); + skb = nlmsg_new(len, GFP_KERNEL); if (!skb) { err = -ENOBUFS; goto send_fail; } - nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, - skblen - sizeof(*nlh), 0); + nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, len, 0); if (!nlh) { err = -ENOBUFS; goto send_fail_skb; } - event = NLMSG_DATA(nlh); + event = nlmsg_data(nlh); INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC, FC_NL_ASYNC_EVENT, len); @@ -590,7 +602,7 @@ fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number, struct sk_buff *skb; struct nlmsghdr *nlh; struct fc_nl_event *event; - u32 len, skblen; + u32 len; int err; if (!scsi_nl_sock) { @@ -599,21 +611,19 @@ fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number, } len = FC_NL_MSGALIGN(sizeof(*event) + data_len); - skblen = NLMSG_SPACE(len); - skb = alloc_skb(skblen, GFP_KERNEL); + skb = nlmsg_new(len, GFP_KERNEL); if (!skb) { err = -ENOBUFS; goto send_vendor_fail; } - nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, - skblen - sizeof(*nlh), 0); + nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, len, 0); if (!nlh) { err = -ENOBUFS; goto send_vendor_fail_skb; } - event = NLMSG_DATA(nlh); + event = nlmsg_data(nlh); INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC, FC_NL_ASYNC_EVENT, len); @@ -1513,6 +1523,13 @@ fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20, fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20); fc_private_host_rd_attr(max_npiv_vports, "%u\n", 20); fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1)); +fc_private_host_rd_attr(manufacturer, "%s\n", FC_SERIAL_NUMBER_SIZE + 1); +fc_private_host_rd_attr(model, "%s\n", FC_SYMBOLIC_NAME_SIZE + 1); +fc_private_host_rd_attr(model_description, "%s\n", FC_SYMBOLIC_NAME_SIZE + 1); +fc_private_host_rd_attr(hardware_version, "%s\n", FC_VERSION_STRING_SIZE + 1); +fc_private_host_rd_attr(driver_version, "%s\n", FC_VERSION_STRING_SIZE + 1); +fc_private_host_rd_attr(firmware_version, "%s\n", FC_VERSION_STRING_SIZE + 1); +fc_private_host_rd_attr(optionrom_version, "%s\n", FC_VERSION_STRING_SIZE + 1); /* Dynamic Host Attributes */ @@ -1723,6 +1740,15 @@ fc_host_statistic(fcp_output_requests); fc_host_statistic(fcp_control_requests); fc_host_statistic(fcp_input_megabytes); fc_host_statistic(fcp_output_megabytes); +fc_host_statistic(fcp_packet_alloc_failures); +fc_host_statistic(fcp_packet_aborts); +fc_host_statistic(fcp_frame_alloc_failures); +fc_host_statistic(fc_no_free_exch); +fc_host_statistic(fc_no_free_exch_xid); +fc_host_statistic(fc_xid_not_found); +fc_host_statistic(fc_xid_busy); +fc_host_statistic(fc_seq_not_found); +fc_host_statistic(fc_non_bls_resp); static ssize_t fc_reset_statistics(struct device *dev, struct device_attribute *attr, @@ -1763,6 +1789,15 @@ static struct attribute *fc_statistics_attrs[] = { &device_attr_host_fcp_control_requests.attr, &device_attr_host_fcp_input_megabytes.attr, &device_attr_host_fcp_output_megabytes.attr, + &device_attr_host_fcp_packet_alloc_failures.attr, + &device_attr_host_fcp_packet_aborts.attr, + &device_attr_host_fcp_frame_alloc_failures.attr, + &device_attr_host_fc_no_free_exch.attr, + &device_attr_host_fc_no_free_exch_xid.attr, + &device_attr_host_fc_xid_not_found.attr, + &device_attr_host_fc_xid_busy.attr, + &device_attr_host_fc_seq_not_found.attr, + &device_attr_host_fc_non_bls_resp.attr, &device_attr_host_reset_statistics.attr, NULL }; @@ -2208,6 +2243,13 @@ fc_attach_transport(struct fc_function_template *ft) SETUP_HOST_ATTRIBUTE_RD_NS(npiv_vports_inuse); } SETUP_HOST_ATTRIBUTE_RD(serial_number); + SETUP_HOST_ATTRIBUTE_RD(manufacturer); + SETUP_HOST_ATTRIBUTE_RD(model); + SETUP_HOST_ATTRIBUTE_RD(model_description); + SETUP_HOST_ATTRIBUTE_RD(hardware_version); + SETUP_HOST_ATTRIBUTE_RD(driver_version); + SETUP_HOST_ATTRIBUTE_RD(firmware_version); + SETUP_HOST_ATTRIBUTE_RD(optionrom_version); SETUP_HOST_ATTRIBUTE_RD(port_id); SETUP_HOST_ATTRIBUTE_RD(port_type); @@ -2449,11 +2491,9 @@ static void fc_terminate_rport_io(struct fc_rport *rport) i->f->terminate_rport_io(rport); /* - * must unblock to flush queued IO. The caller will have set - * the port_state or flags, so that fc_remote_port_chkready will - * fail IO. + * Must unblock to flush queued IO. scsi-ml will fail incoming reqs. */ - scsi_target_unblock(&rport->dev); + scsi_target_unblock(&rport->dev, SDEV_TRANSPORT_OFFLINE); } /** @@ -2509,6 +2549,7 @@ fc_rport_final_delete(struct work_struct *work) fc_flush_devloss(shost); if (!cancel_delayed_work(&rport->dev_loss_work)) fc_flush_devloss(shost); + cancel_work_sync(&rport->scan_work); spin_lock_irqsave(shost->host_lock, flags); rport->flags &= ~FC_RPORT_DEVLOSS_PENDING; } @@ -2780,17 +2821,20 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, FC_RPORT_DEVLOSS_PENDING | FC_RPORT_DEVLOSS_CALLBK_DONE); + spin_unlock_irqrestore(shost->host_lock, flags); + /* if target, initiate a scan */ if (rport->scsi_target_id != -1) { + scsi_target_unblock(&rport->dev, + SDEV_RUNNING); + spin_lock_irqsave(shost->host_lock, + flags); rport->flags |= FC_RPORT_SCAN_PENDING; scsi_queue_work(shost, &rport->scan_work); spin_unlock_irqrestore(shost->host_lock, flags); - scsi_target_unblock(&rport->dev); - } else - spin_unlock_irqrestore(shost->host_lock, - flags); + } fc_bsg_goose_queue(rport); @@ -2848,16 +2892,17 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, if (fci->f->dd_fcrport_size) memset(rport->dd_data, 0, fci->f->dd_fcrport_size); + spin_unlock_irqrestore(shost->host_lock, flags); + + if (ids->roles & FC_PORT_ROLE_FCP_TARGET) { + scsi_target_unblock(&rport->dev, SDEV_RUNNING); - if (rport->roles & FC_PORT_ROLE_FCP_TARGET) { /* initiate a scan of the target */ + spin_lock_irqsave(shost->host_lock, flags); rport->flags |= FC_RPORT_SCAN_PENDING; scsi_queue_work(shost, &rport->scan_work); spin_unlock_irqrestore(shost->host_lock, flags); - scsi_target_unblock(&rport->dev); - } else - spin_unlock_irqrestore(shost->host_lock, flags); - + } return rport; } } @@ -3055,12 +3100,12 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) /* ensure any stgt delete functions are done */ fc_flush_work(shost); + scsi_target_unblock(&rport->dev, SDEV_RUNNING); /* initiate a scan of the target */ spin_lock_irqsave(shost->host_lock, flags); rport->flags |= FC_RPORT_SCAN_PENDING; scsi_queue_work(shost, &rport->scan_work); spin_unlock_irqrestore(shost->host_lock, flags); - scsi_target_unblock(&rport->dev); } } EXPORT_SYMBOL(fc_remote_port_rolechg); @@ -3099,7 +3144,7 @@ fc_timeout_deleted_rport(struct work_struct *work) "blocked FC remote port time out: no longer" " a FCP target, removing starget\n"); spin_unlock_irqrestore(shost->host_lock, flags); - scsi_target_unblock(&rport->dev); + scsi_target_unblock(&rport->dev, SDEV_TRANSPORT_OFFLINE); fc_queue_work(shost, &rport->stgt_delete_work); return; } @@ -4098,45 +4143,7 @@ fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport *rport) static void fc_bsg_remove(struct request_queue *q) { - struct request *req; /* block request */ - int counts; /* totals for request_list count and starved */ - if (q) { - /* Stop taking in new requests */ - spin_lock_irq(q->queue_lock); - blk_stop_queue(q); - - /* drain all requests in the queue */ - while (1) { - /* need the lock to fetch a request - * this may fetch the same reqeust as the previous pass - */ - req = blk_fetch_request(q); - /* save requests in use and starved */ - counts = q->rq.count[0] + q->rq.count[1] + - q->rq.starved[0] + q->rq.starved[1]; - spin_unlock_irq(q->queue_lock); - /* any requests still outstanding? */ - if (counts == 0) - break; - - /* This may be the same req as the previous iteration, - * always send the blk_end_request_all after a prefetch. - * It is not okay to not end the request because the - * prefetch started the request. - */ - if (req) { - /* return -ENXIO to indicate that this queue is - * going away - */ - req->errors = -ENXIO; - blk_end_request_all(req, -ENXIO); - } - - msleep(200); /* allow bsg to possibly finish */ - spin_lock_irq(q->queue_lock); - } - bsg_unregister_queue(q); blk_cleanup_queue(q); } |
