summaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/dasd.c17
-rw-r--r--drivers/s390/block/dasd_devmap.c15
-rw-r--r--drivers/s390/block/dasd_eckd.c1
-rw-r--r--drivers/s390/block/dasd_fba.c10
-rw-r--r--drivers/s390/block/dasd_genhd.c3
-rw-r--r--drivers/s390/block/dasd_int.h3
-rw-r--r--drivers/s390/cio/vfio_ccw_ops.c17
-rw-r--r--drivers/s390/crypto/vfio_ap_ops.c14
-rw-r--r--drivers/s390/net/qeth_core_main.c18
-rw-r--r--drivers/s390/net/qeth_l3_main.c31
-rw-r--r--drivers/s390/scsi/zfcp_aux.c28
-rw-r--r--drivers/s390/scsi/zfcp_def.h6
-rw-r--r--drivers/s390/scsi/zfcp_diag.c42
-rw-r--r--drivers/s390/scsi/zfcp_diag.h7
-rw-r--r--drivers/s390/scsi/zfcp_ext.h4
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c1
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c68
-rw-r--r--drivers/s390/scsi/zfcp_qdio.h5
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c14
-rw-r--r--drivers/s390/scsi/zfcp_unit.c4
20 files changed, 138 insertions, 170 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 3a945abf268c..c8df75e99f4c 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -3439,15 +3439,6 @@ static void dasd_generic_auto_online(void *data, async_cookie_t cookie)
*/
int dasd_generic_probe(struct ccw_device *cdev)
{
- int ret;
-
- ret = dasd_add_sysfs_files(cdev);
- if (ret) {
- DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s",
- "dasd_generic_probe: could not add "
- "sysfs entries");
- return ret;
- }
cdev->handler = &dasd_int_handler;
/*
@@ -3488,15 +3479,13 @@ void dasd_generic_remove(struct ccw_device *cdev)
struct dasd_block *block;
device = dasd_device_from_cdev(cdev);
- if (IS_ERR(device)) {
- dasd_remove_sysfs_files(cdev);
+ if (IS_ERR(device))
return;
- }
+
if (test_and_set_bit(DASD_FLAG_OFFLINE, &device->flags) &&
!test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
/* Already doing offline processing */
dasd_put_device(device);
- dasd_remove_sysfs_files(cdev);
return;
}
/*
@@ -3515,8 +3504,6 @@ void dasd_generic_remove(struct ccw_device *cdev)
*/
if (block)
dasd_free_block(block);
-
- dasd_remove_sysfs_files(cdev);
}
EXPORT_SYMBOL_GPL(dasd_generic_remove);
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 03d27ee9cac6..2c40fe15da55 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -1772,12 +1772,13 @@ static const struct attribute_group ext_pool_attr_group = {
.attrs = ext_pool_attrs,
};
-static const struct attribute_group *dasd_attr_groups[] = {
+const struct attribute_group *dasd_dev_groups[] = {
&dasd_attr_group,
&capacity_attr_group,
&ext_pool_attr_group,
NULL,
};
+EXPORT_SYMBOL_GPL(dasd_dev_groups);
/*
* Return value of the specified feature.
@@ -1895,18 +1896,6 @@ void dasd_path_remove_kobjects(struct dasd_device *device)
}
EXPORT_SYMBOL(dasd_path_remove_kobjects);
-int dasd_add_sysfs_files(struct ccw_device *cdev)
-{
- return sysfs_create_groups(&cdev->dev.kobj, dasd_attr_groups);
-}
-
-void
-dasd_remove_sysfs_files(struct ccw_device *cdev)
-{
- sysfs_remove_groups(&cdev->dev.kobj, dasd_attr_groups);
-}
-
-
int
dasd_devmap_init(void)
{
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 65eb87cbbb9b..a6ac505cbdd7 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -6630,6 +6630,7 @@ static struct ccw_driver dasd_eckd_driver = {
.driver = {
.name = "dasd-eckd",
.owner = THIS_MODULE,
+ .dev_groups = dasd_dev_groups,
},
.ids = dasd_eckd_ids,
.probe = dasd_eckd_probe,
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 1aeb68794ce8..4789410885e4 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -54,13 +54,6 @@ static struct ccw_device_id dasd_fba_ids[] = {
MODULE_DEVICE_TABLE(ccw, dasd_fba_ids);
-static struct ccw_driver dasd_fba_driver; /* see below */
-static int
-dasd_fba_probe(struct ccw_device *cdev)
-{
- return dasd_generic_probe(cdev);
-}
-
static int
dasd_fba_set_online(struct ccw_device *cdev)
{
@@ -71,9 +64,10 @@ static struct ccw_driver dasd_fba_driver = {
.driver = {
.name = "dasd-fba",
.owner = THIS_MODULE,
+ .dev_groups = dasd_dev_groups,
},
.ids = dasd_fba_ids,
- .probe = dasd_fba_probe,
+ .probe = dasd_generic_probe,
.remove = dasd_generic_remove,
.set_offline = dasd_generic_set_offline,
.set_online = dasd_fba_set_online,
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index a9698fba9b76..8d6587ec73e2 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -146,12 +146,11 @@ void dasd_destroy_partitions(struct dasd_block *block)
block->bdev = NULL;
mutex_lock(&bdev->bd_mutex);
- blk_drop_partitions(bdev);
+ bdev_disk_changed(bdev, true);
mutex_unlock(&bdev->bd_mutex);
/* Matching blkdev_put to the blkdev_get in dasd_scan_partitions. */
blkdev_put(bdev, FMODE_READ);
- set_capacity(block->gdp, 0);
}
int dasd_gendisk_init(void)
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index b8a04c42d1d2..1c59b0e86a9f 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -854,8 +854,7 @@ void dasd_delete_device(struct dasd_device *);
int dasd_get_feature(struct ccw_device *, int);
int dasd_set_feature(struct ccw_device *, int, int);
-int dasd_add_sysfs_files(struct ccw_device *);
-void dasd_remove_sysfs_files(struct ccw_device *);
+extern const struct attribute_group *dasd_dev_groups[];
void dasd_path_create_kobj(struct dasd_device *, int);
void dasd_path_create_kobjects(struct dasd_device *);
void dasd_path_remove_kobjects(struct dasd_device *);
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index 767ac41686fe..491a64c61fff 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -71,23 +71,26 @@ static int vfio_ccw_mdev_notifier(struct notifier_block *nb,
return NOTIFY_DONE;
}
-static ssize_t name_show(struct kobject *kobj, struct device *dev, char *buf)
+static ssize_t name_show(struct mdev_type *mtype,
+ struct mdev_type_attribute *attr, char *buf)
{
return sprintf(buf, "I/O subchannel (Non-QDIO)\n");
}
static MDEV_TYPE_ATTR_RO(name);
-static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
- char *buf)
+static ssize_t device_api_show(struct mdev_type *mtype,
+ struct mdev_type_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", VFIO_DEVICE_API_CCW_STRING);
}
static MDEV_TYPE_ATTR_RO(device_api);
-static ssize_t available_instances_show(struct kobject *kobj,
- struct device *dev, char *buf)
+static ssize_t available_instances_show(struct mdev_type *mtype,
+ struct mdev_type_attribute *attr,
+ char *buf)
{
- struct vfio_ccw_private *private = dev_get_drvdata(dev);
+ struct vfio_ccw_private *private =
+ dev_get_drvdata(mtype_get_parent_dev(mtype));
return sprintf(buf, "%d\n", atomic_read(&private->avail));
}
@@ -110,7 +113,7 @@ static struct attribute_group *mdev_type_groups[] = {
NULL,
};
-static int vfio_ccw_mdev_create(struct kobject *kobj, struct mdev_device *mdev)
+static int vfio_ccw_mdev_create(struct mdev_device *mdev)
{
struct vfio_ccw_private *private =
dev_get_drvdata(mdev_parent_dev(mdev));
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 6946a7e26eff..b2c7e10dfdcd 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -335,7 +335,7 @@ static void vfio_ap_matrix_init(struct ap_config_info *info,
matrix->adm_max = info->apxa ? info->Nd : 15;
}
-static int vfio_ap_mdev_create(struct kobject *kobj, struct mdev_device *mdev)
+static int vfio_ap_mdev_create(struct mdev_device *mdev)
{
struct ap_matrix_mdev *matrix_mdev;
@@ -386,15 +386,17 @@ static int vfio_ap_mdev_remove(struct mdev_device *mdev)
return 0;
}
-static ssize_t name_show(struct kobject *kobj, struct device *dev, char *buf)
+static ssize_t name_show(struct mdev_type *mtype,
+ struct mdev_type_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", VFIO_AP_MDEV_NAME_HWVIRT);
}
static MDEV_TYPE_ATTR_RO(name);
-static ssize_t available_instances_show(struct kobject *kobj,
- struct device *dev, char *buf)
+static ssize_t available_instances_show(struct mdev_type *mtype,
+ struct mdev_type_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%d\n",
atomic_read(&matrix_dev->available_instances));
@@ -402,8 +404,8 @@ static ssize_t available_instances_show(struct kobject *kobj,
static MDEV_TYPE_ATTR_RO(available_instances);
-static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
- char *buf)
+static ssize_t device_api_show(struct mdev_type *mtype,
+ struct mdev_type_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", VFIO_DEVICE_API_AP_STRING);
}
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 175b82b98f36..a1f08e9aa064 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -1429,7 +1429,7 @@ static void qeth_free_out_buf(struct qeth_qdio_out_buffer *buf)
static void qeth_tx_complete_pending_bufs(struct qeth_card *card,
struct qeth_qdio_out_q *queue,
- bool drain)
+ bool drain, int budget)
{
struct qeth_qdio_out_buffer *buf, *tmp;
@@ -1441,7 +1441,7 @@ static void qeth_tx_complete_pending_bufs(struct qeth_card *card,
if (drain)
qeth_notify_skbs(queue, buf,
TX_NOTIFY_GENERALERROR);
- qeth_tx_complete_buf(buf, drain, 0);
+ qeth_tx_complete_buf(buf, drain, budget);
list_del(&buf->list_entry);
qeth_free_out_buf(buf);
@@ -1453,7 +1453,7 @@ static void qeth_drain_output_queue(struct qeth_qdio_out_q *q, bool free)
{
int j;
- qeth_tx_complete_pending_bufs(q->card, q, true);
+ qeth_tx_complete_pending_bufs(q->card, q, true, 0);
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
if (!q->bufs[j])
@@ -2566,11 +2566,12 @@ static int qeth_ulp_setup(struct qeth_card *card)
return qeth_send_control_data(card, iob, qeth_ulp_setup_cb, NULL);
}
-static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
+static int qeth_alloc_out_buf(struct qeth_qdio_out_q *q, unsigned int bidx,
+ gfp_t gfp)
{
struct qeth_qdio_out_buffer *newbuf;
- newbuf = kmem_cache_zalloc(qeth_qdio_outbuf_cache, GFP_ATOMIC);
+ newbuf = kmem_cache_zalloc(qeth_qdio_outbuf_cache, gfp);
if (!newbuf)
return -ENOMEM;
@@ -2605,7 +2606,7 @@ static struct qeth_qdio_out_q *qeth_alloc_output_queue(void)
goto err_qdio_bufs;
for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
- if (qeth_init_qdio_out_buf(q, i))
+ if (qeth_alloc_out_buf(q, i, GFP_KERNEL))
goto err_out_bufs;
}
@@ -6080,7 +6081,8 @@ static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue,
/* Prepare the queue slot for immediate re-use: */
qeth_scrub_qdio_buffer(buffer->buffer, queue->max_elements);
- if (qeth_init_qdio_out_buf(queue, bidx)) {
+ if (qeth_alloc_out_buf(queue, bidx,
+ GFP_ATOMIC)) {
QETH_CARD_TEXT(card, 2, "outofbuf");
qeth_schedule_recovery(card);
}
@@ -6144,7 +6146,7 @@ static int qeth_tx_poll(struct napi_struct *napi, int budget)
unsigned int bytes = 0;
int completed;
- qeth_tx_complete_pending_bufs(card, queue, false);
+ qeth_tx_complete_pending_bufs(card, queue, false, budget);
if (qeth_out_queue_is_empty(queue)) {
napi_complete(napi);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index dd441eaec66e..d308ff744a29 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1098,8 +1098,9 @@ walk_ipv6:
tmp.disp_flag = QETH_DISP_ADDR_ADD;
tmp.is_multicast = 1;
- read_lock_bh(&in6_dev->lock);
- for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
+ for (im6 = rtnl_dereference(in6_dev->mc_list);
+ im6;
+ im6 = rtnl_dereference(im6->next)) {
tmp.u.a6.addr = im6->mca_addr;
ipm = qeth_l3_find_addr_by_ip(card, &tmp);
@@ -1117,30 +1118,11 @@ walk_ipv6:
qeth_l3_ipaddr_hash(ipm));
}
- read_unlock_bh(&in6_dev->lock);
out:
return 0;
}
-static int qeth_l3_vlan_rx_add_vid(struct net_device *dev,
- __be16 proto, u16 vid)
-{
- struct qeth_card *card = dev->ml_priv;
-
- QETH_CARD_TEXT_(card, 4, "aid:%d", vid);
- return 0;
-}
-
-static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev,
- __be16 proto, u16 vid)
-{
- struct qeth_card *card = dev->ml_priv;
-
- QETH_CARD_TEXT_(card, 4, "kid:%d", vid);
- return 0;
-}
-
static void qeth_l3_set_promisc_mode(struct qeth_card *card)
{
bool enable = card->dev->flags & IFF_PROMISC;
@@ -1861,8 +1843,6 @@ static const struct net_device_ops qeth_l3_netdev_ops = {
.ndo_do_ioctl = qeth_do_ioctl,
.ndo_fix_features = qeth_fix_features,
.ndo_set_features = qeth_set_features,
- .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid,
- .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid,
.ndo_tx_timeout = qeth_tx_timeout,
};
@@ -1878,8 +1858,6 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = {
.ndo_do_ioctl = qeth_do_ioctl,
.ndo_fix_features = qeth_fix_features,
.ndo_set_features = qeth_set_features,
- .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid,
- .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid,
.ndo_tx_timeout = qeth_tx_timeout,
.ndo_neigh_setup = qeth_l3_neigh_setup,
};
@@ -1933,8 +1911,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
card->dev->needed_headroom = headroom;
card->dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
- NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_VLAN_CTAG_FILTER;
+ NETIF_F_HW_VLAN_CTAG_RX;
netif_keep_dst(card->dev);
if (card->dev->hw_features & (NETIF_F_TSO | NETIF_F_TSO6))
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 768873dd55b8..fd2f1c31bd21 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -413,12 +413,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
dev_set_drvdata(&ccw_device->dev, adapter);
- if (sysfs_create_group(&ccw_device->dev.kobj,
- &zfcp_sysfs_adapter_attrs))
- goto failed;
-
- if (zfcp_diag_sysfs_setup(adapter))
- goto failed;
+ if (device_add_groups(&ccw_device->dev, zfcp_sysfs_adapter_attr_groups))
+ goto err_sysfs;
/* report size limit per scatter-gather segment */
adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
@@ -427,8 +423,23 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
return adapter;
+err_sysfs:
failed:
- zfcp_adapter_unregister(adapter);
+ /* TODO: make this more fine-granular */
+ cancel_delayed_work_sync(&adapter->scan_work);
+ cancel_work_sync(&adapter->stat_work);
+ cancel_work_sync(&adapter->ns_up_work);
+ cancel_work_sync(&adapter->version_change_lost_work);
+ zfcp_destroy_adapter_work_queue(adapter);
+
+ zfcp_fc_wka_ports_force_offline(adapter->gs);
+ zfcp_scsi_adapter_unregister(adapter);
+
+ zfcp_erp_thread_kill(adapter);
+ zfcp_dbf_adapter_unregister(adapter);
+ zfcp_qdio_destroy(adapter->qdio);
+
+ zfcp_ccw_adapter_put(adapter); /* final put to release */
return ERR_PTR(-ENOMEM);
}
@@ -444,8 +455,7 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter)
zfcp_fc_wka_ports_force_offline(adapter->gs);
zfcp_scsi_adapter_unregister(adapter);
- zfcp_diag_sysfs_destroy(adapter);
- sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs);
+ device_remove_groups(&cdev->dev, zfcp_sysfs_adapter_attr_groups);
zfcp_erp_thread_kill(adapter);
zfcp_dbf_adapter_unregister(adapter);
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 26c89c232ef2..94de55304a02 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -156,7 +156,7 @@ struct zfcp_adapter {
u32 fsf_lic_version;
u32 adapter_features; /* FCP channel features */
u32 connection_features; /* host connection features */
- u32 hardware_version; /* of FCP channel */
+ u32 hardware_version; /* of FCP channel */
u32 fc_security_algorithms; /* of FCP channel */
u32 fc_security_algorithms_old; /* of FCP channel */
u16 timer_ticks; /* time int for a tick */
@@ -180,7 +180,7 @@ struct zfcp_adapter {
rwlock_t erp_lock;
wait_queue_head_t erp_done_wqh;
struct zfcp_erp_action erp_action; /* pending error recovery */
- atomic_t erp_counter;
+ atomic_t erp_counter;
u32 erp_total_count; /* total nr of enqueued erp
actions */
u32 erp_low_mem_count; /* nr of erp actions waiting
@@ -217,7 +217,7 @@ struct zfcp_port {
u32 d_id; /* D_ID */
u32 handle; /* handle assigned by FSF */
struct zfcp_erp_action erp_action; /* pending error recovery */
- atomic_t erp_counter;
+ atomic_t erp_counter;
u32 maxframe_size;
u32 supported_classes;
u32 connection_info;
diff --git a/drivers/s390/scsi/zfcp_diag.c b/drivers/s390/scsi/zfcp_diag.c
index 67a8f4e57db1..4d2d89d9c15a 100644
--- a/drivers/s390/scsi/zfcp_diag.c
+++ b/drivers/s390/scsi/zfcp_diag.c
@@ -10,8 +10,6 @@
#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include <linux/string.h>
-#include <linux/kernfs.h>
-#include <linux/sysfs.h>
#include <linux/errno.h>
#include <linux/slab.h>
@@ -80,46 +78,6 @@ void zfcp_diag_adapter_free(struct zfcp_adapter *const adapter)
}
/**
- * zfcp_diag_sysfs_setup() - Setup the sysfs-group for adapter-diagnostics.
- * @adapter: target adapter to which the group should be added.
- *
- * Return: 0 on success; Something else otherwise (see sysfs_create_group()).
- */
-int zfcp_diag_sysfs_setup(struct zfcp_adapter *const adapter)
-{
- int rc = sysfs_create_group(&adapter->ccw_device->dev.kobj,
- &zfcp_sysfs_diag_attr_group);
- if (rc == 0)
- adapter->diagnostics->sysfs_established = 1;
-
- return rc;
-}
-
-/**
- * zfcp_diag_sysfs_destroy() - Remove the sysfs-group for adapter-diagnostics.
- * @adapter: target adapter from which the group should be removed.
- */
-void zfcp_diag_sysfs_destroy(struct zfcp_adapter *const adapter)
-{
- if (adapter->diagnostics == NULL ||
- !adapter->diagnostics->sysfs_established)
- return;
-
- /*
- * We need this state-handling so we can prevent warnings being printed
- * on the kernel-console in case we have to abort a halfway done
- * zfcp_adapter_enqueue(), in which the sysfs-group was not yet
- * established. sysfs_remove_group() does this checking as well, but
- * still prints a warning in case we try to remove a group that has not
- * been established before
- */
- adapter->diagnostics->sysfs_established = 0;
- sysfs_remove_group(&adapter->ccw_device->dev.kobj,
- &zfcp_sysfs_diag_attr_group);
-}
-
-
-/**
* zfcp_diag_update_xdata() - Update a diagnostics buffer.
* @hdr: the meta data to update.
* @data: data to use for the update.
diff --git a/drivers/s390/scsi/zfcp_diag.h b/drivers/s390/scsi/zfcp_diag.h
index 3852367f15f6..da55133da8fe 100644
--- a/drivers/s390/scsi/zfcp_diag.h
+++ b/drivers/s390/scsi/zfcp_diag.h
@@ -40,8 +40,6 @@ struct zfcp_diag_header {
/**
* struct zfcp_diag_adapter - central storage for all diagnostics concerning an
* adapter.
- * @sysfs_established: flag showing that the associated sysfs-group was created
- * during run of zfcp_adapter_enqueue().
* @max_age: maximum age of data in diagnostic buffers before they need to be
* refreshed (in ms).
* @port_data: data retrieved using exchange port data.
@@ -52,8 +50,6 @@ struct zfcp_diag_header {
* @config_data.data: cached QTCB Bottom of command exchange config data.
*/
struct zfcp_diag_adapter {
- u64 sysfs_established :1;
-
unsigned long max_age;
struct zfcp_diag_adapter_port_data {
@@ -69,9 +65,6 @@ struct zfcp_diag_adapter {
int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter);
void zfcp_diag_adapter_free(struct zfcp_adapter *const adapter);
-int zfcp_diag_sysfs_setup(struct zfcp_adapter *const adapter);
-void zfcp_diag_sysfs_destroy(struct zfcp_adapter *const adapter);
-
void zfcp_diag_update_xdata(struct zfcp_diag_header *const hdr,
const void *const data, const bool incomplete);
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 58879213f225..6bc96d70254d 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -11,6 +11,7 @@
#define ZFCP_EXT_H
#include <linux/types.h>
+#include <linux/sysfs.h>
#include <scsi/fc/fc_els.h>
#include "zfcp_def.h"
#include "zfcp_fc.h"
@@ -179,13 +180,12 @@ extern void zfcp_scsi_shost_update_port_data(
const struct fsf_qtcb_bottom_port *const bottom);
/* zfcp_sysfs.c */
+extern const struct attribute_group *zfcp_sysfs_adapter_attr_groups[];
extern const struct attribute_group *zfcp_unit_attr_groups[];
-extern struct attribute_group zfcp_sysfs_adapter_attrs;
extern const struct attribute_group *zfcp_port_attr_groups[];
extern struct mutex zfcp_sysfs_port_units_mutex;
extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
extern struct device_attribute *zfcp_sysfs_shost_attrs[];
-extern const struct attribute_group zfcp_sysfs_diag_attr_group;
bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port);
/* zfcp_unit.c */
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 485028324eae..2e4804ef2fb9 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -846,7 +846,6 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
if (adapter->req_no == 0)
adapter->req_no++;
- INIT_LIST_HEAD(&req->list);
timer_setup(&req->timer, NULL, 0);
init_completion(&req->completion);
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 049596cbfb5d..6671d9563f6c 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -20,6 +20,9 @@ static bool enable_multibuffer = true;
module_param_named(datarouter, enable_multibuffer, bool, 0400);
MODULE_PARM_DESC(datarouter, "Enable hardware data router support (default on)");
+#define ZFCP_QDIO_REQUEST_RESCAN_MSECS (MSEC_PER_SEC * 10)
+#define ZFCP_QDIO_REQUEST_SCAN_MSECS MSEC_PER_SEC
+
static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *dbftag,
unsigned int qdio_err)
{
@@ -70,15 +73,41 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
zfcp_qdio_handler_error(qdio, "qdireq1", qdio_err);
return;
}
+}
- /* cleanup all SBALs being program-owned now */
- zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
+static void zfcp_qdio_request_tasklet(struct tasklet_struct *tasklet)
+{
+ struct zfcp_qdio *qdio = from_tasklet(qdio, tasklet, request_tasklet);
+ struct ccw_device *cdev = qdio->adapter->ccw_device;
+ unsigned int start, error;
+ int completed;
- spin_lock_irq(&qdio->stat_lock);
- zfcp_qdio_account(qdio);
- spin_unlock_irq(&qdio->stat_lock);
- atomic_add(count, &qdio->req_q_free);
- wake_up(&qdio->req_q_wq);
+ completed = qdio_inspect_queue(cdev, 0, false, &start, &error);
+ if (completed > 0) {
+ if (error) {
+ zfcp_qdio_handler_error(qdio, "qdreqt1", error);
+ } else {
+ /* cleanup all SBALs being program-owned now */
+ zfcp_qdio_zero_sbals(qdio->req_q, start, completed);
+
+ spin_lock_irq(&qdio->stat_lock);
+ zfcp_qdio_account(qdio);
+ spin_unlock_irq(&qdio->stat_lock);
+ atomic_add(completed, &qdio->req_q_free);
+ wake_up(&qdio->req_q_wq);
+ }
+ }
+
+ if (atomic_read(&qdio->req_q_free) < QDIO_MAX_BUFFERS_PER_Q)
+ timer_reduce(&qdio->request_timer,
+ jiffies + msecs_to_jiffies(ZFCP_QDIO_REQUEST_RESCAN_MSECS));
+}
+
+static void zfcp_qdio_request_timer(struct timer_list *timer)
+{
+ struct zfcp_qdio *qdio = from_timer(qdio, timer, request_timer);
+
+ tasklet_schedule(&qdio->request_tasklet);
}
static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
@@ -139,8 +168,11 @@ static void zfcp_qdio_irq_tasklet(struct tasklet_struct *tasklet)
unsigned int start, error;
int completed;
- /* Check the Response Queue, and kick off the Request Queue tasklet: */
- completed = qdio_get_next_buffers(cdev, 0, &start, &error);
+ if (atomic_read(&qdio->req_q_free) < QDIO_MAX_BUFFERS_PER_Q)
+ tasklet_schedule(&qdio->request_tasklet);
+
+ /* Check the Response Queue: */
+ completed = qdio_inspect_queue(cdev, 0, true, &start, &error);
if (completed < 0)
return;
if (completed > 0)
@@ -286,7 +318,7 @@ int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
/*
* This should actually be a spin_lock_bh(stat_lock), to protect against
- * zfcp_qdio_int_req() in tasklet context.
+ * Request Queue completion processing in tasklet context.
* But we can't do so (and are safe), as we always get called with IRQs
* disabled by spin_lock_irq[save](req_q_lock).
*/
@@ -308,6 +340,12 @@ int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
return retval;
}
+ if (atomic_read(&qdio->req_q_free) <= 2 * ZFCP_QDIO_MAX_SBALS_PER_REQ)
+ tasklet_schedule(&qdio->request_tasklet);
+ else
+ timer_reduce(&qdio->request_timer,
+ jiffies + msecs_to_jiffies(ZFCP_QDIO_REQUEST_SCAN_MSECS));
+
/* account for transferred buffers */
qdio->req_q_idx += sbal_number;
qdio->req_q_idx %= QDIO_MAX_BUFFERS_PER_Q;
@@ -368,6 +406,8 @@ void zfcp_qdio_close(struct zfcp_qdio *qdio)
wake_up(&qdio->req_q_wq);
tasklet_disable(&qdio->irq_tasklet);
+ tasklet_disable(&qdio->request_tasklet);
+ del_timer_sync(&qdio->request_timer);
qdio_stop_irq(adapter->ccw_device);
qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
@@ -428,8 +468,6 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
init_data.int_parm = (unsigned long) qdio;
init_data.input_sbal_addr_array = input_sbals;
init_data.output_sbal_addr_array = output_sbals;
- init_data.scan_threshold =
- QDIO_MAX_BUFFERS_PER_Q - ZFCP_QDIO_MAX_SBALS_PER_REQ * 2;
if (qdio_establish(cdev, &init_data))
goto failed_establish;
@@ -472,6 +510,8 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);
atomic_or(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
+ /* Enable processing for Request Queue completions: */
+ tasklet_enable(&qdio->request_tasklet);
/* Enable processing for QDIO interrupts: */
tasklet_enable(&qdio->irq_tasklet);
/* This results in a qdio_start_irq(): */
@@ -495,6 +535,7 @@ void zfcp_qdio_destroy(struct zfcp_qdio *qdio)
return;
tasklet_kill(&qdio->irq_tasklet);
+ tasklet_kill(&qdio->request_tasklet);
if (qdio->adapter->ccw_device)
qdio_free(qdio->adapter->ccw_device);
@@ -521,8 +562,11 @@ int zfcp_qdio_setup(struct zfcp_adapter *adapter)
spin_lock_init(&qdio->req_q_lock);
spin_lock_init(&qdio->stat_lock);
+ timer_setup(&qdio->request_timer, zfcp_qdio_request_timer, 0);
tasklet_setup(&qdio->irq_tasklet, zfcp_qdio_irq_tasklet);
+ tasklet_setup(&qdio->request_tasklet, zfcp_qdio_request_tasklet);
tasklet_disable(&qdio->irq_tasklet);
+ tasklet_disable(&qdio->request_tasklet);
adapter->qdio = qdio;
return 0;
diff --git a/drivers/s390/scsi/zfcp_qdio.h b/drivers/s390/scsi/zfcp_qdio.h
index 9c1f310db155..390706867df3 100644
--- a/drivers/s390/scsi/zfcp_qdio.h
+++ b/drivers/s390/scsi/zfcp_qdio.h
@@ -30,6 +30,9 @@
* @req_q_util: used for accounting
* @req_q_full: queue full incidents
* @req_q_wq: used to wait for SBAL availability
+ * @irq_tasklet: used for QDIO interrupt processing
+ * @request_tasklet: used for Request Queue completion processing
+ * @request_timer: used to trigger the Request Queue completion processing
* @adapter: adapter used in conjunction with this qdio structure
* @max_sbale_per_sbal: qdio limit per sbal
* @max_sbale_per_req: qdio limit per request
@@ -46,6 +49,8 @@ struct zfcp_qdio {
atomic_t req_q_full;
wait_queue_head_t req_q_wq;
struct tasklet_struct irq_tasklet;
+ struct tasklet_struct request_tasklet;
+ struct timer_list request_timer;
struct zfcp_adapter *adapter;
u16 max_sbale_per_sbal;
u16 max_sbale_per_req;
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index 8d9662e8b717..544efd4c42f0 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -327,10 +327,10 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
list_del(&port->list);
write_unlock_irq(&adapter->port_list_lock);
- put_device(&port->dev);
-
zfcp_erp_port_shutdown(port, 0, "syprs_1");
device_unregister(&port->dev);
+
+ put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */
out:
zfcp_ccw_adapter_put(adapter);
return retval ? retval : (ssize_t) count;
@@ -435,7 +435,7 @@ static struct attribute *zfcp_adapter_attrs[] = {
NULL
};
-struct attribute_group zfcp_sysfs_adapter_attrs = {
+static const struct attribute_group zfcp_sysfs_adapter_attr_group = {
.attrs = zfcp_adapter_attrs,
};
@@ -906,7 +906,13 @@ static struct attribute *zfcp_sysfs_diag_attrs[] = {
NULL,
};
-const struct attribute_group zfcp_sysfs_diag_attr_group = {
+static const struct attribute_group zfcp_sysfs_diag_attr_group = {
.name = "diagnostics",
.attrs = zfcp_sysfs_diag_attrs,
};
+
+const struct attribute_group *zfcp_sysfs_adapter_attr_groups[] = {
+ &zfcp_sysfs_adapter_attr_group,
+ &zfcp_sysfs_diag_attr_group,
+ NULL,
+};
diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c
index e67bf7388cae..59333f0257a8 100644
--- a/drivers/s390/scsi/zfcp_unit.c
+++ b/drivers/s390/scsi/zfcp_unit.c
@@ -255,9 +255,9 @@ int zfcp_unit_remove(struct zfcp_port *port, u64 fcp_lun)
scsi_device_put(sdev);
}
- put_device(&unit->dev);
-
device_unregister(&unit->dev);
+ put_device(&unit->dev); /* undo _zfcp_unit_find() */
+
return 0;
}