diff options
Diffstat (limited to 'drivers/s390')
31 files changed, 729 insertions, 562 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index f401b4c38cfc..73cce3ecb97f 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -3041,7 +3041,8 @@ static blk_status_t do_dasd_request(struct blk_mq_hw_ctx *hctx, cqr->callback_data = req; cqr->status = DASD_CQR_FILLED; cqr->dq = dq; - req->completion_data = cqr; + *((struct dasd_ccw_req **) blk_mq_rq_to_pdu(req)) = cqr; + blk_mq_start_request(req); spin_lock(&block->queue_lock); list_add_tail(&cqr->blocklist, &block->ccw_queue); @@ -3060,19 +3061,20 @@ out: * * Return values: * BLK_EH_RESET_TIMER if the request should be left running - * BLK_EH_NOT_HANDLED if the request is handled or terminated + * BLK_EH_DONE if the request is handled or terminated * by the driver. */ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved) { - struct dasd_ccw_req *cqr = req->completion_data; struct dasd_block *block = req->q->queuedata; struct dasd_device *device; + struct dasd_ccw_req *cqr; unsigned long flags; int rc = 0; + cqr = *((struct dasd_ccw_req **) blk_mq_rq_to_pdu(req)); if (!cqr) - return BLK_EH_NOT_HANDLED; + return BLK_EH_DONE; spin_lock_irqsave(&cqr->dq->lock, flags); device = cqr->startdev ? cqr->startdev : block->base; @@ -3127,7 +3129,7 @@ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved) spin_unlock(&block->queue_lock); spin_unlock_irqrestore(&cqr->dq->lock, flags); - return rc ? BLK_EH_RESET_TIMER : BLK_EH_NOT_HANDLED; + return rc ? BLK_EH_RESET_TIMER : BLK_EH_DONE; } static int dasd_init_hctx(struct blk_mq_hw_ctx *hctx, void *data, @@ -3172,6 +3174,7 @@ static int dasd_alloc_queue(struct dasd_block *block) int rc; block->tag_set.ops = &dasd_mq_ops; + block->tag_set.cmd_size = sizeof(struct dasd_ccw_req *); block->tag_set.nr_hw_queues = DASD_NR_HW_QUEUES; block->tag_set.queue_depth = DASD_MAX_LCU_DEV * DASD_REQ_PER_DEV; block->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 7bdc6aaa0ba3..2016e0ed5865 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -18,7 +18,6 @@ #include <linux/fs.h> #include <linux/blkpg.h> #include <linux/slab.h> -#include <asm/compat.h> #include <asm/ccwdev.h> #include <asm/schid.h> #include <asm/cmb.h> diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index c33788a829c3..5cb80c645489 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -131,19 +131,6 @@ static const struct seq_operations dasd_devices_seq_ops = { .show = dasd_devices_show, }; -static int dasd_devices_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &dasd_devices_seq_ops); -} - -static const struct file_operations dasd_devices_file_ops = { - .owner = THIS_MODULE, - .open = dasd_devices_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - #ifdef CONFIG_DASD_PROFILE static int dasd_stats_all_block_on(void) { @@ -352,10 +339,10 @@ dasd_proc_init(void) dasd_proc_root_entry = proc_mkdir("dasd", NULL); if (!dasd_proc_root_entry) goto out_nodasd; - dasd_devices_entry = proc_create("devices", + dasd_devices_entry = proc_create_seq("devices", S_IFREG | S_IRUGO | S_IWUSR, dasd_proc_root_entry, - &dasd_devices_file_ops); + &dasd_devices_seq_ops); if (!dasd_devices_entry) goto out_nodevices; dasd_statistics_entry = proc_create("statistics", diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 0a312e450207..29024492b8ed 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -51,9 +51,16 @@ static size_t dcssblk_dax_copy_from_iter(struct dax_device *dax_dev, return copy_from_iter(addr, bytes, i); } +static size_t dcssblk_dax_copy_to_iter(struct dax_device *dax_dev, + pgoff_t pgoff, void *addr, size_t bytes, struct iov_iter *i) +{ + return copy_to_iter(addr, bytes, i); +} + static const struct dax_operations dcssblk_dax_ops = { .direct_access = dcssblk_dax_direct_access, .copy_from_iter = dcssblk_dax_copy_from_iter, + .copy_to_iter = dcssblk_dax_copy_to_iter, }; struct dcssblk_dev_info { diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 61822480a2a0..16a4e8528bbc 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c @@ -19,7 +19,6 @@ #include <linux/slab.h> #include <linux/types.h> -#include <asm/compat.h> #include <asm/ccwdev.h> #include <asm/cio.h> #include <asm/ebcdic.h> diff --git a/drivers/s390/char/sclp_ctl.c b/drivers/s390/char/sclp_ctl.c index a78cea0c3a09..248b5db3eaa8 100644 --- a/drivers/s390/char/sclp_ctl.c +++ b/drivers/s390/char/sclp_ctl.c @@ -14,7 +14,6 @@ #include <linux/init.h> #include <linux/ioctl.h> #include <linux/fs.h> -#include <asm/compat.h> #include <asm/sclp_ctl.h> #include <asm/sclp.h> diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c index faae30476f4b..32a14ee31c6b 100644 --- a/drivers/s390/char/tape_proc.c +++ b/drivers/s390/char/tape_proc.c @@ -105,29 +105,14 @@ static const struct seq_operations tape_proc_seq = { .show = tape_proc_show, }; -static int tape_proc_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &tape_proc_seq); -} - -static const struct file_operations tape_proc_ops = -{ - .owner = THIS_MODULE, - .open = tape_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - /* * Initialize procfs stuff on startup */ void tape_proc_init(void) { - tape_proc_devices = - proc_create("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, NULL, - &tape_proc_ops); + tape_proc_devices = proc_create_seq("tapedevices", + S_IFREG | S_IRUGO | S_IWUSR, NULL, &tape_proc_seq); if (tape_proc_devices == NULL) { return; } diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index 17e411c57576..948ce82a7725 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c @@ -23,7 +23,6 @@ #include <linux/mutex.h> #include <linux/cma.h> #include <linux/mm.h> -#include <asm/compat.h> #include <asm/cpcmd.h> #include <asm/debug.h> #include <asm/vmcp.h> diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index db9c854088bc..93b2862bd3fa 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -326,8 +326,7 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, if (num_devices < 1) return -EINVAL; - gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]), - GFP_KERNEL); + gdev = kzalloc(struct_size(gdev, cdev, num_devices), GFP_KERNEL); if (!gdev) return -ENOMEM; diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 0015729d917d..8d9f36625ba5 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c @@ -16,7 +16,6 @@ #include <linux/miscdevice.h> #include <linux/kernel_stat.h> -#include <asm/compat.h> #include <asm/cio.h> #include <asm/chsc.h> #include <asm/isc.h> diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 439991d71b14..4c14ce428e92 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -141,7 +141,7 @@ static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues) int i; for (i = 0; i < nr_queues; i++) { - q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL); + q = kmem_cache_zalloc(qdio_q_cache, GFP_KERNEL); if (!q) return -ENOMEM; @@ -456,7 +456,6 @@ int qdio_setup_irq(struct qdio_initialize *init_data) { struct ciw *ciw; struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data; - int rc; memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib)); memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag)); @@ -493,16 +492,14 @@ int qdio_setup_irq(struct qdio_initialize *init_data) ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_EQUEUE); if (!ciw) { DBF_ERROR("%4x NO EQ", irq_ptr->schid.sch_no); - rc = -EINVAL; - goto out_err; + return -EINVAL; } irq_ptr->equeue = *ciw; ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_AQUEUE); if (!ciw) { DBF_ERROR("%4x NO AQ", irq_ptr->schid.sch_no); - rc = -EINVAL; - goto out_err; + return -EINVAL; } irq_ptr->aqueue = *ciw; @@ -512,9 +509,6 @@ int qdio_setup_irq(struct qdio_initialize *init_data) init_data->cdev->handler = qdio_int_handler; spin_unlock_irq(get_ccwdev_lock(irq_ptr->cdev)); return 0; -out_err: - qdio_release_memory(irq_ptr); - return rc; } void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 02184cf35834..6a273c5ebca5 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -198,11 +198,18 @@ struct ap_message { */ static inline void ap_init_message(struct ap_message *ap_msg) { - ap_msg->psmid = 0; - ap_msg->length = 0; - ap_msg->rc = 0; - ap_msg->special = 0; - ap_msg->receive = NULL; + memset(ap_msg, 0, sizeof(*ap_msg)); +} + +/** + * ap_release_message() - Release ap_message. + * Releases all memory used internal within the ap_message struct + * Currently this is the message and private field. + */ +static inline void ap_release_message(struct ap_message *ap_msg) +{ + kzfree(ap_msg->message); + kzfree(ap_msg->private); } #define for_each_ap_card(_ac) \ diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 5efd84862ccb..febcdb5135bf 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -371,6 +371,7 @@ long zcrypt_send_cprb(struct ica_xcRB *xcRB) trace_s390_zcrypt_req(xcRB, TB_ZSECSENDCPRB); + ap_init_message(&ap_msg); rc = get_cprb_fc(xcRB, &ap_msg, &func_code, &domain); if (rc) goto out; @@ -425,6 +426,7 @@ long zcrypt_send_cprb(struct ica_xcRB *xcRB) spin_unlock(&zcrypt_list_lock); out: + ap_release_message(&ap_msg); trace_s390_zcrypt_rep(xcRB, func_code, rc, AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; @@ -468,6 +470,8 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) trace_s390_zcrypt_req(xcrb, TP_ZSENDEP11CPRB); + ap_init_message(&ap_msg); + target_num = (unsigned short) xcrb->targets_num; /* empty list indicates autoselect (all available targets) */ @@ -485,7 +489,7 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) if (copy_from_user(targets, uptr, target_num * sizeof(*targets))) { rc = -EFAULT; - goto out; + goto out_free; } } @@ -542,6 +546,7 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) out_free: kfree(targets); out: + ap_release_message(&ap_msg); trace_s390_zcrypt_rep(xcrb, func_code, rc, AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; @@ -559,6 +564,7 @@ static long zcrypt_rng(char *buffer) trace_s390_zcrypt_req(buffer, TP_HWRNGCPRB); + ap_init_message(&ap_msg); rc = get_rng_fc(&ap_msg, &func_code, &domain); if (rc) goto out; @@ -589,8 +595,10 @@ static long zcrypt_rng(char *buffer) pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, weight); spin_unlock(&zcrypt_list_lock); - if (!pref_zq) - return -ENODEV; + if (!pref_zq) { + rc = -ENODEV; + goto out; + } qid = pref_zq->queue->qid; rc = pref_zq->ops->rng(pref_zq, buffer, &ap_msg); @@ -600,6 +608,7 @@ static long zcrypt_rng(char *buffer) spin_unlock(&zcrypt_list_lock); out: + ap_release_message(&ap_msg); trace_s390_zcrypt_rep(buffer, func_code, rc, AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index f54bef4a928e..97d4bacbc442 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -1084,6 +1084,13 @@ out_free: return rc; } +/** + * Fetch function code from cprb. + * Extracting the fc requires to copy the cprb from userspace. + * So this function allocates memory and needs an ap_msg prepared + * by the caller with ap_init_message(). Also the caller has to + * make sure ap_release_message() is always called even on failure. + */ unsigned int get_cprb_fc(struct ica_xcRB *xcRB, struct ap_message *ap_msg, unsigned int *func_code, unsigned short **dom) @@ -1091,9 +1098,7 @@ unsigned int get_cprb_fc(struct ica_xcRB *xcRB, struct response_type resp_type = { .type = PCIXCC_RESPONSE_TYPE_XCRB, }; - int rc; - ap_init_message(ap_msg); ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); if (!ap_msg->message) return -ENOMEM; @@ -1101,17 +1106,10 @@ unsigned int get_cprb_fc(struct ica_xcRB *xcRB, ap_msg->psmid = (((unsigned long long) current->pid) << 32) + atomic_inc_return(&zcrypt_step); ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL); - if (!ap_msg->private) { - kzfree(ap_msg->message); + if (!ap_msg->private) return -ENOMEM; - } memcpy(ap_msg->private, &resp_type, sizeof(resp_type)); - rc = XCRB_msg_to_type6CPRB_msgX(ap_msg, xcRB, func_code, dom); - if (rc) { - kzfree(ap_msg->message); - kzfree(ap_msg->private); - } - return rc; + return XCRB_msg_to_type6CPRB_msgX(ap_msg, xcRB, func_code, dom); } /** @@ -1139,11 +1137,16 @@ static long zcrypt_msgtype6_send_cprb(struct zcrypt_queue *zq, /* Signal pending. */ ap_cancel_message(zq->queue, ap_msg); - kzfree(ap_msg->message); - kzfree(ap_msg->private); return rc; } +/** + * Fetch function code from ep11 cprb. + * Extracting the fc requires to copy the ep11 cprb from userspace. + * So this function allocates memory and needs an ap_msg prepared + * by the caller with ap_init_message(). Also the caller has to + * make sure ap_release_message() is always called even on failure. + */ unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb, struct ap_message *ap_msg, unsigned int *func_code) @@ -1151,9 +1154,7 @@ unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb, struct response_type resp_type = { .type = PCIXCC_RESPONSE_TYPE_EP11, }; - int rc; - ap_init_message(ap_msg); ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); if (!ap_msg->message) return -ENOMEM; @@ -1161,17 +1162,10 @@ unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb, ap_msg->psmid = (((unsigned long long) current->pid) << 32) + atomic_inc_return(&zcrypt_step); ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL); - if (!ap_msg->private) { - kzfree(ap_msg->message); + if (!ap_msg->private) return -ENOMEM; - } memcpy(ap_msg->private, &resp_type, sizeof(resp_type)); - rc = xcrb_msg_to_type6_ep11cprb_msgx(ap_msg, xcrb, func_code); - if (rc) { - kzfree(ap_msg->message); - kzfree(ap_msg->private); - } - return rc; + return xcrb_msg_to_type6_ep11cprb_msgx(ap_msg, xcrb, func_code); } /** @@ -1246,8 +1240,6 @@ static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_queue *zq, /* Signal pending. */ ap_cancel_message(zq->queue, ap_msg); - kzfree(ap_msg->message); - kzfree(ap_msg->private); return rc; } @@ -1258,7 +1250,6 @@ unsigned int get_rng_fc(struct ap_message *ap_msg, int *func_code, .type = PCIXCC_RESPONSE_TYPE_XCRB, }; - ap_init_message(ap_msg); ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); if (!ap_msg->message) return -ENOMEM; @@ -1266,10 +1257,8 @@ unsigned int get_rng_fc(struct ap_message *ap_msg, int *func_code, ap_msg->psmid = (((unsigned long long) current->pid) << 32) + atomic_inc_return(&zcrypt_step); ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL); - if (!ap_msg->private) { - kzfree(ap_msg->message); + if (!ap_msg->private) return -ENOMEM; - } memcpy(ap_msg->private, &resp_type, sizeof(resp_type)); rng_type6CPRB_msgX(ap_msg, ZCRYPT_RNG_BUFFER_SIZE, domain); @@ -1313,8 +1302,6 @@ static long zcrypt_msgtype6_rng(struct zcrypt_queue *zq, /* Signal pending. */ ap_cancel_message(zq->queue, ap_msg); - kzfree(ap_msg->message); - kzfree(ap_msg->private); return rc; } diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 0ee8f33efb54..2d9fe7e4ee40 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -1928,6 +1928,8 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char return -EINVAL; /* TODO: sanity checks */ card->portno = value; + if (card->dev) + card->dev->dev_port = card->portno; return count; @@ -2158,6 +2160,7 @@ lcs_new_device(struct ccwgroup_device *ccwgdev) card->dev = dev; card->dev->ml_priv = card; card->dev->netdev_ops = &lcs_netdev_ops; + card->dev->dev_port = card->portno; memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH); #ifdef CONFIG_IP_MULTICAST if (!lcs_check_multicast_support(card)) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 78b98b3e7efa..2a5fec55bf60 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -148,6 +148,7 @@ struct qeth_perf_stats { unsigned int tx_csum; unsigned int tx_lin; unsigned int tx_linfail; + unsigned int rx_csum; }; /* Routing stuff */ @@ -712,9 +713,6 @@ enum qeth_discipline_id { struct qeth_discipline { const struct device_type *devtype; - void (*start_poll)(struct ccw_device *, int, unsigned long); - qdio_handler_t *input_handler; - qdio_handler_t *output_handler; int (*process_rx_buffer)(struct qeth_card *card, int budget, int *done); int (*recover)(void *ptr); int (*setup) (struct ccwgroup_device *); @@ -780,9 +778,9 @@ struct qeth_card { struct qeth_card_options options; wait_queue_head_t wait_q; - spinlock_t vlanlock; spinlock_t mclock; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; + struct mutex vid_list_mutex; /* vid_list */ struct list_head vid_list; DECLARE_HASHTABLE(mac_htable, 4); DECLARE_HASHTABLE(ip_htable, 4); @@ -867,6 +865,32 @@ static inline int qeth_get_ip_version(struct sk_buff *skb) } } +static inline void qeth_rx_csum(struct qeth_card *card, struct sk_buff *skb, + u8 flags) +{ + if ((card->dev->features & NETIF_F_RXCSUM) && + (flags & QETH_HDR_EXT_CSUM_TRANSP_REQ)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + if (card->options.performance_stats) + card->perf_stats.rx_csum++; + } else { + skb->ip_summed = CHECKSUM_NONE; + } +} + +static inline void qeth_tx_csum(struct sk_buff *skb, u8 *flags, int ipv) +{ + *flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ; + if ((ipv == 4 && ip_hdr(skb)->protocol == IPPROTO_UDP) || + (ipv == 6 && ipv6_hdr(skb)->nexthdr == IPPROTO_UDP)) + *flags |= QETH_HDR_EXT_UDP; + if (ipv == 4) { + /* some HW requires combined L3+L4 csum offload: */ + *flags |= QETH_HDR_EXT_CSUM_HDR_REQ; + ip_hdr(skb)->check = 0; + } +} + static inline void qeth_put_buffer_pool_entry(struct qeth_card *card, struct qeth_buffer_pool_entry *entry) { @@ -879,6 +903,27 @@ static inline int qeth_is_diagass_supported(struct qeth_card *card, return card->info.diagass_support & (__u32)cmd; } +int qeth_send_simple_setassparms_prot(struct qeth_card *card, + enum qeth_ipa_funcs ipa_func, + u16 cmd_code, long data, + enum qeth_prot_versions prot); +/* IPv4 variant */ +static inline int qeth_send_simple_setassparms(struct qeth_card *card, + enum qeth_ipa_funcs ipa_func, + u16 cmd_code, long data) +{ + return qeth_send_simple_setassparms_prot(card, ipa_func, cmd_code, + data, QETH_PROT_IPV4); +} + +static inline int qeth_send_simple_setassparms_v6(struct qeth_card *card, + enum qeth_ipa_funcs ipa_func, + u16 cmd_code, long data) +{ + return qeth_send_simple_setassparms_prot(card, ipa_func, cmd_code, + data, QETH_PROT_IPV6); +} + extern struct qeth_discipline qeth_l2_discipline; extern struct qeth_discipline qeth_l3_discipline; extern const struct attribute_group *qeth_generic_attr_groups[]; @@ -921,13 +966,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *, struct qeth_qdio_buffer *, struct qdio_buffer_element **, int *, struct qeth_hdr **); void qeth_schedule_recovery(struct qeth_card *); -void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long); int qeth_poll(struct napi_struct *napi, int budget); -void qeth_qdio_input_handler(struct ccw_device *, - unsigned int, unsigned int, int, - int, unsigned long); -void qeth_qdio_output_handler(struct ccw_device *, unsigned int, - int, int, int, unsigned long); void qeth_clear_ipacmd_list(struct qeth_card *); int qeth_qdio_clear_card(struct qeth_card *, int); void qeth_clear_working_pool_list(struct qeth_card *); @@ -979,8 +1018,6 @@ int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot); void qeth_trace_features(struct qeth_card *); void qeth_close_dev(struct qeth_card *); -int qeth_send_simple_setassparms(struct qeth_card *, enum qeth_ipa_funcs, - __u16, long); int qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, __u16, long, int (*reply_cb)(struct qeth_card *, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index dffd820731f2..9f28b6f2efc4 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -10,6 +10,7 @@ #define KMSG_COMPONENT "qeth" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include <linux/compat.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/string.h> @@ -32,7 +33,6 @@ #include <asm/chpid.h> #include <asm/io.h> #include <asm/sysinfo.h> -#include <asm/compat.h> #include <asm/diag.h> #include <asm/cio.h> #include <asm/ccwdev.h> @@ -1467,13 +1467,13 @@ static int qeth_setup_card(struct qeth_card *card) card->lan_online = 0; card->read_or_write_problem = 0; card->dev = NULL; - spin_lock_init(&card->vlanlock); spin_lock_init(&card->mclock); spin_lock_init(&card->lock); spin_lock_init(&card->ip_lock); spin_lock_init(&card->thread_mask_lock); mutex_init(&card->conf_mutex); mutex_init(&card->discipline_mutex); + mutex_init(&card->vid_list_mutex); card->thread_start_mask = 0; card->thread_allowed_mask = 0; card->thread_running_mask = 0; @@ -3588,15 +3588,14 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) } } -void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue, - unsigned long card_ptr) +static void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue, + unsigned long card_ptr) { struct qeth_card *card = (struct qeth_card *)card_ptr; if (card->dev && (card->dev->flags & IFF_UP)) napi_schedule(&card->napi); } -EXPORT_SYMBOL_GPL(qeth_qdio_start_poll); int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq) { @@ -3698,9 +3697,10 @@ out: return; } -void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err, - unsigned int queue, int first_elem, int count, - unsigned long card_ptr) +static void qeth_qdio_input_handler(struct ccw_device *ccwdev, + unsigned int qdio_err, int queue, + int first_elem, int count, + unsigned long card_ptr) { struct qeth_card *card = (struct qeth_card *)card_ptr; @@ -3711,14 +3711,12 @@ void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err, qeth_qdio_cq_handler(card, qdio_err, queue, first_elem, count); else if (qdio_err) qeth_schedule_recovery(card); - - } -EXPORT_SYMBOL_GPL(qeth_qdio_input_handler); -void qeth_qdio_output_handler(struct ccw_device *ccwdev, - unsigned int qdio_error, int __queue, int first_element, - int count, unsigned long card_ptr) +static void qeth_qdio_output_handler(struct ccw_device *ccwdev, + unsigned int qdio_error, int __queue, + int first_element, int count, + unsigned long card_ptr) { struct qeth_card *card = (struct qeth_card *) card_ptr; struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue]; @@ -3787,7 +3785,6 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, card->perf_stats.outbound_handler_time += qeth_get_micros() - card->perf_stats.outbound_handler_start_time; } -EXPORT_SYMBOL_GPL(qeth_qdio_output_handler); /* We cannot use outbound queue 3 for unicast packets on HiperSockets */ static inline int qeth_cut_iqd_prio(struct qeth_card *card, int queue_num) @@ -4995,7 +4992,7 @@ static int qeth_qdio_establish(struct qeth_card *card) goto out_free_in_sbals; } for (i = 0; i < card->qdio.no_in_queues; ++i) - queue_start_poll[i] = card->discipline->start_poll; + queue_start_poll[i] = qeth_qdio_start_poll; qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll); @@ -5019,8 +5016,8 @@ static int qeth_qdio_establish(struct qeth_card *card) init_data.qib_param_field = qib_param_field; init_data.no_input_qs = card->qdio.no_in_queues; init_data.no_output_qs = card->qdio.no_out_queues; - init_data.input_handler = card->discipline->input_handler; - init_data.output_handler = card->discipline->output_handler; + init_data.input_handler = qeth_qdio_input_handler; + init_data.output_handler = qeth_qdio_output_handler; init_data.queue_start_poll_array = queue_start_poll; init_data.int_parm = (unsigned long) card; init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; @@ -5204,6 +5201,11 @@ retriable: rc = qeth_query_ipassists(card, QETH_PROT_IPV4); if (rc == -ENOMEM) goto out; + if (qeth_is_supported(card, IPA_IPV6)) { + rc = qeth_query_ipassists(card, QETH_PROT_IPV6); + if (rc == -ENOMEM) + goto out; + } if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) { rc = qeth_query_setadapterparms(card); if (rc < 0) { @@ -5511,26 +5513,26 @@ int qeth_send_setassparms(struct qeth_card *card, } EXPORT_SYMBOL_GPL(qeth_send_setassparms); -int qeth_send_simple_setassparms(struct qeth_card *card, - enum qeth_ipa_funcs ipa_func, - __u16 cmd_code, long data) +int qeth_send_simple_setassparms_prot(struct qeth_card *card, + enum qeth_ipa_funcs ipa_func, + u16 cmd_code, long data, + enum qeth_prot_versions prot) { int rc; int length = 0; struct qeth_cmd_buffer *iob; - QETH_CARD_TEXT(card, 4, "simassp4"); + QETH_CARD_TEXT_(card, 4, "simassp%i", prot); if (data) length = sizeof(__u32); - iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code, - length, QETH_PROT_IPV4); + iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code, length, prot); if (!iob) return -ENOMEM; rc = qeth_send_setassparms(card, iob, length, data, qeth_setassparms_cb, NULL); return rc; } -EXPORT_SYMBOL_GPL(qeth_send_simple_setassparms); +EXPORT_SYMBOL_GPL(qeth_send_simple_setassparms_prot); static void qeth_unregister_dbf_views(void) { @@ -6008,7 +6010,8 @@ static struct { {"tx lin"}, {"tx linfail"}, {"cq handler count"}, - {"cq handler time"} + {"cq handler time"}, + {"rx csum"} }; int qeth_core_get_sset_count(struct net_device *dev, int stringset) @@ -6070,6 +6073,7 @@ void qeth_core_get_ethtool_stats(struct net_device *dev, data[35] = card->perf_stats.tx_linfail; data[36] = card->perf_stats.cq_cnt; data[37] = card->perf_stats.cq_time; + data[38] = card->perf_stats.rx_csum; } EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats); @@ -6326,14 +6330,15 @@ static int qeth_ipa_checksum_run_cmd_cb(struct qeth_card *card, static int qeth_ipa_checksum_run_cmd(struct qeth_card *card, enum qeth_ipa_funcs ipa_func, __u16 cmd_code, long data, - struct qeth_checksum_cmd *chksum_cb) + struct qeth_checksum_cmd *chksum_cb, + enum qeth_prot_versions prot) { struct qeth_cmd_buffer *iob; int rc = -ENOMEM; QETH_CARD_TEXT(card, 4, "chkdocmd"); iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code, - sizeof(__u32), QETH_PROT_IPV4); + sizeof(__u32), prot); if (iob) rc = qeth_send_setassparms(card, iob, sizeof(__u32), data, qeth_ipa_checksum_run_cmd_cb, @@ -6341,16 +6346,17 @@ static int qeth_ipa_checksum_run_cmd(struct qeth_card *card, return rc; } -static int qeth_send_checksum_on(struct qeth_card *card, int cstype) +static int qeth_send_checksum_on(struct qeth_card *card, int cstype, + enum qeth_prot_versions prot) { - const __u32 required_features = QETH_IPA_CHECKSUM_IP_HDR | - QETH_IPA_CHECKSUM_UDP | - QETH_IPA_CHECKSUM_TCP; + u32 required_features = QETH_IPA_CHECKSUM_UDP | QETH_IPA_CHECKSUM_TCP; struct qeth_checksum_cmd chksum_cb; int rc; + if (prot == QETH_PROT_IPV4) + required_features |= QETH_IPA_CHECKSUM_IP_HDR; rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_START, 0, - &chksum_cb); + &chksum_cb, prot); if (!rc) { if ((required_features & chksum_cb.supported) != required_features) @@ -6362,37 +6368,42 @@ static int qeth_send_checksum_on(struct qeth_card *card, int cstype) QETH_CARD_IFNAME(card)); } if (rc) { - qeth_send_simple_setassparms(card, cstype, IPA_CMD_ASS_STOP, 0); + qeth_send_simple_setassparms_prot(card, cstype, + IPA_CMD_ASS_STOP, 0, prot); dev_warn(&card->gdev->dev, - "Starting HW checksumming for %s failed, using SW checksumming\n", - QETH_CARD_IFNAME(card)); + "Starting HW IPv%d checksumming for %s failed, using SW checksumming\n", + prot, QETH_CARD_IFNAME(card)); return rc; } rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_ENABLE, - chksum_cb.supported, &chksum_cb); + chksum_cb.supported, &chksum_cb, + prot); if (!rc) { if ((required_features & chksum_cb.enabled) != required_features) rc = -EIO; } if (rc) { - qeth_send_simple_setassparms(card, cstype, IPA_CMD_ASS_STOP, 0); + qeth_send_simple_setassparms_prot(card, cstype, + IPA_CMD_ASS_STOP, 0, prot); dev_warn(&card->gdev->dev, - "Enabling HW checksumming for %s failed, using SW checksumming\n", - QETH_CARD_IFNAME(card)); + "Enabling HW IPv%d checksumming for %s failed, using SW checksumming\n", + prot, QETH_CARD_IFNAME(card)); return rc; } - dev_info(&card->gdev->dev, "HW Checksumming (%sbound) enabled\n", - cstype == IPA_INBOUND_CHECKSUM ? "in" : "out"); + dev_info(&card->gdev->dev, "HW Checksumming (%sbound IPv%d) enabled\n", + cstype == IPA_INBOUND_CHECKSUM ? "in" : "out", prot); return 0; } -static int qeth_set_ipa_csum(struct qeth_card *card, int on, int cstype) +static int qeth_set_ipa_csum(struct qeth_card *card, bool on, int cstype, + enum qeth_prot_versions prot) { - int rc = (on) ? qeth_send_checksum_on(card, cstype) - : qeth_send_simple_setassparms(card, cstype, - IPA_CMD_ASS_STOP, 0); + int rc = (on) ? qeth_send_checksum_on(card, cstype, prot) + : qeth_send_simple_setassparms_prot(card, cstype, + IPA_CMD_ASS_STOP, 0, + prot); return rc ? -EIO : 0; } @@ -6419,8 +6430,31 @@ static int qeth_set_ipa_tso(struct qeth_card *card, int on) return rc; } -#define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO) +static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on) +{ + int rc_ipv4 = (on) ? -EOPNOTSUPP : 0; + int rc_ipv6; + + if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) + rc_ipv4 = qeth_set_ipa_csum(card, on, IPA_INBOUND_CHECKSUM, + QETH_PROT_IPV4); + if (!qeth_is_supported6(card, IPA_INBOUND_CHECKSUM_V6)) + /* no/one Offload Assist available, so the rc is trivial */ + return rc_ipv4; + rc_ipv6 = qeth_set_ipa_csum(card, on, IPA_INBOUND_CHECKSUM, + QETH_PROT_IPV6); + + if (on) + /* enable: success if any Assist is active */ + return (rc_ipv6) ? rc_ipv4 : 0; + + /* disable: failure if any Assist is still active */ + return (rc_ipv6) ? rc_ipv6 : rc_ipv4; +} + +#define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO | \ + NETIF_F_IPV6_CSUM) /** * qeth_recover_features() - Restore device features after recovery * @dev: the recovering net_device @@ -6455,16 +6489,19 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features) QETH_DBF_HEX(SETUP, 2, &features, sizeof(features)); if ((changed & NETIF_F_IP_CSUM)) { - rc = qeth_set_ipa_csum(card, - features & NETIF_F_IP_CSUM ? 1 : 0, - IPA_OUTBOUND_CHECKSUM); + rc = qeth_set_ipa_csum(card, features & NETIF_F_IP_CSUM, + IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV4); if (rc) changed ^= NETIF_F_IP_CSUM; } - if ((changed & NETIF_F_RXCSUM)) { - rc = qeth_set_ipa_csum(card, - features & NETIF_F_RXCSUM ? 1 : 0, - IPA_INBOUND_CHECKSUM); + if (changed & NETIF_F_IPV6_CSUM) { + rc = qeth_set_ipa_csum(card, features & NETIF_F_IPV6_CSUM, + IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV6); + if (rc) + changed ^= NETIF_F_IPV6_CSUM; + } + if (changed & NETIF_F_RXCSUM) { + rc = qeth_set_ipa_rx_csum(card, features & NETIF_F_RXCSUM); if (rc) changed ^= NETIF_F_RXCSUM; } @@ -6491,7 +6528,10 @@ netdev_features_t qeth_fix_features(struct net_device *dev, QETH_DBF_TEXT(SETUP, 2, "fixfeat"); if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) features &= ~NETIF_F_IP_CSUM; - if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) + if (!qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) + features &= ~NETIF_F_IPV6_CSUM; + if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM) && + !qeth_is_supported6(card, IPA_INBOUND_CHECKSUM_V6)) features &= ~NETIF_F_RXCSUM; if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) features &= ~NETIF_F_TSO; diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index f4d1ec0b8f5a..878e62f35169 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -246,6 +246,8 @@ enum qeth_ipa_funcs { IPA_QUERY_ARP_ASSIST = 0x00040000L, IPA_INBOUND_TSO = 0x00080000L, IPA_OUTBOUND_TSO = 0x00100000L, + IPA_INBOUND_CHECKSUM_V6 = 0x00400000L, + IPA_OUTBOUND_CHECKSUM_V6 = 0x00800000L, }; /* SETIP/DELIP IPA Command: ***************************************************/ diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index ae81534de912..c3f18afb368b 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -144,6 +144,8 @@ static ssize_t qeth_dev_portno_store(struct device *dev, goto out; } card->info.portno = portno; + if (card->dev) + card->dev->dev_port = portno; out: mutex_unlock(&card->conf_mutex); return rc ? rc : count; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index b8079f2a65b3..a7cb37da6a21 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -17,7 +17,6 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/etherdevice.h> -#include <linux/ip.h> #include <linux/list.h> #include <linux/hash.h> #include <linux/hashtable.h> @@ -195,23 +194,6 @@ static int qeth_l2_get_cast_type(struct qeth_card *card, struct sk_buff *skb) return RTN_UNSPEC; } -static void qeth_l2_hdr_csum(struct qeth_card *card, struct qeth_hdr *hdr, - struct sk_buff *skb) -{ - struct iphdr *iph = ip_hdr(skb); - - /* tcph->check contains already the pseudo hdr checksum - * so just set the header flags - */ - if (iph->protocol == IPPROTO_UDP) - hdr->hdr.l2.flags[1] |= QETH_HDR_EXT_UDP; - hdr->hdr.l2.flags[1] |= QETH_HDR_EXT_CSUM_TRANSP_REQ | - QETH_HDR_EXT_CSUM_HDR_REQ; - iph->check = 0; - if (card->options.performance_stats) - card->perf_stats.tx_csum++; -} - static void qeth_l2_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb, int cast_type, unsigned int data_len) { @@ -297,12 +279,13 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i, static void qeth_l2_process_vlans(struct qeth_card *card) { struct qeth_vlan_vid *id; + QETH_CARD_TEXT(card, 3, "L2prcvln"); - spin_lock_bh(&card->vlanlock); + mutex_lock(&card->vid_list_mutex); list_for_each_entry(id, &card->vid_list, list) { qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN); } - spin_unlock_bh(&card->vlanlock); + mutex_unlock(&card->vid_list_mutex); } static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, @@ -319,7 +302,7 @@ static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, QETH_CARD_TEXT(card, 3, "aidREC"); return 0; } - id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC); + id = kmalloc(sizeof(*id), GFP_KERNEL); if (id) { id->vid = vid; rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN); @@ -327,9 +310,9 @@ static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, kfree(id); return rc; } - spin_lock_bh(&card->vlanlock); + mutex_lock(&card->vid_list_mutex); list_add_tail(&id->list, &card->vid_list); - spin_unlock_bh(&card->vlanlock); + mutex_unlock(&card->vid_list_mutex); } else { return -ENOMEM; } @@ -348,7 +331,7 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, QETH_CARD_TEXT(card, 3, "kidREC"); return 0; } - spin_lock_bh(&card->vlanlock); + mutex_lock(&card->vid_list_mutex); list_for_each_entry(id, &card->vid_list, list) { if (id->vid == vid) { list_del(&id->list); @@ -356,7 +339,7 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, break; } } - spin_unlock_bh(&card->vlanlock); + mutex_unlock(&card->vid_list_mutex); if (tmpid) { rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN); kfree(tmpid); @@ -423,15 +406,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card, switch (hdr->hdr.l2.id) { case QETH_HEADER_TYPE_LAYER2: skb->protocol = eth_type_trans(skb, skb->dev); - if ((card->dev->features & NETIF_F_RXCSUM) - && ((hdr->hdr.l2.flags[1] & - (QETH_HDR_EXT_CSUM_HDR_REQ | - QETH_HDR_EXT_CSUM_TRANSP_REQ)) == - (QETH_HDR_EXT_CSUM_HDR_REQ | - QETH_HDR_EXT_CSUM_TRANSP_REQ))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; + qeth_rx_csum(card, skb, hdr->hdr.l2.flags[1]); if (skb->protocol == htons(ETH_P_802_2)) *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; len = skb->len; @@ -464,7 +439,6 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card, static int qeth_l2_request_initial_mac(struct qeth_card *card) { int rc = 0; - char vendor_pre[] = {0x02, 0x00, 0x00}; QETH_DBF_TEXT(SETUP, 2, "l2reqmac"); QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card)); @@ -484,16 +458,20 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) card->info.type == QETH_CARD_TYPE_OSX || card->info.guestlan) { rc = qeth_setadpparms_change_macaddr(card); - if (rc) { - QETH_DBF_MESSAGE(2, "couldn't get MAC address on " - "device %s: x%x\n", CARD_BUS_ID(card), rc); - QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc); - return rc; - } - } else { - eth_random_addr(card->dev->dev_addr); - memcpy(card->dev->dev_addr, vendor_pre, 3); + if (!rc) + goto out; + QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %s: x%x\n", + CARD_BUS_ID(card), rc); + QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc); + /* fall back once more: */ } + + /* some devices don't support a custom MAC address: */ + if (card->info.type == QETH_CARD_TYPE_OSM || + card->info.type == QETH_CARD_TYPE_OSX) + return (rc) ? rc : -EADDRNOTAVAIL; + eth_hw_addr_random(card->dev); + out: QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, card->dev->addr_len); return 0; @@ -685,7 +663,8 @@ out: } static int qeth_l2_xmit_osa(struct qeth_card *card, struct sk_buff *skb, - struct qeth_qdio_out_q *queue, int cast_type) + struct qeth_qdio_out_q *queue, int cast_type, + int ipv) { int push_len = sizeof(struct qeth_hdr); unsigned int elements, nr_frags; @@ -723,8 +702,11 @@ static int qeth_l2_xmit_osa(struct qeth_card *card, struct sk_buff *skb, hdr_elements = 1; } qeth_l2_fill_header(hdr, skb, cast_type, skb->len - push_len); - if (skb->ip_summed == CHECKSUM_PARTIAL) - qeth_l2_hdr_csum(card, hdr, skb); + if (skb->ip_summed == CHECKSUM_PARTIAL) { + qeth_tx_csum(skb, &hdr->hdr.l2.flags[1], ipv); + if (card->options.performance_stats) + card->perf_stats.tx_csum++; + } elements = qeth_get_elements_no(card, skb, hdr_elements, 0); if (!elements) { @@ -776,6 +758,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, { struct qeth_card *card = dev->ml_priv; int cast_type = qeth_l2_get_cast_type(card, skb); + int ipv = qeth_get_ip_version(skb); struct qeth_qdio_out_q *queue; int tx_bytes = skb->len; int rc; @@ -783,7 +766,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, if (card->qdio.do_prio_queueing || (cast_type && card->info.is_multicast_different)) queue = card->qdio.out_qs[qeth_get_priority_queue(card, skb, - qeth_get_ip_version(skb), cast_type)]; + ipv, cast_type)]; else queue = card->qdio.out_qs[card->qdio.default_out_queue]; @@ -806,7 +789,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, rc = qeth_l2_xmit_iqd(card, skb, queue, cast_type); break; default: - rc = qeth_l2_xmit_osa(card, skb, queue, cast_type); + rc = qeth_l2_xmit_osa(card, skb, queue, cast_type, ipv); } if (!rc) { @@ -983,6 +966,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) card->dev->mtu = card->info.initial_mtu; card->dev->min_mtu = 64; card->dev->max_mtu = ETH_MAX_MTU; + card->dev->dev_port = card->info.portno; card->dev->netdev_ops = &qeth_l2_netdev_ops; if (card->info.type == QETH_CARD_TYPE_OSN) { card->dev->ethtool_ops = &qeth_l2_osn_ops; @@ -1011,10 +995,15 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) card->dev->hw_features |= NETIF_F_IP_CSUM; card->dev->vlan_features |= NETIF_F_IP_CSUM; } - if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) { - card->dev->hw_features |= NETIF_F_RXCSUM; - card->dev->vlan_features |= NETIF_F_RXCSUM; - } + } + if (qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) { + card->dev->hw_features |= NETIF_F_IPV6_CSUM; + card->dev->vlan_features |= NETIF_F_IPV6_CSUM; + } + if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM) || + qeth_is_supported6(card, IPA_INBOUND_CHECKSUM_V6)) { + card->dev->hw_features |= NETIF_F_RXCSUM; + card->dev->vlan_features |= NETIF_F_RXCSUM; } card->info.broadcast_capable = 1; @@ -1315,9 +1304,6 @@ static int qeth_l2_control_event(struct qeth_card *card, struct qeth_discipline qeth_l2_discipline = { .devtype = &qeth_l2_devtype, - .start_poll = qeth_qdio_start_poll, - .input_handler = (qdio_handler_t *) qeth_qdio_input_handler, - .output_handler = (qdio_handler_t *) qeth_qdio_output_handler, .process_rx_buffer = qeth_l2_process_inbound_buffer, .recover = qeth_l2_recover, .setup = qeth_l2_probe_device, diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index c1a16a74aa83..e7fa479adf47 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -735,22 +735,6 @@ static int qeth_l3_setadapter_parms(struct qeth_card *card) return rc; } -static int qeth_l3_send_simple_setassparms_ipv6(struct qeth_card *card, - enum qeth_ipa_funcs ipa_func, __u16 cmd_code) -{ - int rc; - struct qeth_cmd_buffer *iob; - - QETH_CARD_TEXT(card, 4, "simassp6"); - iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code, - 0, QETH_PROT_IPV6); - if (!iob) - return -ENOMEM; - rc = qeth_send_setassparms(card, iob, 0, 0, - qeth_setassparms_cb, NULL); - return rc; -} - static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card) { int rc; @@ -851,14 +835,6 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card) QETH_CARD_TEXT(card, 3, "softipv6"); - rc = qeth_query_ipassists(card, QETH_PROT_IPV6); - if (rc) { - dev_err(&card->gdev->dev, - "Activating IPv6 support for %s failed\n", - QETH_CARD_IFNAME(card)); - return rc; - } - if (card->info.type == QETH_CARD_TYPE_IQD) goto out; @@ -870,16 +846,16 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card) QETH_CARD_IFNAME(card)); return rc; } - rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_IPV6, - IPA_CMD_ASS_START); + rc = qeth_send_simple_setassparms_v6(card, IPA_IPV6, + IPA_CMD_ASS_START, 0); if (rc) { dev_err(&card->gdev->dev, "Activating IPv6 support for %s failed\n", QETH_CARD_IFNAME(card)); return rc; } - rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_PASSTHRU, - IPA_CMD_ASS_START); + rc = qeth_send_simple_setassparms_v6(card, IPA_PASSTHRU, + IPA_CMD_ASS_START, 0); if (rc) { dev_warn(&card->gdev->dev, "Enabling the passthrough mode for %s failed\n", @@ -1293,91 +1269,6 @@ static void qeth_l3_add_multicast_ipv6(struct qeth_card *card) in6_dev_put(in6_dev); } -static void qeth_l3_free_vlan_addresses4(struct qeth_card *card, - unsigned short vid) -{ - struct in_device *in_dev; - struct in_ifaddr *ifa; - struct qeth_ipaddr *addr; - struct net_device *netdev; - - QETH_CARD_TEXT(card, 4, "frvaddr4"); - - netdev = __vlan_find_dev_deep_rcu(card->dev, htons(ETH_P_8021Q), vid); - if (!netdev) - return; - in_dev = in_dev_get(netdev); - if (!in_dev) - return; - - addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); - if (!addr) - goto out; - - spin_lock_bh(&card->ip_lock); - - for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { - addr->u.a4.addr = be32_to_cpu(ifa->ifa_address); - addr->u.a4.mask = be32_to_cpu(ifa->ifa_mask); - addr->type = QETH_IP_TYPE_NORMAL; - qeth_l3_delete_ip(card, addr); - } - - spin_unlock_bh(&card->ip_lock); - - kfree(addr); -out: - in_dev_put(in_dev); -} - -static void qeth_l3_free_vlan_addresses6(struct qeth_card *card, - unsigned short vid) -{ - struct inet6_dev *in6_dev; - struct inet6_ifaddr *ifa; - struct qeth_ipaddr *addr; - struct net_device *netdev; - - QETH_CARD_TEXT(card, 4, "frvaddr6"); - - netdev = __vlan_find_dev_deep_rcu(card->dev, htons(ETH_P_8021Q), vid); - if (!netdev) - return; - - in6_dev = in6_dev_get(netdev); - if (!in6_dev) - return; - - addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6); - if (!addr) - goto out; - - spin_lock_bh(&card->ip_lock); - - list_for_each_entry(ifa, &in6_dev->addr_list, if_list) { - memcpy(&addr->u.a6.addr, &ifa->addr, - sizeof(struct in6_addr)); - addr->u.a6.pfxlen = ifa->prefix_len; - addr->type = QETH_IP_TYPE_NORMAL; - qeth_l3_delete_ip(card, addr); - } - - spin_unlock_bh(&card->ip_lock); - - kfree(addr); -out: - in6_dev_put(in6_dev); -} - -static void qeth_l3_free_vlan_addresses(struct qeth_card *card, - unsigned short vid) -{ - rcu_read_lock(); - qeth_l3_free_vlan_addresses4(card, vid); - qeth_l3_free_vlan_addresses6(card, vid); - rcu_read_unlock(); -} - static int qeth_l3_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid) { @@ -1398,8 +1289,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev, QETH_CARD_TEXT(card, 3, "kidREC"); return 0; } - /* unregister IP addresses of vlan device */ - qeth_l3_free_vlan_addresses(card, vid); clear_bit(vid, card->active_vlans); qeth_l3_set_rx_mode(dev); return 0; @@ -1454,17 +1343,7 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tag); } - if (card->dev->features & NETIF_F_RXCSUM) { - if ((hdr->hdr.l3.ext_flags & - (QETH_HDR_EXT_CSUM_HDR_REQ | - QETH_HDR_EXT_CSUM_TRANSP_REQ)) == - (QETH_HDR_EXT_CSUM_HDR_REQ | - QETH_HDR_EXT_CSUM_TRANSP_REQ)) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - } else - skb->ip_summed = CHECKSUM_NONE; + qeth_rx_csum(card, skb, hdr->hdr.l3.ext_flags); } static int qeth_l3_process_inbound_buffer(struct qeth_card *card, @@ -2210,23 +2089,6 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, rcu_read_unlock(); } -static void qeth_l3_hdr_csum(struct qeth_card *card, struct qeth_hdr *hdr, - struct sk_buff *skb) -{ - struct iphdr *iph = ip_hdr(skb); - - /* tcph->check contains already the pseudo hdr checksum - * so just set the header flags - */ - if (iph->protocol == IPPROTO_UDP) - hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_UDP; - hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ | - QETH_HDR_EXT_CSUM_HDR_REQ; - iph->check = 0; - if (card->options.performance_stats) - card->perf_stats.tx_csum++; -} - static void qeth_tso_fill_header(struct qeth_card *card, struct qeth_hdr *qhdr, struct sk_buff *skb) { @@ -2418,8 +2280,11 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, } } - if (skb->ip_summed == CHECKSUM_PARTIAL) - qeth_l3_hdr_csum(card, hdr, new_skb); + if (new_skb->ip_summed == CHECKSUM_PARTIAL) { + qeth_tx_csum(new_skb, &hdr->hdr.l3.ext_flags, ipv); + if (card->options.performance_stats) + card->perf_stats.tx_csum++; + } } elements = use_tso ? @@ -2620,28 +2485,32 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) (card->info.link_type == QETH_LINK_TYPE_HSTR)) { pr_info("qeth_l3: ignoring TR device\n"); return -ENODEV; - } else { - card->dev = alloc_etherdev(0); - if (!card->dev) - return -ENODEV; - card->dev->netdev_ops = &qeth_l3_osa_netdev_ops; - - /*IPv6 address autoconfiguration stuff*/ - qeth_l3_get_unique_id(card); - if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD)) - card->dev->dev_id = card->info.unique_id & - 0xffff; - - card->dev->hw_features |= NETIF_F_SG; - card->dev->vlan_features |= NETIF_F_SG; - - if (!card->info.guestlan) { - card->dev->features |= NETIF_F_SG; - card->dev->hw_features |= NETIF_F_TSO | - NETIF_F_RXCSUM | NETIF_F_IP_CSUM; - card->dev->vlan_features |= NETIF_F_TSO | - NETIF_F_RXCSUM | NETIF_F_IP_CSUM; - } + } + + card->dev = alloc_etherdev(0); + if (!card->dev) + return -ENODEV; + card->dev->netdev_ops = &qeth_l3_osa_netdev_ops; + + /*IPv6 address autoconfiguration stuff*/ + qeth_l3_get_unique_id(card); + if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD)) + card->dev->dev_id = card->info.unique_id & 0xffff; + + card->dev->hw_features |= NETIF_F_SG; + card->dev->vlan_features |= NETIF_F_SG; + + if (!card->info.guestlan) { + card->dev->features |= NETIF_F_SG; + card->dev->hw_features |= NETIF_F_TSO | + NETIF_F_RXCSUM | NETIF_F_IP_CSUM; + card->dev->vlan_features |= NETIF_F_TSO | + NETIF_F_RXCSUM | NETIF_F_IP_CSUM; + } + + if (qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) { + card->dev->hw_features |= NETIF_F_IPV6_CSUM; + card->dev->vlan_features |= NETIF_F_IPV6_CSUM; } } else if (card->info.type == QETH_CARD_TYPE_IQD) { card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN, @@ -2663,6 +2532,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) card->dev->mtu = card->info.initial_mtu; card->dev->min_mtu = 64; card->dev->max_mtu = ETH_MAX_MTU; + card->dev->dev_port = card->info.portno; card->dev->ethtool_ops = &qeth_l3_ethtool_ops; card->dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | @@ -2960,9 +2830,6 @@ static int qeth_l3_control_event(struct qeth_card *card, struct qeth_discipline qeth_l3_discipline = { .devtype = &qeth_l3_devtype, - .start_poll = qeth_qdio_start_poll, - .input_handler = (qdio_handler_t *) qeth_qdio_input_handler, - .output_handler = (qdio_handler_t *) qeth_qdio_output_handler, .process_rx_buffer = qeth_l3_process_inbound_buffer, .recover = qeth_l3_recover, .setup = qeth_l3_probe_device, diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index a8b831000b2d..3b368fcf13f4 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -4,7 +4,7 @@ * * Debug traces for zfcp. * - * Copyright IBM Corp. 2002, 2017 + * Copyright IBM Corp. 2002, 2018 */ #define KMSG_COMPONENT "zfcp" @@ -285,6 +285,8 @@ void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter, struct list_head *entry; unsigned long flags; + lockdep_assert_held(&adapter->erp_lock); + if (unlikely(!debug_level_enabled(dbf->rec, level))) return; @@ -308,6 +310,27 @@ void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter, spin_unlock_irqrestore(&dbf->rec_lock, flags); } +/** + * zfcp_dbf_rec_trig_lock - trace event related to triggered recovery with lock + * @tag: identifier for event + * @adapter: adapter on which the erp_action should run + * @port: remote port involved in the erp_action + * @sdev: scsi device involved in the erp_action + * @want: wanted erp_action + * @need: required erp_action + * + * The adapter->erp_lock must not be held. + */ +void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter, + struct zfcp_port *port, struct scsi_device *sdev, + u8 want, u8 need) +{ + unsigned long flags; + + read_lock_irqsave(&adapter->erp_lock, flags); + zfcp_dbf_rec_trig(tag, adapter, port, sdev, want, need); + read_unlock_irqrestore(&adapter->erp_lock, flags); +} /** * zfcp_dbf_rec_run_lvl - trace event related to running recovery @@ -578,16 +601,18 @@ void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf) } /** - * zfcp_dbf_scsi - trace event for scsi commands - * @tag: identifier for event - * @sc: pointer to struct scsi_cmnd - * @fsf: pointer to struct zfcp_fsf_req + * zfcp_dbf_scsi_common() - Common trace event helper for scsi. + * @tag: Identifier for event. + * @level: trace level of event. + * @sdev: Pointer to SCSI device as context for this event. + * @sc: Pointer to SCSI command, or NULL with task management function (TMF). + * @fsf: Pointer to FSF request, or NULL. */ -void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc, - struct zfcp_fsf_req *fsf) +void zfcp_dbf_scsi_common(char *tag, int level, struct scsi_device *sdev, + struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf) { struct zfcp_adapter *adapter = - (struct zfcp_adapter *) sc->device->host->hostdata[0]; + (struct zfcp_adapter *) sdev->host->hostdata[0]; struct zfcp_dbf *dbf = adapter->dbf; struct zfcp_dbf_scsi *rec = &dbf->scsi_buf; struct fcp_resp_with_ext *fcp_rsp; @@ -599,16 +624,28 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc, memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); rec->id = ZFCP_DBF_SCSI_CMND; - rec->scsi_result = sc->result; - rec->scsi_retries = sc->retries; - rec->scsi_allowed = sc->allowed; - rec->scsi_id = sc->device->id; - rec->scsi_lun = (u32)sc->device->lun; - rec->scsi_lun_64_hi = (u32)(sc->device->lun >> 32); - rec->host_scribble = (unsigned long)sc->host_scribble; - - memcpy(rec->scsi_opcode, sc->cmnd, - min((int)sc->cmd_len, ZFCP_DBF_SCSI_OPCODE)); + if (sc) { + rec->scsi_result = sc->result; + rec->scsi_retries = sc->retries; + rec->scsi_allowed = sc->allowed; + rec->scsi_id = sc->device->id; + rec->scsi_lun = (u32)sc->device->lun; + rec->scsi_lun_64_hi = (u32)(sc->device->lun >> 32); + rec->host_scribble = (unsigned long)sc->host_scribble; + + memcpy(rec->scsi_opcode, sc->cmnd, + min_t(int, sc->cmd_len, ZFCP_DBF_SCSI_OPCODE)); + } else { + rec->scsi_result = ~0; + rec->scsi_retries = ~0; + rec->scsi_allowed = ~0; + rec->scsi_id = sdev->id; + rec->scsi_lun = (u32)sdev->lun; + rec->scsi_lun_64_hi = (u32)(sdev->lun >> 32); + rec->host_scribble = ~0; + + memset(rec->scsi_opcode, 0xff, ZFCP_DBF_SCSI_OPCODE); + } if (fsf) { rec->fsf_req_id = fsf->req_id; @@ -643,6 +680,46 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc, spin_unlock_irqrestore(&dbf->scsi_lock, flags); } +/** + * zfcp_dbf_scsi_eh() - Trace event for special cases of scsi_eh callbacks. + * @tag: Identifier for event. + * @adapter: Pointer to zfcp adapter as context for this event. + * @scsi_id: SCSI ID/target to indicate scope of task management function (TMF). + * @ret: Return value of calling function. + * + * This SCSI trace variant does not depend on any of: + * scsi_cmnd, zfcp_fsf_req, scsi_device. + */ +void zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter, + unsigned int scsi_id, int ret) +{ + struct zfcp_dbf *dbf = adapter->dbf; + struct zfcp_dbf_scsi *rec = &dbf->scsi_buf; + unsigned long flags; + static int const level = 1; + + if (unlikely(!debug_level_enabled(adapter->dbf->scsi, level))) + return; + + spin_lock_irqsave(&dbf->scsi_lock, flags); + memset(rec, 0, sizeof(*rec)); + + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + rec->id = ZFCP_DBF_SCSI_CMND; + rec->scsi_result = ret; /* re-use field, int is 4 bytes and fits */ + rec->scsi_retries = ~0; + rec->scsi_allowed = ~0; + rec->fcp_rsp_info = ~0; + rec->scsi_id = scsi_id; + rec->scsi_lun = (u32)ZFCP_DBF_INVALID_LUN; + rec->scsi_lun_64_hi = (u32)(ZFCP_DBF_INVALID_LUN >> 32); + rec->host_scribble = ~0; + memset(rec->scsi_opcode, 0xff, ZFCP_DBF_SCSI_OPCODE); + + debug_event(dbf->scsi, level, rec, sizeof(*rec)); + spin_unlock_irqrestore(&dbf->scsi_lock, flags); +} + static debug_info_t *zfcp_dbf_reg(const char *name, int size, int rec_size) { struct debug_info *d; diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index e2a973cd2573..d116c07ed77a 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -359,7 +359,7 @@ void _zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *scmd, scmd->device->host->hostdata[0]; if (debug_level_enabled(adapter->dbf->scsi, level)) - zfcp_dbf_scsi(tag, level, scmd, req); + zfcp_dbf_scsi_common(tag, level, scmd->device, scmd, req); } /** @@ -402,16 +402,23 @@ void zfcp_dbf_scsi_abort(char *tag, struct scsi_cmnd *scmd, } /** - * zfcp_dbf_scsi_devreset - trace event for Logical Unit or Target Reset - * @tag: tag indicating success or failure of reset operation - * @scmnd: SCSI command which caused this error recovery - * @flag: indicates type of reset (Target Reset, Logical Unit Reset) + * zfcp_dbf_scsi_devreset() - Trace event for Logical Unit or Target Reset. + * @tag: Tag indicating success or failure of reset operation. + * @sdev: Pointer to SCSI device as context for this event. + * @flag: Indicates type of reset (Target Reset, Logical Unit Reset). + * @fsf_req: Pointer to FSF request representing the TMF, or NULL. */ static inline -void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag, +void zfcp_dbf_scsi_devreset(char *tag, struct scsi_device *sdev, u8 flag, struct zfcp_fsf_req *fsf_req) { + struct zfcp_adapter *adapter = (struct zfcp_adapter *) + sdev->host->hostdata[0]; char tmp_tag[ZFCP_DBF_TAG_LEN]; + static int const level = 1; + + if (unlikely(!debug_level_enabled(adapter->dbf->scsi, level))) + return; if (flag == FCP_TMF_TGT_RESET) memcpy(tmp_tag, "tr_", 3); @@ -419,7 +426,7 @@ void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag, memcpy(tmp_tag, "lr_", 3); memcpy(&tmp_tag[3], tag, 4); - _zfcp_dbf_scsi(tmp_tag, 1, scmnd, fsf_req); + zfcp_dbf_scsi_common(tmp_tag, level, sdev, NULL, fsf_req); } /** diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 1d91a32db08e..e7e6b63905e2 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -19,7 +19,6 @@ enum zfcp_erp_act_flags { ZFCP_STATUS_ERP_TIMEDOUT = 0x10000000, ZFCP_STATUS_ERP_CLOSE_ONLY = 0x01000000, - ZFCP_STATUS_ERP_DISMISSING = 0x00100000, ZFCP_STATUS_ERP_DISMISSED = 0x00200000, ZFCP_STATUS_ERP_LOWMEM = 0x00400000, ZFCP_STATUS_ERP_NO_REF = 0x00800000, @@ -27,7 +26,6 @@ enum zfcp_erp_act_flags { enum zfcp_erp_steps { ZFCP_ERP_STEP_UNINITIALIZED = 0x0000, - ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001, ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, ZFCP_ERP_STEP_PORT_OPENING = 0x0800, @@ -35,16 +33,28 @@ enum zfcp_erp_steps { ZFCP_ERP_STEP_LUN_OPENING = 0x2000, }; +/** + * enum zfcp_erp_act_type - Type of ERP action object. + * @ZFCP_ERP_ACTION_REOPEN_LUN: LUN recovery. + * @ZFCP_ERP_ACTION_REOPEN_PORT: Port recovery. + * @ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: Forced port recovery. + * @ZFCP_ERP_ACTION_REOPEN_ADAPTER: Adapter recovery. + * @ZFCP_ERP_ACTION_NONE: Eyecatcher pseudo flag to bitwise or-combine with + * either of the first four enum values. + * Used to indicate that an ERP action could not be + * set up despite a detected need for some recovery. + * @ZFCP_ERP_ACTION_FAILED: Eyecatcher pseudo flag to bitwise or-combine with + * either of the first four enum values. + * Used to indicate that ERP not needed because + * the object has ZFCP_STATUS_COMMON_ERP_FAILED. + */ enum zfcp_erp_act_type { ZFCP_ERP_ACTION_REOPEN_LUN = 1, ZFCP_ERP_ACTION_REOPEN_PORT = 2, ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, -}; - -enum zfcp_erp_act_state { - ZFCP_ERP_ACTION_RUNNING = 1, - ZFCP_ERP_ACTION_READY = 2, + ZFCP_ERP_ACTION_NONE = 0xc0, + ZFCP_ERP_ACTION_FAILED = 0xe0, }; enum zfcp_erp_act_result { @@ -62,14 +72,14 @@ static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask) ZFCP_STATUS_COMMON_UNBLOCKED | mask); } -static int zfcp_erp_action_exists(struct zfcp_erp_action *act) +static bool zfcp_erp_action_is_running(struct zfcp_erp_action *act) { struct zfcp_erp_action *curr_act; list_for_each_entry(curr_act, &act->adapter->erp_running_head, list) if (act == curr_act) - return ZFCP_ERP_ACTION_RUNNING; - return 0; + return true; + return false; } static void zfcp_erp_action_ready(struct zfcp_erp_action *act) @@ -85,7 +95,7 @@ static void zfcp_erp_action_ready(struct zfcp_erp_action *act) static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act) { act->status |= ZFCP_STATUS_ERP_DISMISSED; - if (zfcp_erp_action_exists(act) == ZFCP_ERP_ACTION_RUNNING) + if (zfcp_erp_action_is_running(act)) zfcp_erp_action_ready(act); } @@ -126,6 +136,49 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) } } +static int zfcp_erp_handle_failed(int want, struct zfcp_adapter *adapter, + struct zfcp_port *port, + struct scsi_device *sdev) +{ + int need = want; + struct zfcp_scsi_dev *zsdev; + + switch (want) { + case ZFCP_ERP_ACTION_REOPEN_LUN: + zsdev = sdev_to_zfcp(sdev); + if (atomic_read(&zsdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) + need = 0; + break; + case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: + if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) + need = 0; + break; + case ZFCP_ERP_ACTION_REOPEN_PORT: + if (atomic_read(&port->status) & + ZFCP_STATUS_COMMON_ERP_FAILED) { + need = 0; + /* ensure propagation of failed status to new devices */ + zfcp_erp_set_port_status( + port, ZFCP_STATUS_COMMON_ERP_FAILED); + } + break; + case ZFCP_ERP_ACTION_REOPEN_ADAPTER: + if (atomic_read(&adapter->status) & + ZFCP_STATUS_COMMON_ERP_FAILED) { + need = 0; + /* ensure propagation of failed status to new devices */ + zfcp_erp_set_adapter_status( + adapter, ZFCP_STATUS_COMMON_ERP_FAILED); + } + break; + default: + need = 0; + break; + } + + return need; +} + static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, struct zfcp_port *port, struct scsi_device *sdev) @@ -241,48 +294,70 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, return erp_action; } -static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, - struct zfcp_port *port, - struct scsi_device *sdev, - char *id, u32 act_status) +static void zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, + struct zfcp_port *port, + struct scsi_device *sdev, + char *id, u32 act_status) { - int retval = 1, need; + int need; struct zfcp_erp_action *act; - if (!adapter->erp_thread) - return -EIO; + need = zfcp_erp_handle_failed(want, adapter, port, sdev); + if (!need) { + need = ZFCP_ERP_ACTION_FAILED; /* marker for trace */ + goto out; + } + + if (!adapter->erp_thread) { + need = ZFCP_ERP_ACTION_NONE; /* marker for trace */ + goto out; + } need = zfcp_erp_required_act(want, adapter, port, sdev); if (!need) goto out; act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev); - if (!act) + if (!act) { + need |= ZFCP_ERP_ACTION_NONE; /* marker for trace */ goto out; + } atomic_or(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); ++adapter->erp_total_count; list_add_tail(&act->list, &adapter->erp_ready_head); wake_up(&adapter->erp_ready_wq); - retval = 0; out: zfcp_dbf_rec_trig(id, adapter, port, sdev, want, need); - return retval; } -static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, +void zfcp_erp_port_forced_no_port_dbf(char *id, struct zfcp_adapter *adapter, + u64 port_name, u32 port_id) +{ + unsigned long flags; + static /* don't waste stack */ struct zfcp_port tmpport; + + write_lock_irqsave(&adapter->erp_lock, flags); + /* Stand-in zfcp port with fields just good enough for + * zfcp_dbf_rec_trig() and zfcp_dbf_set_common(). + * Under lock because tmpport is static. + */ + atomic_set(&tmpport.status, -1); /* unknown */ + tmpport.wwpn = port_name; + tmpport.d_id = port_id; + zfcp_dbf_rec_trig(id, adapter, &tmpport, NULL, + ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, + ZFCP_ERP_ACTION_NONE); + write_unlock_irqrestore(&adapter->erp_lock, flags); +} + +static void _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask, char *id) { zfcp_erp_adapter_block(adapter, clear_mask); zfcp_scsi_schedule_rports_block(adapter); - /* ensure propagation of failed status to new devices */ - if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { - zfcp_erp_set_adapter_status(adapter, - ZFCP_STATUS_COMMON_ERP_FAILED); - return -EIO; - } - return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, - adapter, NULL, NULL, id, 0); + zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, + adapter, NULL, NULL, id, 0); } /** @@ -299,12 +374,8 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, char *id) zfcp_scsi_schedule_rports_block(adapter); write_lock_irqsave(&adapter->erp_lock, flags); - if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) - zfcp_erp_set_adapter_status(adapter, - ZFCP_STATUS_COMMON_ERP_FAILED); - else - zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, - NULL, NULL, id, 0); + zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, + NULL, NULL, id, 0); write_unlock_irqrestore(&adapter->erp_lock, flags); } @@ -345,9 +416,6 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); - if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) - return; - zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, port->adapter, port, NULL, id, 0); } @@ -368,19 +436,13 @@ void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id) write_unlock_irqrestore(&adapter->erp_lock, flags); } -static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) +static void _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) { zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); - if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { - /* ensure propagation of failed status to new devices */ - zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED); - return -EIO; - } - - return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, - port->adapter, port, NULL, id, 0); + zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, + port->adapter, port, NULL, id, 0); } /** @@ -388,20 +450,15 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) * @port: port to recover * @clear_mask: flags in port status to be cleared * @id: Id for debug trace event. - * - * Returns 0 if recovery has been triggered, < 0 if not. */ -int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) +void zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) { - int retval; unsigned long flags; struct zfcp_adapter *adapter = port->adapter; write_lock_irqsave(&adapter->erp_lock, flags); - retval = _zfcp_erp_port_reopen(port, clear, id); + _zfcp_erp_port_reopen(port, clear, id); write_unlock_irqrestore(&adapter->erp_lock, flags); - - return retval; } static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask) @@ -418,9 +475,6 @@ static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id, zfcp_erp_lun_block(sdev, clear); - if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) - return; - zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter, zfcp_sdev->port, sdev, id, act_status); } @@ -482,21 +536,23 @@ void zfcp_erp_lun_shutdown_wait(struct scsi_device *sdev, char *id) zfcp_erp_wait(adapter); } -static int status_change_set(unsigned long mask, atomic_t *status) +static int zfcp_erp_status_change_set(unsigned long mask, atomic_t *status) { return (atomic_read(status) ^ mask) & mask; } static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) { - if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) + if (zfcp_erp_status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, + &adapter->status)) zfcp_dbf_rec_run("eraubl1", &adapter->erp_action); atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status); } static void zfcp_erp_port_unblock(struct zfcp_port *port) { - if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) + if (zfcp_erp_status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, + &port->status)) zfcp_dbf_rec_run("erpubl1", &port->erp_action); atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status); } @@ -505,7 +561,8 @@ static void zfcp_erp_lun_unblock(struct scsi_device *sdev) { struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); - if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status)) + if (zfcp_erp_status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, + &zfcp_sdev->status)) zfcp_dbf_rec_run("erlubl1", &sdev_to_zfcp(sdev)->erp_action); atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status); } @@ -553,7 +610,7 @@ void zfcp_erp_notify(struct zfcp_erp_action *erp_action, unsigned long set_mask) unsigned long flags; write_lock_irqsave(&adapter->erp_lock, flags); - if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) { + if (zfcp_erp_action_is_running(erp_action)) { erp_action->status |= set_mask; zfcp_erp_action_ready(erp_action); } @@ -1634,3 +1691,14 @@ void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask) atomic_set(&zfcp_sdev->erp_counter, 0); } +/** + * zfcp_erp_adapter_reset_sync() - Really reopen adapter and wait. + * @adapter: Pointer to zfcp_adapter to reopen. + * @id: Trace tag string of length %ZFCP_DBF_TAG_LEN. + */ +void zfcp_erp_adapter_reset_sync(struct zfcp_adapter *adapter, char *id) +{ + zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); + zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, id); + zfcp_erp_wait(adapter); +} diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index bf8ea4df2bb8..bd0c5a9f04cb 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -4,7 +4,7 @@ * * External function declarations. * - * Copyright IBM Corp. 2002, 2016 + * Copyright IBM Corp. 2002, 2018 */ #ifndef ZFCP_EXT_H @@ -35,6 +35,9 @@ extern int zfcp_dbf_adapter_register(struct zfcp_adapter *); extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *); extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *, struct zfcp_port *, struct scsi_device *, u8, u8); +extern void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter, + struct zfcp_port *port, + struct scsi_device *sdev, u8 want, u8 need); extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *); extern void zfcp_dbf_rec_run_lvl(int level, char *tag, struct zfcp_erp_action *erp); @@ -47,17 +50,23 @@ extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *); extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); -extern void zfcp_dbf_scsi(char *, int, struct scsi_cmnd *, - struct zfcp_fsf_req *); +extern void zfcp_dbf_scsi_common(char *tag, int level, struct scsi_device *sdev, + struct scsi_cmnd *sc, + struct zfcp_fsf_req *fsf); +extern void zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter, + unsigned int scsi_id, int ret); /* zfcp_erp.c */ extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32); extern void zfcp_erp_clear_adapter_status(struct zfcp_adapter *, u32); +extern void zfcp_erp_port_forced_no_port_dbf(char *id, + struct zfcp_adapter *adapter, + u64 port_name, u32 port_id); extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *); extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *); extern void zfcp_erp_set_port_status(struct zfcp_port *, u32); extern void zfcp_erp_clear_port_status(struct zfcp_port *, u32); -extern int zfcp_erp_port_reopen(struct zfcp_port *, int, char *); +extern void zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id); extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *); extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *); extern void zfcp_erp_set_lun_status(struct scsi_device *, u32); @@ -70,6 +79,7 @@ extern void zfcp_erp_thread_kill(struct zfcp_adapter *); extern void zfcp_erp_wait(struct zfcp_adapter *); extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long); extern void zfcp_erp_timeout_handler(struct timer_list *t); +extern void zfcp_erp_adapter_reset_sync(struct zfcp_adapter *adapter, char *id); /* zfcp_fc.c */ extern struct kmem_cache *zfcp_fc_req_cache; @@ -117,7 +127,8 @@ extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32, struct zfcp_fsf_ct_els *, unsigned int); extern int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *); extern void zfcp_fsf_req_free(struct zfcp_fsf_req *); -extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *, u8); +extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_device *sdev, + u8 tm_flags); extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *); extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int); diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 6162cf57a20a..f6c415d6ef48 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -111,11 +111,10 @@ void zfcp_fc_post_event(struct work_struct *work) list_for_each_entry_safe(event, tmp, &tmp_lh, list) { fc_host_post_event(adapter->scsi_host, fc_get_event_number(), - event->code, event->data); + event->code, event->data); list_del(&event->list); kfree(event); } - } /** @@ -126,7 +125,7 @@ void zfcp_fc_post_event(struct work_struct *work) * @event_data: The event data (e.g. n_port page in case of els) */ void zfcp_fc_enqueue_event(struct zfcp_adapter *adapter, - enum fc_host_event_code event_code, u32 event_data) + enum fc_host_event_code event_code, u32 event_data) { struct zfcp_fc_event *event; @@ -425,6 +424,7 @@ void zfcp_fc_port_did_lookup(struct work_struct *work) struct zfcp_port *port = container_of(work, struct zfcp_port, gid_pn_work); + set_worker_desc("zgidpn%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */ ret = zfcp_fc_ns_gid_pn(port); if (ret) { /* could not issue gid_pn for some reason */ @@ -559,6 +559,7 @@ void zfcp_fc_link_test_work(struct work_struct *work) container_of(work, struct zfcp_port, test_link_work); int retval; + set_worker_desc("zadisc%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */ get_device(&port->dev); port->rport_task = RPORT_DEL; zfcp_scsi_rport_work(&port->rport_work); @@ -596,7 +597,7 @@ void zfcp_fc_test_link(struct zfcp_port *port) put_device(&port->dev); } -static struct zfcp_fc_req *zfcp_alloc_sg_env(int buf_num) +static struct zfcp_fc_req *zfcp_fc_alloc_sg_env(int buf_num) { struct zfcp_fc_req *fc_req; @@ -748,7 +749,7 @@ void zfcp_fc_scan_ports(struct work_struct *work) if (zfcp_fc_wka_port_get(&adapter->gs->ds)) return; - fc_req = zfcp_alloc_sg_env(buf_num); + fc_req = zfcp_fc_alloc_sg_env(buf_num); if (!fc_req) goto out; diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h index 6a397ddaadf0..3cd74729cfb9 100644 --- a/drivers/s390/scsi/zfcp_fc.h +++ b/drivers/s390/scsi/zfcp_fc.h @@ -207,21 +207,14 @@ struct zfcp_fc_wka_ports { * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd * @fcp: fcp_cmnd to setup * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB - * @tm: task management flags to setup task management command */ static inline -void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi, - u8 tm_flags) +void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi) { u32 datalen; int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun); - if (unlikely(tm_flags)) { - fcp->fc_tm_flags = tm_flags; - return; - } - fcp->fc_pri_ta = FCP_PTA_SIMPLE; if (scsi->sc_data_direction == DMA_FROM_DEVICE) @@ -241,6 +234,19 @@ void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi, } /** + * zfcp_fc_fcp_tm() - Setup FCP command as task management command. + * @fcp: Pointer to FCP_CMND IU to set up. + * @dev: Pointer to SCSI_device where to send the task management command. + * @tm_flags: Task management flags to setup tm command. + */ +static inline +void zfcp_fc_fcp_tm(struct fcp_cmnd *fcp, struct scsi_device *dev, u8 tm_flags) +{ + int_to_scsilun(dev->lun, (struct scsi_lun *) &fcp->fc_lun); + fcp->fc_tm_flags = tm_flags; +} + +/** * zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly * @fcp_rsp: FCP RSP IU to evaluate * @scsi: SCSI command where to update status and sense buffer diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index b12cb81ad8a2..3c86e27f094d 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -4,7 +4,7 @@ * * Implementation of FSF commands. * - * Copyright IBM Corp. 2002, 2017 + * Copyright IBM Corp. 2002, 2018 */ #define KMSG_COMPONENT "zfcp" @@ -437,6 +437,9 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) #define ZFCP_FSF_PORTSPEED_10GBIT (1 << 3) #define ZFCP_FSF_PORTSPEED_8GBIT (1 << 4) #define ZFCP_FSF_PORTSPEED_16GBIT (1 << 5) +#define ZFCP_FSF_PORTSPEED_32GBIT (1 << 6) +#define ZFCP_FSF_PORTSPEED_64GBIT (1 << 7) +#define ZFCP_FSF_PORTSPEED_128GBIT (1 << 8) #define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15) static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed) @@ -454,6 +457,12 @@ static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed) fdmi_speed |= FC_PORTSPEED_8GBIT; if (fsf_speed & ZFCP_FSF_PORTSPEED_16GBIT) fdmi_speed |= FC_PORTSPEED_16GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_32GBIT) + fdmi_speed |= FC_PORTSPEED_32GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_64GBIT) + fdmi_speed |= FC_PORTSPEED_64GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_128GBIT) + fdmi_speed |= FC_PORTSPEED_128GBIT; if (fsf_speed & ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED) fdmi_speed |= FC_PORTSPEED_NOT_NEGOTIATED; return fdmi_speed; @@ -662,7 +671,7 @@ static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool) return req; } -static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool) +static struct fsf_qtcb *zfcp_fsf_qtcb_alloc(mempool_t *pool) { struct fsf_qtcb *qtcb; @@ -701,9 +710,10 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio, if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) { if (likely(pool)) - req->qtcb = zfcp_qtcb_alloc(adapter->pool.qtcb_pool); + req->qtcb = zfcp_fsf_qtcb_alloc( + adapter->pool.qtcb_pool); else - req->qtcb = zfcp_qtcb_alloc(NULL); + req->qtcb = zfcp_fsf_qtcb_alloc(NULL); if (unlikely(!req->qtcb)) { zfcp_fsf_req_free(req); @@ -2036,10 +2046,14 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) sizeof(blktrc)); } -static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) +/** + * zfcp_fsf_fcp_handler_common() - FCP response handler common to I/O and TMF. + * @req: Pointer to FSF request. + * @sdev: Pointer to SCSI device as request context. + */ +static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req, + struct scsi_device *sdev) { - struct scsi_cmnd *scmnd = req->data; - struct scsi_device *sdev = scmnd->device; struct zfcp_scsi_dev *zfcp_sdev; struct fsf_qtcb_header *header = &req->qtcb->header; @@ -2051,7 +2065,7 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_HANDLE_MISMATCH: case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1"); + zfcp_erp_adapter_reopen(req->adapter, 0, "fssfch1"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_FCPLUN_NOT_VALID: @@ -2069,8 +2083,7 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) req->qtcb->bottom.io.data_direction, (unsigned long long)zfcp_scsi_dev_lun(sdev), (unsigned long long)zfcp_sdev->port->wwpn); - zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0, - "fssfch3"); + zfcp_erp_adapter_shutdown(req->adapter, 0, "fssfch3"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_CMND_LENGTH_NOT_VALID: @@ -2080,8 +2093,7 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) req->qtcb->bottom.io.fcp_cmnd_length, (unsigned long long)zfcp_scsi_dev_lun(sdev), (unsigned long long)zfcp_sdev->port->wwpn); - zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0, - "fssfch4"); + zfcp_erp_adapter_shutdown(req->adapter, 0, "fssfch4"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_PORT_BOXED: @@ -2120,7 +2132,7 @@ static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req) return; } - zfcp_fsf_fcp_handler_common(req); + zfcp_fsf_fcp_handler_common(req, scpnt->device); if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED); @@ -2258,7 +2270,7 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd) BUILD_BUG_ON(sizeof(struct fcp_cmnd) > FSF_FCP_CMND_SIZE); fcp_cmnd = &req->qtcb->bottom.io.fcp_cmnd.iu; - zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0); + zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd); if ((scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) && scsi_prot_sg_count(scsi_cmnd)) { @@ -2297,10 +2309,11 @@ out: static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req) { + struct scsi_device *sdev = req->data; struct fcp_resp_with_ext *fcp_rsp; struct fcp_resp_rsp_info *rsp_info; - zfcp_fsf_fcp_handler_common(req); + zfcp_fsf_fcp_handler_common(req, sdev); fcp_rsp = &req->qtcb->bottom.io.fcp_rsp.iu; rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; @@ -2311,17 +2324,18 @@ static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req) } /** - * zfcp_fsf_fcp_task_mgmt - send SCSI task management command - * @scmnd: SCSI command to send the task management command for - * @tm_flags: unsigned byte for task management flags - * Returns: on success pointer to struct fsf_req, NULL otherwise + * zfcp_fsf_fcp_task_mgmt() - Send SCSI task management command (TMF). + * @sdev: Pointer to SCSI device to send the task management command to. + * @tm_flags: Unsigned byte for task management flags. + * + * Return: On success pointer to struct zfcp_fsf_req, %NULL otherwise. */ -struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd, +struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_device *sdev, u8 tm_flags) { struct zfcp_fsf_req *req = NULL; struct fcp_cmnd *fcp_cmnd; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device); + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio; if (unlikely(!(atomic_read(&zfcp_sdev->status) & @@ -2341,7 +2355,8 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd, goto out; } - req->data = scmnd; + req->data = sdev; + req->handler = zfcp_fsf_fcp_task_mgmt_handler; req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; req->qtcb->header.port_handle = zfcp_sdev->port->handle; @@ -2352,7 +2367,7 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd, zfcp_qdio_set_sbale_last(qdio, &req->qdio_req); fcp_cmnd = &req->qtcb->bottom.io.fcp_cmnd.iu; - zfcp_fc_scsi_to_fcp(fcp_cmnd, scmnd, tm_flags); + zfcp_fc_fcp_tm(fcp_cmnd, sdev, tm_flags); zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT); if (!zfcp_fsf_req_send(req)) diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 4baca67aba6d..535628b92f0a 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -4,7 +4,7 @@ * * Interface to the FSF support functions. * - * Copyright IBM Corp. 2002, 2017 + * Copyright IBM Corp. 2002, 2018 */ #ifndef FSF_H @@ -356,7 +356,7 @@ struct fsf_qtcb_bottom_config { u32 adapter_features; u32 connection_features; u32 fc_topology; - u32 fc_link_speed; + u32 fc_link_speed; /* one of ZFCP_FSF_PORTSPEED_* */ u32 adapter_type; u8 res0; u8 peer_d_id[3]; @@ -382,7 +382,7 @@ struct fsf_qtcb_bottom_port { u32 class_of_service; /* should be 0x00000006 for class 2 and 3 */ u8 supported_fc4_types[32]; /* should be 0x00000100 for scsi fcp */ u8 active_fc4_types[32]; - u32 supported_speed; /* 0x0001 for 1 GBit/s or 0x0002 for 2 GBit/s */ + u32 supported_speed; /* any combination of ZFCP_FSF_PORTSPEED_* */ u32 maximum_frame_size; /* fixed value of 2112 */ u64 seconds_since_last_reset; u64 tx_frames; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 4d2ba5682493..a8efcb330bc1 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -4,7 +4,7 @@ * * Interface to Linux SCSI midlayer. * - * Copyright IBM Corp. 2002, 2017 + * Copyright IBM Corp. 2002, 2018 */ #define KMSG_COMPONENT "zfcp" @@ -181,6 +181,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) if (abrt_req) break; + zfcp_dbf_scsi_abort("abrt_wt", scpnt, NULL); zfcp_erp_wait(adapter); ret = fc_block_scsi_eh(scpnt); if (ret) { @@ -264,44 +265,52 @@ static void zfcp_scsi_forget_cmnds(struct zfcp_scsi_dev *zsdev, u8 tm_flags) write_unlock_irqrestore(&adapter->abort_lock, flags); } -static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) +/** + * zfcp_scsi_task_mgmt_function() - Send a task management function (sync). + * @sdev: Pointer to SCSI device to send the task management command to. + * @tm_flags: Task management flags, + * here we only handle %FCP_TMF_TGT_RESET or %FCP_TMF_LUN_RESET. + */ +static int zfcp_scsi_task_mgmt_function(struct scsi_device *sdev, u8 tm_flags) { - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device); + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; + struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); struct zfcp_fsf_req *fsf_req = NULL; int retval = SUCCESS, ret; int retry = 3; while (retry--) { - fsf_req = zfcp_fsf_fcp_task_mgmt(scpnt, tm_flags); + fsf_req = zfcp_fsf_fcp_task_mgmt(sdev, tm_flags); if (fsf_req) break; + zfcp_dbf_scsi_devreset("wait", sdev, tm_flags, NULL); zfcp_erp_wait(adapter); - ret = fc_block_scsi_eh(scpnt); + ret = fc_block_rport(rport); if (ret) { - zfcp_dbf_scsi_devreset("fiof", scpnt, tm_flags, NULL); + zfcp_dbf_scsi_devreset("fiof", sdev, tm_flags, NULL); return ret; } if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_RUNNING)) { - zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags, NULL); + zfcp_dbf_scsi_devreset("nres", sdev, tm_flags, NULL); return SUCCESS; } } if (!fsf_req) { - zfcp_dbf_scsi_devreset("reqf", scpnt, tm_flags, NULL); + zfcp_dbf_scsi_devreset("reqf", sdev, tm_flags, NULL); return FAILED; } wait_for_completion(&fsf_req->completion); if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { - zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags, fsf_req); + zfcp_dbf_scsi_devreset("fail", sdev, tm_flags, fsf_req); retval = FAILED; } else { - zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags, fsf_req); + zfcp_dbf_scsi_devreset("okay", sdev, tm_flags, fsf_req); zfcp_scsi_forget_cmnds(zfcp_sdev, tm_flags); } @@ -311,27 +320,81 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) { - return zfcp_task_mgmt_function(scpnt, FCP_TMF_LUN_RESET); + struct scsi_device *sdev = scpnt->device; + + return zfcp_scsi_task_mgmt_function(sdev, FCP_TMF_LUN_RESET); } static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) { - return zfcp_task_mgmt_function(scpnt, FCP_TMF_TGT_RESET); + struct scsi_target *starget = scsi_target(scpnt->device); + struct fc_rport *rport = starget_to_rport(starget); + struct Scsi_Host *shost = rport_to_shost(rport); + struct scsi_device *sdev = NULL, *tmp_sdev; + struct zfcp_adapter *adapter = + (struct zfcp_adapter *)shost->hostdata[0]; + int ret; + + shost_for_each_device(tmp_sdev, shost) { + if (tmp_sdev->id == starget->id) { + sdev = tmp_sdev; + break; + } + } + if (!sdev) { + ret = FAILED; + zfcp_dbf_scsi_eh("tr_nosd", adapter, starget->id, ret); + return ret; + } + + ret = zfcp_scsi_task_mgmt_function(sdev, FCP_TMF_TGT_RESET); + + /* release reference from above shost_for_each_device */ + if (sdev) + scsi_device_put(tmp_sdev); + + return ret; } static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) { struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device); struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; - int ret; + int ret = SUCCESS, fc_ret; zfcp_erp_adapter_reopen(adapter, 0, "schrh_1"); zfcp_erp_wait(adapter); - ret = fc_block_scsi_eh(scpnt); - if (ret) + fc_ret = fc_block_scsi_eh(scpnt); + if (fc_ret) + ret = fc_ret; + + zfcp_dbf_scsi_eh("schrh_r", adapter, ~0, ret); + return ret; +} + +/** + * zfcp_scsi_sysfs_host_reset() - Support scsi_host sysfs attribute host_reset. + * @shost: Pointer to Scsi_Host to perform action on. + * @reset_type: We support %SCSI_ADAPTER_RESET but not %SCSI_FIRMWARE_RESET. + * + * Return: 0 on %SCSI_ADAPTER_RESET, -%EOPNOTSUPP otherwise. + * + * This is similar to zfcp_sysfs_adapter_failed_store(). + */ +static int zfcp_scsi_sysfs_host_reset(struct Scsi_Host *shost, int reset_type) +{ + struct zfcp_adapter *adapter = + (struct zfcp_adapter *)shost->hostdata[0]; + int ret = 0; + + if (reset_type != SCSI_ADAPTER_RESET) { + ret = -EOPNOTSUPP; + zfcp_dbf_scsi_eh("scshr_n", adapter, ~0, ret); return ret; + } - return SUCCESS; + zfcp_erp_adapter_reset_sync(adapter, "scshr_y"); + return ret; } struct scsi_transport_template *zfcp_scsi_transport_template; @@ -349,6 +412,7 @@ static struct scsi_host_template zfcp_scsi_host_template = { .slave_configure = zfcp_scsi_slave_configure, .slave_destroy = zfcp_scsi_slave_destroy, .change_queue_depth = scsi_change_queue_depth, + .host_reset = zfcp_scsi_sysfs_host_reset, .proc_name = "zfcp", .can_queue = 4096, .this_id = -1, @@ -363,6 +427,7 @@ static struct scsi_host_template zfcp_scsi_host_template = { .shost_attrs = zfcp_sysfs_shost_attrs, .sdev_attrs = zfcp_sysfs_sdev_attrs, .track_queue_depth = 1, + .supported_mode = MODE_INITIATOR, }; /** @@ -430,7 +495,7 @@ void zfcp_scsi_adapter_unregister(struct zfcp_adapter *adapter) } static struct fc_host_statistics* -zfcp_init_fc_host_stats(struct zfcp_adapter *adapter) +zfcp_scsi_init_fc_host_stats(struct zfcp_adapter *adapter) { struct fc_host_statistics *fc_stats; @@ -444,9 +509,9 @@ zfcp_init_fc_host_stats(struct zfcp_adapter *adapter) return adapter->fc_stats; } -static void zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats, - struct fsf_qtcb_bottom_port *data, - struct fsf_qtcb_bottom_port *old) +static void zfcp_scsi_adjust_fc_host_stats(struct fc_host_statistics *fc_stats, + struct fsf_qtcb_bottom_port *data, + struct fsf_qtcb_bottom_port *old) { fc_stats->seconds_since_last_reset = data->seconds_since_last_reset - old->seconds_since_last_reset; @@ -477,8 +542,8 @@ static void zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats, fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb; } -static void zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats, - struct fsf_qtcb_bottom_port *data) +static void zfcp_scsi_set_fc_host_stats(struct fc_host_statistics *fc_stats, + struct fsf_qtcb_bottom_port *data) { fc_stats->seconds_since_last_reset = data->seconds_since_last_reset; fc_stats->tx_frames = data->tx_frames; @@ -502,7 +567,8 @@ static void zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats, fc_stats->fcp_output_megabytes = data->output_mb; } -static struct fc_host_statistics *zfcp_get_fc_host_stats(struct Scsi_Host *host) +static struct fc_host_statistics * +zfcp_scsi_get_fc_host_stats(struct Scsi_Host *host) { struct zfcp_adapter *adapter; struct fc_host_statistics *fc_stats; @@ -510,7 +576,7 @@ static struct fc_host_statistics *zfcp_get_fc_host_stats(struct Scsi_Host *host) int ret; adapter = (struct zfcp_adapter *)host->hostdata[0]; - fc_stats = zfcp_init_fc_host_stats(adapter); + fc_stats = zfcp_scsi_init_fc_host_stats(adapter); if (!fc_stats) return NULL; @@ -527,16 +593,16 @@ static struct fc_host_statistics *zfcp_get_fc_host_stats(struct Scsi_Host *host) if (adapter->stats_reset && ((jiffies/HZ - adapter->stats_reset) < data->seconds_since_last_reset)) - zfcp_adjust_fc_host_stats(fc_stats, data, - adapter->stats_reset_data); + zfcp_scsi_adjust_fc_host_stats(fc_stats, data, + adapter->stats_reset_data); else - zfcp_set_fc_host_stats(fc_stats, data); + zfcp_scsi_set_fc_host_stats(fc_stats, data); kfree(data); return fc_stats; } -static void zfcp_reset_fc_host_stats(struct Scsi_Host *shost) +static void zfcp_scsi_reset_fc_host_stats(struct Scsi_Host *shost) { struct zfcp_adapter *adapter; struct fsf_qtcb_bottom_port *data; @@ -558,7 +624,7 @@ static void zfcp_reset_fc_host_stats(struct Scsi_Host *shost) } } -static void zfcp_get_host_port_state(struct Scsi_Host *shost) +static void zfcp_scsi_get_host_port_state(struct Scsi_Host *shost) { struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; @@ -575,7 +641,8 @@ static void zfcp_get_host_port_state(struct Scsi_Host *shost) fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; } -static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout) +static void zfcp_scsi_set_rport_dev_loss_tmo(struct fc_rport *rport, + u32 timeout) { rport->dev_loss_tmo = timeout; } @@ -602,6 +669,11 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) if (port) { zfcp_erp_port_forced_reopen(port, 0, "sctrpi1"); put_device(&port->dev); + } else { + zfcp_erp_port_forced_no_port_dbf( + "sctrpin", adapter, + rport->port_name /* zfcp_scsi_rport_register */, + rport->port_id /* zfcp_scsi_rport_register */); } } @@ -618,9 +690,9 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port) ids.port_id = port->d_id; ids.roles = FC_RPORT_ROLE_FCP_TARGET; - zfcp_dbf_rec_trig("scpaddy", port->adapter, port, NULL, - ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD, - ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD); + zfcp_dbf_rec_trig_lock("scpaddy", port->adapter, port, NULL, + ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD, + ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD); rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); if (!rport) { dev_err(&port->adapter->ccw_device->dev, @@ -642,9 +714,9 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port) struct fc_rport *rport = port->rport; if (rport) { - zfcp_dbf_rec_trig("scpdely", port->adapter, port, NULL, - ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL, - ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL); + zfcp_dbf_rec_trig_lock("scpdely", port->adapter, port, NULL, + ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL, + ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL); fc_remote_port_delete(rport); port->rport = NULL; } @@ -687,6 +759,9 @@ void zfcp_scsi_rport_work(struct work_struct *work) struct zfcp_port *port = container_of(work, struct zfcp_port, rport_work); + set_worker_desc("zrp%c-%16llx", + (port->rport_task == RPORT_ADD) ? 'a' : 'd', + port->wwpn); /* < WORKER_DESC_LEN=24 */ while (port->rport_task) { if (port->rport_task == RPORT_ADD) { port->rport_task = RPORT_NONE; @@ -761,10 +836,10 @@ struct fc_function_template zfcp_transport_functions = { .show_host_supported_speeds = 1, .show_host_maxframe_size = 1, .show_host_serial_number = 1, - .get_fc_host_stats = zfcp_get_fc_host_stats, - .reset_fc_host_stats = zfcp_reset_fc_host_stats, - .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo, - .get_host_port_state = zfcp_get_host_port_state, + .get_fc_host_stats = zfcp_scsi_get_fc_host_stats, + .reset_fc_host_stats = zfcp_scsi_reset_fc_host_stats, + .set_rport_dev_loss_tmo = zfcp_scsi_set_rport_dev_loss_tmo, + .get_host_port_state = zfcp_scsi_get_host_port_state, .terminate_rport_io = zfcp_scsi_terminate_rport_io, .show_host_port_state = 1, .show_host_active_fc4s = 1, diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 3ac823f2540f..b277be6f7611 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -200,10 +200,7 @@ static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev, goto out; } - zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); - zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - "syafai2"); - zfcp_erp_wait(adapter); + zfcp_erp_adapter_reset_sync(adapter, "syafai2"); out: zfcp_ccw_adapter_put(adapter); return retval ? retval : (ssize_t) count; |