diff options
author | Ursula Braun <ursula.braun@de.ibm.com> | 2011-02-02 01:04:34 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-02-02 18:00:01 -0500 |
commit | d0ff1f52361d714863c49abb721a8714ea4e76d6 (patch) | |
tree | a7fe4ddcb49a0b38d0cbf713664df5f4c19d73cd /drivers/s390 | |
parent | 8b2e18f662939fb3d9b0ffe5da953ba56d259e3a (diff) |
qeth: allow OSA CHPARM change in suspend state
For OSA the CHPARM-definition determines the number of available
outbound queues.
A CHPARM-change may occur while a Linux system with probed
OSA device is in suspend state. This patch enables proper
resuming of an OSA device in this case.
Signed-off-by: Ursula braun <ursula.braun@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 104 |
1 files changed, 63 insertions, 41 deletions
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index eca3e094031a..019ae58ab913 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -988,16 +988,30 @@ static void qeth_get_channel_path_desc(struct qeth_card *card) | |||
988 | chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0); | 988 | chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0); |
989 | if (chp_dsc != NULL) { | 989 | if (chp_dsc != NULL) { |
990 | /* CHPP field bit 6 == 1 -> single queue */ | 990 | /* CHPP field bit 6 == 1 -> single queue */ |
991 | if ((chp_dsc->chpp & 0x02) == 0x02) | 991 | if ((chp_dsc->chpp & 0x02) == 0x02) { |
992 | if ((atomic_read(&card->qdio.state) != | ||
993 | QETH_QDIO_UNINITIALIZED) && | ||
994 | (card->qdio.no_out_queues == 4)) | ||
995 | /* change from 4 to 1 outbound queues */ | ||
996 | qeth_free_qdio_buffers(card); | ||
992 | card->qdio.no_out_queues = 1; | 997 | card->qdio.no_out_queues = 1; |
998 | if (card->qdio.default_out_queue != 0) | ||
999 | dev_info(&card->gdev->dev, | ||
1000 | "Priority Queueing not supported\n"); | ||
1001 | card->qdio.default_out_queue = 0; | ||
1002 | } else { | ||
1003 | if ((atomic_read(&card->qdio.state) != | ||
1004 | QETH_QDIO_UNINITIALIZED) && | ||
1005 | (card->qdio.no_out_queues == 1)) { | ||
1006 | /* change from 1 to 4 outbound queues */ | ||
1007 | qeth_free_qdio_buffers(card); | ||
1008 | card->qdio.default_out_queue = 2; | ||
1009 | } | ||
1010 | card->qdio.no_out_queues = 4; | ||
1011 | } | ||
993 | card->info.func_level = 0x4100 + chp_dsc->desc; | 1012 | card->info.func_level = 0x4100 + chp_dsc->desc; |
994 | kfree(chp_dsc); | 1013 | kfree(chp_dsc); |
995 | } | 1014 | } |
996 | if (card->qdio.no_out_queues == 1) { | ||
997 | card->qdio.default_out_queue = 0; | ||
998 | dev_info(&card->gdev->dev, | ||
999 | "Priority Queueing not supported\n"); | ||
1000 | } | ||
1001 | QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues); | 1015 | QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues); |
1002 | QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level); | 1016 | QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level); |
1003 | return; | 1017 | return; |
@@ -3756,6 +3770,47 @@ static inline int qeth_get_qdio_q_format(struct qeth_card *card) | |||
3756 | } | 3770 | } |
3757 | } | 3771 | } |
3758 | 3772 | ||
3773 | static void qeth_determine_capabilities(struct qeth_card *card) | ||
3774 | { | ||
3775 | int rc; | ||
3776 | int length; | ||
3777 | char *prcd; | ||
3778 | struct ccw_device *ddev; | ||
3779 | int ddev_offline = 0; | ||
3780 | |||
3781 | QETH_DBF_TEXT(SETUP, 2, "detcapab"); | ||
3782 | ddev = CARD_DDEV(card); | ||
3783 | if (!ddev->online) { | ||
3784 | ddev_offline = 1; | ||
3785 | rc = ccw_device_set_online(ddev); | ||
3786 | if (rc) { | ||
3787 | QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); | ||
3788 | goto out; | ||
3789 | } | ||
3790 | } | ||
3791 | |||
3792 | rc = qeth_read_conf_data(card, (void **) &prcd, &length); | ||
3793 | if (rc) { | ||
3794 | QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n", | ||
3795 | dev_name(&card->gdev->dev), rc); | ||
3796 | QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); | ||
3797 | goto out_offline; | ||
3798 | } | ||
3799 | qeth_configure_unitaddr(card, prcd); | ||
3800 | qeth_configure_blkt_default(card, prcd); | ||
3801 | kfree(prcd); | ||
3802 | |||
3803 | rc = qdio_get_ssqd_desc(ddev, &card->ssqd); | ||
3804 | if (rc) | ||
3805 | QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); | ||
3806 | |||
3807 | out_offline: | ||
3808 | if (ddev_offline == 1) | ||
3809 | ccw_device_set_offline(ddev); | ||
3810 | out: | ||
3811 | return; | ||
3812 | } | ||
3813 | |||
3759 | static int qeth_qdio_establish(struct qeth_card *card) | 3814 | static int qeth_qdio_establish(struct qeth_card *card) |
3760 | { | 3815 | { |
3761 | struct qdio_initialize init_data; | 3816 | struct qdio_initialize init_data; |
@@ -3886,6 +3941,7 @@ int qeth_core_hardsetup_card(struct qeth_card *card) | |||
3886 | 3941 | ||
3887 | QETH_DBF_TEXT(SETUP, 2, "hrdsetup"); | 3942 | QETH_DBF_TEXT(SETUP, 2, "hrdsetup"); |
3888 | atomic_set(&card->force_alloc_skb, 0); | 3943 | atomic_set(&card->force_alloc_skb, 0); |
3944 | qeth_get_channel_path_desc(card); | ||
3889 | retry: | 3945 | retry: |
3890 | if (retries) | 3946 | if (retries) |
3891 | QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", | 3947 | QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", |
@@ -3914,6 +3970,7 @@ retriable: | |||
3914 | else | 3970 | else |
3915 | goto retry; | 3971 | goto retry; |
3916 | } | 3972 | } |
3973 | qeth_determine_capabilities(card); | ||
3917 | qeth_init_tokens(card); | 3974 | qeth_init_tokens(card); |
3918 | qeth_init_func_level(card); | 3975 | qeth_init_func_level(card); |
3919 | rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb); | 3976 | rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb); |
@@ -4183,41 +4240,6 @@ void qeth_core_free_discipline(struct qeth_card *card) | |||
4183 | card->discipline.ccwgdriver = NULL; | 4240 | card->discipline.ccwgdriver = NULL; |
4184 | } | 4241 | } |
4185 | 4242 | ||
4186 | static void qeth_determine_capabilities(struct qeth_card *card) | ||
4187 | { | ||
4188 | int rc; | ||
4189 | int length; | ||
4190 | char *prcd; | ||
4191 | |||
4192 | QETH_DBF_TEXT(SETUP, 2, "detcapab"); | ||
4193 | rc = ccw_device_set_online(CARD_DDEV(card)); | ||
4194 | if (rc) { | ||
4195 | QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); | ||
4196 | goto out; | ||
4197 | } | ||
4198 | |||
4199 | |||
4200 | rc = qeth_read_conf_data(card, (void **) &prcd, &length); | ||
4201 | if (rc) { | ||
4202 | QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n", | ||
4203 | dev_name(&card->gdev->dev), rc); | ||
4204 | QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); | ||
4205 | goto out_offline; | ||
4206 | } | ||
4207 | qeth_configure_unitaddr(card, prcd); | ||
4208 | qeth_configure_blkt_default(card, prcd); | ||
4209 | kfree(prcd); | ||
4210 | |||
4211 | rc = qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd); | ||
4212 | if (rc) | ||
4213 | QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); | ||
4214 | |||
4215 | out_offline: | ||
4216 | ccw_device_set_offline(CARD_DDEV(card)); | ||
4217 | out: | ||
4218 | return; | ||
4219 | } | ||
4220 | |||
4221 | static int qeth_core_probe_device(struct ccwgroup_device *gdev) | 4243 | static int qeth_core_probe_device(struct ccwgroup_device *gdev) |
4222 | { | 4244 | { |
4223 | struct qeth_card *card; | 4245 | struct qeth_card *card; |