hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/scsi/ibmvscsi/ibmvscsi.c
....@@ -1,24 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* ------------------------------------------------------------
23 * ibmvscsi.c
34 * (C) Copyright IBM Corporation 1994, 2004
45 * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
56 * Santiago Leon (santil@us.ibm.com)
67 * Dave Boutcher (sleddog@us.ibm.com)
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version.
12
- *
13
- * This program is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- * GNU General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU General Public License
19
- * along with this program; if not, write to the Free Software
20
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21
- * USA
228 *
239 * ------------------------------------------------------------
2410 * Emulation of a SCSI host adapter for Virtual I/O devices
....@@ -683,7 +669,7 @@
683669 }
684670
685671 /**
686
- * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields
672
+ * map_sg_data: - Maps dma for a scatterlist and initializes descriptor fields
687673 * @cmd: struct scsi_cmnd with the scatterlist
688674 * @srp_cmd: srp_cmd that contains the memory descriptor
689675 * @dev: device for which to map dma memory
....@@ -821,16 +807,32 @@
821807 }
822808
823809 /**
810
+ * ibmvscsi_set_request_limit - Set the adapter request_limit in response to
811
+ * an adapter failure, reset, or SRP Login. Done under host lock to prevent
812
+ * race with SCSI command submission.
813
+ * @hostdata: adapter to adjust
814
+ * @limit: new request limit
815
+ */
816
+static void ibmvscsi_set_request_limit(struct ibmvscsi_host_data *hostdata, int limit)
817
+{
818
+ unsigned long flags;
819
+
820
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
821
+ atomic_set(&hostdata->request_limit, limit);
822
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
823
+}
824
+
825
+/**
824826 * ibmvscsi_reset_host - Reset the connection to the server
825827 * @hostdata: struct ibmvscsi_host_data to reset
826828 */
827829 static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
828830 {
829831 scsi_block_requests(hostdata->host);
830
- atomic_set(&hostdata->request_limit, 0);
832
+ ibmvscsi_set_request_limit(hostdata, 0);
831833
832834 purge_requests(hostdata, DID_ERROR);
833
- hostdata->reset_crq = 1;
835
+ hostdata->action = IBMVSCSI_HOST_ACTION_RESET;
834836 wake_up(&hostdata->work_wait_q);
835837 }
836838
....@@ -1160,13 +1162,13 @@
11601162 dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n",
11611163 evt_struct->xfer_iu->srp.login_rej.reason);
11621164 /* Login failed. */
1163
- atomic_set(&hostdata->request_limit, -1);
1165
+ ibmvscsi_set_request_limit(hostdata, -1);
11641166 return;
11651167 default:
11661168 dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n",
11671169 evt_struct->xfer_iu->srp.login_rsp.opcode);
11681170 /* Login failed. */
1169
- atomic_set(&hostdata->request_limit, -1);
1171
+ ibmvscsi_set_request_limit(hostdata, -1);
11701172 return;
11711173 }
11721174
....@@ -1177,11 +1179,12 @@
11771179 * This value is set rather than added to request_limit because
11781180 * request_limit could have been set to -1 by this client.
11791181 */
1180
- atomic_set(&hostdata->request_limit,
1182
+ ibmvscsi_set_request_limit(hostdata,
11811183 be32_to_cpu(evt_struct->xfer_iu->srp.login_rsp.req_lim_delta));
11821184
11831185 /* If we had any pending I/Os, kick them */
1184
- scsi_unblock_requests(hostdata->host);
1186
+ hostdata->action = IBMVSCSI_HOST_ACTION_UNBLOCK;
1187
+ wake_up(&hostdata->work_wait_q);
11851188 }
11861189
11871190 /**
....@@ -1208,13 +1211,13 @@
12081211 login->req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
12091212 SRP_BUF_FORMAT_INDIRECT);
12101213
1211
- spin_lock_irqsave(hostdata->host->host_lock, flags);
12121214 /* Start out with a request limit of 0, since this is negotiated in
12131215 * the login request we are just sending and login requests always
12141216 * get sent by the driver regardless of request_limit.
12151217 */
1216
- atomic_set(&hostdata->request_limit, 0);
1218
+ ibmvscsi_set_request_limit(hostdata, 0);
12171219
1220
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
12181221 rc = ibmvscsi_send_srp_event(evt_struct, hostdata, login_timeout * 2);
12191222 spin_unlock_irqrestore(hostdata->host->host_lock, flags);
12201223 dev_info(hostdata->dev, "sent SRP login\n");
....@@ -1794,12 +1797,12 @@
17941797 return;
17951798 case VIOSRP_CRQ_XPORT_EVENT: /* Hypervisor telling us the connection is closed */
17961799 scsi_block_requests(hostdata->host);
1797
- atomic_set(&hostdata->request_limit, 0);
1800
+ ibmvscsi_set_request_limit(hostdata, 0);
17981801 if (crq->format == 0x06) {
17991802 /* We need to re-setup the interpartition connection */
18001803 dev_info(hostdata->dev, "Re-enabling adapter!\n");
18011804 hostdata->client_migrated = 1;
1802
- hostdata->reenable_crq = 1;
1805
+ hostdata->action = IBMVSCSI_HOST_ACTION_REENABLE;
18031806 purge_requests(hostdata, DID_REQUEUE);
18041807 wake_up(&hostdata->work_wait_q);
18051808 } else {
....@@ -2052,6 +2055,16 @@
20522055 .show = show_host_config,
20532056 };
20542057
2058
+static int ibmvscsi_host_reset(struct Scsi_Host *shost, int reset_type)
2059
+{
2060
+ struct ibmvscsi_host_data *hostdata = shost_priv(shost);
2061
+
2062
+ dev_info(hostdata->dev, "Initiating adapter reset!\n");
2063
+ ibmvscsi_reset_host(hostdata);
2064
+
2065
+ return 0;
2066
+}
2067
+
20552068 static struct device_attribute *ibmvscsi_attrs[] = {
20562069 &ibmvscsi_host_vhost_loc,
20572070 &ibmvscsi_host_vhost_name,
....@@ -2078,11 +2091,11 @@
20782091 .eh_host_reset_handler = ibmvscsi_eh_host_reset_handler,
20792092 .slave_configure = ibmvscsi_slave_configure,
20802093 .change_queue_depth = ibmvscsi_change_queue_depth,
2094
+ .host_reset = ibmvscsi_host_reset,
20812095 .cmd_per_lun = IBMVSCSI_CMDS_PER_LUN_DEFAULT,
20822096 .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
20832097 .this_id = -1,
20842098 .sg_tablesize = SG_ALL,
2085
- .use_clustering = ENABLE_CLUSTERING,
20862099 .shost_attrs = ibmvscsi_attrs,
20872100 };
20882101
....@@ -2108,48 +2121,75 @@
21082121
21092122 static void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata)
21102123 {
2124
+ unsigned long flags;
21112125 int rc;
21122126 char *action = "reset";
21132127
2114
- if (hostdata->reset_crq) {
2115
- smp_rmb();
2116
- hostdata->reset_crq = 0;
2117
-
2128
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
2129
+ switch (hostdata->action) {
2130
+ case IBMVSCSI_HOST_ACTION_UNBLOCK:
2131
+ rc = 0;
2132
+ break;
2133
+ case IBMVSCSI_HOST_ACTION_RESET:
2134
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
21182135 rc = ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata);
2136
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
21192137 if (!rc)
21202138 rc = ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0);
21212139 vio_enable_interrupts(to_vio_dev(hostdata->dev));
2122
- } else if (hostdata->reenable_crq) {
2123
- smp_rmb();
2140
+ break;
2141
+ case IBMVSCSI_HOST_ACTION_REENABLE:
21242142 action = "enable";
2143
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
21252144 rc = ibmvscsi_reenable_crq_queue(&hostdata->queue, hostdata);
2126
- hostdata->reenable_crq = 0;
2145
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
21272146 if (!rc)
21282147 rc = ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0);
2129
- } else
2148
+ break;
2149
+ case IBMVSCSI_HOST_ACTION_NONE:
2150
+ default:
2151
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
21302152 return;
2153
+ }
2154
+
2155
+ hostdata->action = IBMVSCSI_HOST_ACTION_NONE;
2156
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
21312157
21322158 if (rc) {
2133
- atomic_set(&hostdata->request_limit, -1);
2159
+ ibmvscsi_set_request_limit(hostdata, -1);
21342160 dev_err(hostdata->dev, "error after %s\n", action);
21352161 }
21362162
21372163 scsi_unblock_requests(hostdata->host);
21382164 }
21392165
2140
-static int ibmvscsi_work_to_do(struct ibmvscsi_host_data *hostdata)
2166
+static int __ibmvscsi_work_to_do(struct ibmvscsi_host_data *hostdata)
21412167 {
21422168 if (kthread_should_stop())
21432169 return 1;
2144
- else if (hostdata->reset_crq) {
2145
- smp_rmb();
2146
- return 1;
2147
- } else if (hostdata->reenable_crq) {
2148
- smp_rmb();
2149
- return 1;
2170
+ switch (hostdata->action) {
2171
+ case IBMVSCSI_HOST_ACTION_NONE:
2172
+ return 0;
2173
+ case IBMVSCSI_HOST_ACTION_RESET:
2174
+ case IBMVSCSI_HOST_ACTION_REENABLE:
2175
+ case IBMVSCSI_HOST_ACTION_UNBLOCK:
2176
+ default:
2177
+ break;
21502178 }
21512179
2152
- return 0;
2180
+ return 1;
2181
+}
2182
+
2183
+static int ibmvscsi_work_to_do(struct ibmvscsi_host_data *hostdata)
2184
+{
2185
+ unsigned long flags;
2186
+ int rc;
2187
+
2188
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
2189
+ rc = __ibmvscsi_work_to_do(hostdata);
2190
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
2191
+
2192
+ return rc;
21532193 }
21542194
21552195 static int ibmvscsi_work(void *data)
....@@ -2202,7 +2242,7 @@
22022242 init_waitqueue_head(&hostdata->work_wait_q);
22032243 hostdata->host = host;
22042244 hostdata->dev = dev;
2205
- atomic_set(&hostdata->request_limit, -1);
2245
+ ibmvscsi_set_request_limit(hostdata, -1);
22062246 hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT;
22072247
22082248 if (map_persist_bufs(hostdata)) {
....@@ -2362,7 +2402,7 @@
23622402 static struct srp_function_template ibmvscsi_transport_functions = {
23632403 };
23642404
2365
-int __init ibmvscsi_module_init(void)
2405
+static int __init ibmvscsi_module_init(void)
23662406 {
23672407 int ret;
23682408
....@@ -2384,7 +2424,7 @@
23842424 return ret;
23852425 }
23862426
2387
-void __exit ibmvscsi_module_exit(void)
2427
+static void __exit ibmvscsi_module_exit(void)
23882428 {
23892429 vio_unregister_driver(&ibmvscsi_driver);
23902430 srp_release_transport(ibmvscsi_transport_template);