| @@ -806,6 +806,22 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code) · 805 unmodified lines |
| 806 | 806 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); |
| 807 | 807 | } |
| 808 | 808 | |
| 809 | +/** |
| 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 | + |
| 809 | 825 | /** |
| 810 | 826 | * ibmvscsi_reset_host - Reset the connection to the server |
| 811 | 827 | * @hostdata: struct ibmvscsi_host_data to reset |
| @@ -813,7 +829,7 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code) · 1 unmodified line |
| 813 | 829 | static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata) |
| 814 | 830 | { |
| 815 | 831 | scsi_block_requests(hostdata->host); |
| 816 | | − atomic_set(&hostdata->request_limit, 0); |
| 832 | + ibmvscsi_set_request_limit(hostdata, 0); |
| 817 | 833 | |
| 818 | 834 | purge_requests(hostdata, DID_ERROR); |
| 819 | 835 | hostdata->action = IBMVSCSI_HOST_ACTION_RESET; |
| @@ -1146,13 +1162,13 @@ static void login_rsp(struct srp_event_struct *evt_struct) · 326 unmodified lines |
| 1146 | 1162 | dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n", |
| 1147 | 1163 | evt_struct->xfer_iu->srp.login_rej.reason); |
| 1148 | 1164 | /* Login failed. */ |
| 1149 | | − atomic_set(&hostdata->request_limit, -1); |
| 1165 | + ibmvscsi_set_request_limit(hostdata, -1); |
| 1150 | 1166 | return; |
| 1151 | 1167 | default: |
| 1152 | 1168 | dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n", |
| 1153 | 1169 | evt_struct->xfer_iu->srp.login_rsp.opcode); |
| 1154 | 1170 | /* Login failed. */ |
| 1155 | | − atomic_set(&hostdata->request_limit, -1); |
| 1171 | + ibmvscsi_set_request_limit(hostdata, -1); |
| 1156 | 1172 | return; |
| 1157 | 1173 | } |
| 1158 | 1174 | |
| @@ -1163,7 +1179,7 @@ static void login_rsp(struct srp_event_struct *evt_struct) · 4 unmodified lines |
| 1163 | 1179 | * This value is set rather than added to request_limit because |
| 1164 | 1180 | * request_limit could have been set to -1 by this client. |
| 1165 | 1181 | */ |
| 1166 | | − atomic_set(&hostdata->request_limit, |
| 1182 | + ibmvscsi_set_request_limit(hostdata, |
| 1167 | 1183 | be32_to_cpu(evt_struct->xfer_iu->srp.login_rsp.req_lim_delta)); |
| 1168 | 1184 | |
| 1169 | 1185 | /* If we had any pending I/Os, kick them */ |
| @@ -1195,13 +1211,13 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata) · 25 unmodified lines |
| 1195 | 1211 | login->req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT | |
| 1196 | 1212 | SRP_BUF_FORMAT_INDIRECT); |
| 1197 | 1213 | |
| 1198 | | − spin_lock_irqsave(hostdata->host->host_lock, flags); |
| 1199 | 1214 | /* Start out with a request limit of 0, since this is negotiated in |
| 1200 | 1215 | * the login request we are just sending and login requests always |
| 1201 | 1216 | * get sent by the driver regardless of request_limit. |
| 1202 | 1217 | */ |
| 1203 | | − atomic_set(&hostdata->request_limit, 0); |
| 1218 | + ibmvscsi_set_request_limit(hostdata, 0); |
| 1204 | 1219 | |
| 1220 | + spin_lock_irqsave(hostdata->host->host_lock, flags); |
| 1205 | 1221 | rc = ibmvscsi_send_srp_event(evt_struct, hostdata, login_timeout * 2); |
| 1206 | 1222 | spin_unlock_irqrestore(hostdata->host->host_lock, flags); |
| 1207 | 1223 | dev_info(hostdata->dev, "sent SRP login\n"); |
| @@ -1781,7 +1797,7 @@ static void ibmvscsi_handle_crq(struct viosrp_crq *crq, · 573 unmodified lines |
| 1781 | 1797 | return; |
| 1782 | 1798 | case VIOSRP_CRQ_XPORT_EVENT: /* Hypervisor telling us the connection is closed */ |
| 1783 | 1799 | scsi_block_requests(hostdata->host); |
| 1784 | | − atomic_set(&hostdata->request_limit, 0); |
| 1800 | + ibmvscsi_set_request_limit(hostdata, 0); |
| 1785 | 1801 | if (crq->format == 0x06) { |
| 1786 | 1802 | /* We need to re-setup the interpartition connection */ |
| 1787 | 1803 | dev_info(hostdata->dev, "Re-enabling adapter!\n"); |
| @@ -2137,12 +2153,12 @@ static void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata) · 349 unmodified lines |
| 2137 | 2153 | } |
| 2138 | 2154 | |
| 2139 | 2155 | hostdata->action = IBMVSCSI_HOST_ACTION_NONE; |
| 2156 | + spin_unlock_irqrestore(hostdata->host->host_lock, flags); |
| 2140 | 2157 | |
| 2141 | 2158 | if (rc) { |
| 2142 | | − atomic_set(&hostdata->request_limit, -1); |
| 2159 | + ibmvscsi_set_request_limit(hostdata, -1); |
| 2143 | 2160 | dev_err(hostdata->dev, "error after %s\n", action); |
| 2144 | 2161 | } |
| 2145 | | − spin_unlock_irqrestore(hostdata->host->host_lock, flags); |
| 2146 | 2162 | |
| 2147 | 2163 | scsi_unblock_requests(hostdata->host); |
| 2148 | 2164 | } |
| @@ -2226,7 +2242,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) · 77 unmodified lines |
| 2226 | 2242 | init_waitqueue_head(&hostdata->work_wait_q); |
| 2227 | 2243 | hostdata->host = host; |
| 2228 | 2244 | hostdata->dev = dev; |
| 2229 | | − atomic_set(&hostdata->request_limit, -1); |
| 2245 | + ibmvscsi_set_request_limit(hostdata, -1); |
| 2230 | 2246 | hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT; |
| 2231 | 2247 | |
| 2232 | 2248 | if (map_persist_bufs(hostdata)) { |