s390/qeth: fine-tune spinlocks
For quite a lot of code paths it's obvious that they will never run in IRQ context. So replace their spin_lock_irqsave() calls with spin_lock_irq(). While at it, get rid of the redundant card pointer in struct qeth_reply that was used by qeth_send_control_data() to access the card's lock. Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
31c92732cd
commit
ed47155bdc
@ -639,7 +639,6 @@ struct qeth_reply {
|
|||||||
atomic_t received;
|
atomic_t received;
|
||||||
int rc;
|
int rc;
|
||||||
void *param;
|
void *param;
|
||||||
struct qeth_card *card;
|
|
||||||
refcount_t refcnt;
|
refcount_t refcnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -592,7 +592,6 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
|
|||||||
if (reply) {
|
if (reply) {
|
||||||
refcount_set(&reply->refcnt, 1);
|
refcount_set(&reply->refcnt, 1);
|
||||||
atomic_set(&reply->received, 0);
|
atomic_set(&reply->received, 0);
|
||||||
reply->card = card;
|
|
||||||
}
|
}
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
@ -1541,15 +1540,14 @@ out:
|
|||||||
|
|
||||||
static int qeth_clear_channel(struct qeth_channel *channel)
|
static int qeth_clear_channel(struct qeth_channel *channel)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
struct qeth_card *card;
|
struct qeth_card *card;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
card = CARD_FROM_CDEV(channel->ccwdev);
|
card = CARD_FROM_CDEV(channel->ccwdev);
|
||||||
QETH_CARD_TEXT(card, 3, "clearch");
|
QETH_CARD_TEXT(card, 3, "clearch");
|
||||||
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
|
rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
|
||||||
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
@ -1565,15 +1563,14 @@ static int qeth_clear_channel(struct qeth_channel *channel)
|
|||||||
|
|
||||||
static int qeth_halt_channel(struct qeth_channel *channel)
|
static int qeth_halt_channel(struct qeth_channel *channel)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
struct qeth_card *card;
|
struct qeth_card *card;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
card = CARD_FROM_CDEV(channel->ccwdev);
|
card = CARD_FROM_CDEV(channel->ccwdev);
|
||||||
QETH_CARD_TEXT(card, 3, "haltch");
|
QETH_CARD_TEXT(card, 3, "haltch");
|
||||||
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
|
rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
|
||||||
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
@ -1667,7 +1664,6 @@ static int qeth_read_conf_data(struct qeth_card *card, void **buffer,
|
|||||||
char *rcd_buf;
|
char *rcd_buf;
|
||||||
int ret;
|
int ret;
|
||||||
struct qeth_channel *channel = &card->data;
|
struct qeth_channel *channel = &card->data;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* scan for RCD command in extended SenseID data
|
* scan for RCD command in extended SenseID data
|
||||||
@ -1681,11 +1677,11 @@ static int qeth_read_conf_data(struct qeth_card *card, void **buffer,
|
|||||||
|
|
||||||
qeth_setup_ccw(channel->ccw, ciw->cmd, ciw->count, rcd_buf);
|
qeth_setup_ccw(channel->ccw, ciw->cmd, ciw->count, rcd_buf);
|
||||||
channel->state = CH_STATE_RCD;
|
channel->state = CH_STATE_RCD;
|
||||||
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
ret = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
|
ret = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
|
||||||
QETH_RCD_PARM, LPM_ANYPATH, 0,
|
QETH_RCD_PARM, LPM_ANYPATH, 0,
|
||||||
QETH_RCD_TIMEOUT);
|
QETH_RCD_TIMEOUT);
|
||||||
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
if (!ret)
|
if (!ret)
|
||||||
wait_event(card->wait_q,
|
wait_event(card->wait_q,
|
||||||
(channel->state == CH_STATE_RCD_DONE ||
|
(channel->state == CH_STATE_RCD_DONE ||
|
||||||
@ -1843,7 +1839,6 @@ static int qeth_idx_activate_get_answer(struct qeth_channel *channel,
|
|||||||
struct qeth_cmd_buffer *))
|
struct qeth_cmd_buffer *))
|
||||||
{
|
{
|
||||||
struct qeth_cmd_buffer *iob;
|
struct qeth_cmd_buffer *iob;
|
||||||
unsigned long flags;
|
|
||||||
int rc;
|
int rc;
|
||||||
struct qeth_card *card;
|
struct qeth_card *card;
|
||||||
|
|
||||||
@ -1858,10 +1853,10 @@ static int qeth_idx_activate_get_answer(struct qeth_channel *channel,
|
|||||||
wait_event(card->wait_q,
|
wait_event(card->wait_q,
|
||||||
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
|
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
|
||||||
QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
|
QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
|
||||||
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
|
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
|
||||||
(addr_t) iob, 0, 0, QETH_TIMEOUT);
|
(addr_t) iob, 0, 0, QETH_TIMEOUT);
|
||||||
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
QETH_DBF_MESSAGE(2, "Error2 in activating channel rc=%d\n", rc);
|
QETH_DBF_MESSAGE(2, "Error2 in activating channel rc=%d\n", rc);
|
||||||
@ -1888,7 +1883,6 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel,
|
|||||||
{
|
{
|
||||||
struct qeth_card *card;
|
struct qeth_card *card;
|
||||||
struct qeth_cmd_buffer *iob;
|
struct qeth_cmd_buffer *iob;
|
||||||
unsigned long flags;
|
|
||||||
__u16 temp;
|
__u16 temp;
|
||||||
__u8 tmp;
|
__u8 tmp;
|
||||||
int rc;
|
int rc;
|
||||||
@ -1928,10 +1922,10 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel,
|
|||||||
wait_event(card->wait_q,
|
wait_event(card->wait_q,
|
||||||
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
|
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
|
||||||
QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
|
QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
|
||||||
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
|
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
|
||||||
(addr_t) iob, 0, 0, QETH_TIMEOUT);
|
(addr_t) iob, 0, 0, QETH_TIMEOUT);
|
||||||
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
QETH_DBF_MESSAGE(2, "Error1 in activating channel. rc=%d\n",
|
QETH_DBF_MESSAGE(2, "Error1 in activating channel. rc=%d\n",
|
||||||
@ -2112,7 +2106,6 @@ int qeth_send_control_data(struct qeth_card *card, int len,
|
|||||||
{
|
{
|
||||||
struct qeth_channel *channel = iob->channel;
|
struct qeth_channel *channel = iob->channel;
|
||||||
int rc;
|
int rc;
|
||||||
unsigned long flags;
|
|
||||||
struct qeth_reply *reply = NULL;
|
struct qeth_reply *reply = NULL;
|
||||||
unsigned long timeout, event_timeout;
|
unsigned long timeout, event_timeout;
|
||||||
struct qeth_ipa_cmd *cmd = NULL;
|
struct qeth_ipa_cmd *cmd = NULL;
|
||||||
@ -2145,26 +2138,26 @@ int qeth_send_control_data(struct qeth_card *card, int len,
|
|||||||
}
|
}
|
||||||
qeth_prepare_control_data(card, len, iob);
|
qeth_prepare_control_data(card, len, iob);
|
||||||
|
|
||||||
spin_lock_irqsave(&card->lock, flags);
|
spin_lock_irq(&card->lock);
|
||||||
list_add_tail(&reply->list, &card->cmd_waiter_list);
|
list_add_tail(&reply->list, &card->cmd_waiter_list);
|
||||||
spin_unlock_irqrestore(&card->lock, flags);
|
spin_unlock_irq(&card->lock);
|
||||||
|
|
||||||
timeout = jiffies + event_timeout;
|
timeout = jiffies + event_timeout;
|
||||||
|
|
||||||
QETH_CARD_TEXT(card, 6, "noirqpnd");
|
QETH_CARD_TEXT(card, 6, "noirqpnd");
|
||||||
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
|
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
|
||||||
(addr_t) iob, 0, 0, event_timeout);
|
(addr_t) iob, 0, 0, event_timeout);
|
||||||
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
if (rc) {
|
if (rc) {
|
||||||
QETH_DBF_MESSAGE(2, "%s qeth_send_control_data: "
|
QETH_DBF_MESSAGE(2, "%s qeth_send_control_data: "
|
||||||
"ccw_device_start rc = %i\n",
|
"ccw_device_start rc = %i\n",
|
||||||
dev_name(&channel->ccwdev->dev), rc);
|
dev_name(&channel->ccwdev->dev), rc);
|
||||||
QETH_CARD_TEXT_(card, 2, " err%d", rc);
|
QETH_CARD_TEXT_(card, 2, " err%d", rc);
|
||||||
spin_lock_irqsave(&card->lock, flags);
|
spin_lock_irq(&card->lock);
|
||||||
list_del_init(&reply->list);
|
list_del_init(&reply->list);
|
||||||
qeth_put_reply(reply);
|
qeth_put_reply(reply);
|
||||||
spin_unlock_irqrestore(&card->lock, flags);
|
spin_unlock_irq(&card->lock);
|
||||||
qeth_release_buffer(channel, iob);
|
qeth_release_buffer(channel, iob);
|
||||||
atomic_set(&channel->irq_pending, 0);
|
atomic_set(&channel->irq_pending, 0);
|
||||||
wake_up(&card->wait_q);
|
wake_up(&card->wait_q);
|
||||||
@ -2192,9 +2185,9 @@ int qeth_send_control_data(struct qeth_card *card, int len,
|
|||||||
|
|
||||||
time_err:
|
time_err:
|
||||||
reply->rc = -ETIME;
|
reply->rc = -ETIME;
|
||||||
spin_lock_irqsave(&reply->card->lock, flags);
|
spin_lock_irq(&card->lock);
|
||||||
list_del_init(&reply->list);
|
list_del_init(&reply->list);
|
||||||
spin_unlock_irqrestore(&reply->card->lock, flags);
|
spin_unlock_irq(&card->lock);
|
||||||
atomic_inc(&reply->received);
|
atomic_inc(&reply->received);
|
||||||
rc = reply->rc;
|
rc = reply->rc;
|
||||||
qeth_put_reply(reply);
|
qeth_put_reply(reply);
|
||||||
@ -5776,7 +5769,6 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
|
|||||||
struct device *dev;
|
struct device *dev;
|
||||||
int rc;
|
int rc;
|
||||||
enum qeth_discipline_id enforced_disc;
|
enum qeth_discipline_id enforced_disc;
|
||||||
unsigned long flags;
|
|
||||||
char dbf_name[DBF_NAME_LEN];
|
char dbf_name[DBF_NAME_LEN];
|
||||||
|
|
||||||
QETH_DBF_TEXT(SETUP, 2, "probedev");
|
QETH_DBF_TEXT(SETUP, 2, "probedev");
|
||||||
@ -5834,9 +5826,9 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
|
write_lock_irq(&qeth_core_card_list.rwlock);
|
||||||
list_add_tail(&card->list, &qeth_core_card_list.list);
|
list_add_tail(&card->list, &qeth_core_card_list.list);
|
||||||
write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
|
write_unlock_irq(&qeth_core_card_list.rwlock);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_disc:
|
err_disc:
|
||||||
@ -5852,7 +5844,6 @@ err_dev:
|
|||||||
|
|
||||||
static void qeth_core_remove_device(struct ccwgroup_device *gdev)
|
static void qeth_core_remove_device(struct ccwgroup_device *gdev)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||||
|
|
||||||
QETH_DBF_TEXT(SETUP, 2, "removedv");
|
QETH_DBF_TEXT(SETUP, 2, "removedv");
|
||||||
@ -5862,9 +5853,9 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev)
|
|||||||
qeth_core_free_discipline(card);
|
qeth_core_free_discipline(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
|
write_lock_irq(&qeth_core_card_list.rwlock);
|
||||||
list_del(&card->list);
|
list_del(&card->list);
|
||||||
write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
|
write_unlock_irq(&qeth_core_card_list.rwlock);
|
||||||
free_netdev(card->dev);
|
free_netdev(card->dev);
|
||||||
qeth_core_free_card(card);
|
qeth_core_free_card(card);
|
||||||
dev_set_drvdata(&gdev->dev, NULL);
|
dev_set_drvdata(&gdev->dev, NULL);
|
||||||
|
@ -1209,7 +1209,6 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len,
|
|||||||
struct qeth_cmd_buffer *iob)
|
struct qeth_cmd_buffer *iob)
|
||||||
{
|
{
|
||||||
struct qeth_channel *channel = iob->channel;
|
struct qeth_channel *channel = iob->channel;
|
||||||
unsigned long flags;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
QETH_CARD_TEXT(card, 5, "osndctrd");
|
QETH_CARD_TEXT(card, 5, "osndctrd");
|
||||||
@ -1218,10 +1217,10 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len,
|
|||||||
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
|
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
|
||||||
qeth_prepare_control_data(card, len, iob);
|
qeth_prepare_control_data(card, len, iob);
|
||||||
QETH_CARD_TEXT(card, 6, "osnoirqp");
|
QETH_CARD_TEXT(card, 6, "osnoirqp");
|
||||||
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
|
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
|
||||||
(addr_t) iob, 0, 0, QETH_IPA_TIMEOUT);
|
(addr_t) iob, 0, 0, QETH_IPA_TIMEOUT);
|
||||||
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||||
if (rc) {
|
if (rc) {
|
||||||
QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: "
|
QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: "
|
||||||
"ccw_device_start rc = %i\n", rc);
|
"ccw_device_start rc = %i\n", rc);
|
||||||
|
Reference in New Issue
Block a user