aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorDave C Boutcher <sleddog@us.ibm.com>2006-01-19 14:34:44 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2006-01-26 08:10:08 -0500
commit2b541f8f77fd339e4c5c5cbe8549b52445012704 (patch)
tree2df9275132ac1bdaadf6695e4d50132b8b955efd /drivers/scsi
parent2dbb04c65561122cc53b22dbea9aa59f9609215b (diff)
[SCSI] ibmvscsi: handle re-enable firmware message
New versions of the Power5 firmware can send a "re-enable" message to the virtual scsi adapter. This fix makes us handle the message correctly. Without it, the driver goes catatonic and the system crashes unpleasantly. Signed-off-by: Dave Boutcher <sleddog@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c67
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h3
-rw-r--r--drivers/scsi/ibmvscsi/iseries_vscsi.c13
-rw-r--r--drivers/scsi/ibmvscsi/rpa_vscsi.c22
4 files changed, 74 insertions, 31 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 822b9fa706f3..eaefeddb2b4a 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -87,7 +87,7 @@ static int max_channel = 3;
87static int init_timeout = 5; 87static int init_timeout = 5;
88static int max_requests = 50; 88static int max_requests = 50;
89 89
90#define IBMVSCSI_VERSION "1.5.7" 90#define IBMVSCSI_VERSION "1.5.8"
91 91
92MODULE_DESCRIPTION("IBM Virtual SCSI"); 92MODULE_DESCRIPTION("IBM Virtual SCSI");
93MODULE_AUTHOR("Dave Boutcher"); 93MODULE_AUTHOR("Dave Boutcher");
@@ -534,7 +534,6 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
534static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, 534static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
535 struct ibmvscsi_host_data *hostdata) 535 struct ibmvscsi_host_data *hostdata)
536{ 536{
537 struct scsi_cmnd *cmnd;
538 u64 *crq_as_u64 = (u64 *) &evt_struct->crq; 537 u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
539 int rc; 538 int rc;
540 539
@@ -544,19 +543,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
544 * can handle more requests (can_queue) when we actually can't 543 * can handle more requests (can_queue) when we actually can't
545 */ 544 */
546 if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) && 545 if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
547 (atomic_dec_if_positive(&hostdata->request_limit) < 0)) { 546 (atomic_dec_if_positive(&hostdata->request_limit) < 0))
548 /* See if the adapter is disabled */ 547 goto send_error;
549 if (atomic_read(&hostdata->request_limit) < 0)
550 goto send_error;
551
552 printk(KERN_WARNING
553 "ibmvscsi: Warning, request_limit exceeded\n");
554 unmap_cmd_data(&evt_struct->iu.srp.cmd,
555 evt_struct,
556 hostdata->dev);
557 free_event_struct(&hostdata->pool, evt_struct);
558 return SCSI_MLQUEUE_HOST_BUSY;
559 }
560 548
561 /* Copy the IU into the transfer area */ 549 /* Copy the IU into the transfer area */
562 *evt_struct->xfer_iu = evt_struct->iu; 550 *evt_struct->xfer_iu = evt_struct->iu;
@@ -572,7 +560,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
572 ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) { 560 ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
573 list_del(&evt_struct->list); 561 list_del(&evt_struct->list);
574 562
575 printk(KERN_ERR "ibmvscsi: failed to send event struct rc %d\n", 563 printk(KERN_ERR "ibmvscsi: send error %d\n",
576 rc); 564 rc);
577 goto send_error; 565 goto send_error;
578 } 566 }
@@ -582,14 +570,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
582 send_error: 570 send_error:
583 unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev); 571 unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
584 572
585 if ((cmnd = evt_struct->cmnd) != NULL) {
586 cmnd->result = DID_ERROR << 16;
587 evt_struct->cmnd_done(cmnd);
588 } else if (evt_struct->done)
589 evt_struct->done(evt_struct);
590
591 free_event_struct(&hostdata->pool, evt_struct); 573 free_event_struct(&hostdata->pool, evt_struct);
592 return 0; 574 return SCSI_MLQUEUE_HOST_BUSY;
593} 575}
594 576
595/** 577/**
@@ -802,7 +784,8 @@ static void login_rsp(struct srp_event_struct *evt_struct)
802 case SRP_LOGIN_RSP_TYPE: /* it worked! */ 784 case SRP_LOGIN_RSP_TYPE: /* it worked! */
803 break; 785 break;
804 case SRP_LOGIN_REJ_TYPE: /* refused! */ 786 case SRP_LOGIN_REJ_TYPE: /* refused! */
805 printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REQ rejected\n"); 787 printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REJ reason %u\n",
788 evt_struct->xfer_iu->srp.login_rej.reason);
806 /* Login failed. */ 789 /* Login failed. */
807 atomic_set(&hostdata->request_limit, -1); 790 atomic_set(&hostdata->request_limit, -1);
808 return; 791 return;
@@ -834,6 +817,9 @@ static void login_rsp(struct srp_event_struct *evt_struct)
834 return; 817 return;
835 } 818 }
836 819
820 /* If we had any pending I/Os, kick them */
821 scsi_unblock_requests(hostdata->host);
822
837 send_mad_adapter_info(hostdata); 823 send_mad_adapter_info(hostdata);
838 return; 824 return;
839} 825}
@@ -862,6 +848,7 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
862 init_timeout * HZ); 848 init_timeout * HZ);
863 849
864 login = &evt_struct->iu.srp.login_req; 850 login = &evt_struct->iu.srp.login_req;
851 memset(login, 0x00, sizeof(struct srp_login_req));
865 login->type = SRP_LOGIN_REQ_TYPE; 852 login->type = SRP_LOGIN_REQ_TYPE;
866 login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu); 853 login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu);
867 login->required_buffer_formats = 0x0006; 854 login->required_buffer_formats = 0x0006;
@@ -1122,7 +1109,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
1122 * purge_requests: Our virtual adapter just shut down. purge any sent requests 1109 * purge_requests: Our virtual adapter just shut down. purge any sent requests
1123 * @hostdata: the adapter 1110 * @hostdata: the adapter
1124 */ 1111 */
1125static void purge_requests(struct ibmvscsi_host_data *hostdata) 1112static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
1126{ 1113{
1127 struct srp_event_struct *tmp_evt, *pos; 1114 struct srp_event_struct *tmp_evt, *pos;
1128 unsigned long flags; 1115 unsigned long flags;
@@ -1131,7 +1118,7 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata)
1131 list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { 1118 list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
1132 list_del(&tmp_evt->list); 1119 list_del(&tmp_evt->list);
1133 if (tmp_evt->cmnd) { 1120 if (tmp_evt->cmnd) {
1134 tmp_evt->cmnd->result = (DID_ERROR << 16); 1121 tmp_evt->cmnd->result = (error_code << 16);
1135 unmap_cmd_data(&tmp_evt->iu.srp.cmd, 1122 unmap_cmd_data(&tmp_evt->iu.srp.cmd,
1136 tmp_evt, 1123 tmp_evt,
1137 tmp_evt->hostdata->dev); 1124 tmp_evt->hostdata->dev);
@@ -1186,12 +1173,30 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
1186 printk(KERN_ERR "ibmvscsi: unknown crq message type\n"); 1173 printk(KERN_ERR "ibmvscsi: unknown crq message type\n");
1187 } 1174 }
1188 return; 1175 return;
1189 case 0xFF: /* Hypervisor telling us the connection is closed */ 1176 case 0xFF: /* Hypervisor telling us the connection is closed */
1190 printk(KERN_INFO "ibmvscsi: Virtual adapter failed!\n"); 1177 scsi_block_requests(hostdata->host);
1178 if (crq->format == 0x06) {
1179 /* We need to re-setup the interpartition connection */
1180 printk(KERN_INFO
1181 "ibmvscsi: Re-enabling adapter!\n");
1182 purge_requests(hostdata, DID_REQUEUE);
1183 if (ibmvscsi_reenable_crq_queue(&hostdata->queue,
1184 hostdata) == 0)
1185 if (ibmvscsi_send_crq(hostdata,
1186 0xC001000000000000LL, 0))
1187 printk(KERN_ERR
1188 "ibmvscsi: transmit error after"
1189 " enable\n");
1190 } else {
1191 printk(KERN_INFO
1192 "ibmvscsi: Virtual adapter failed rc %d!\n",
1193 crq->format);
1191 1194
1192 atomic_set(&hostdata->request_limit, -1); 1195 atomic_set(&hostdata->request_limit, -1);
1193 purge_requests(hostdata); 1196 purge_requests(hostdata, DID_ERROR);
1194 ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata); 1197 ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata);
1198 }
1199 scsi_unblock_requests(hostdata->host);
1195 return; 1200 return;
1196 case 0x80: /* real payload */ 1201 case 0x80: /* real payload */
1197 break; 1202 break;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 5b0edd1f1921..4550d71e4744 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -103,6 +103,9 @@ void ibmvscsi_release_crq_queue(struct crq_queue *queue,
103int ibmvscsi_reset_crq_queue(struct crq_queue *queue, 103int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
104 struct ibmvscsi_host_data *hostdata); 104 struct ibmvscsi_host_data *hostdata);
105 105
106int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
107 struct ibmvscsi_host_data *hostdata);
108
106void ibmvscsi_handle_crq(struct viosrp_crq *crq, 109void ibmvscsi_handle_crq(struct viosrp_crq *crq,
107 struct ibmvscsi_host_data *hostdata); 110 struct ibmvscsi_host_data *hostdata);
108int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, 111int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
index ce15d9e39621..7eed0b098171 100644
--- a/drivers/scsi/ibmvscsi/iseries_vscsi.c
+++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c
@@ -124,6 +124,19 @@ int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
124} 124}
125 125
126/** 126/**
127 * reenable_crq_queue: - reenables a crq after a failure
128 * @queue: crq_queue to initialize and register
129 * @hostdata: ibmvscsi_host_data of host
130 *
131 * no-op for iSeries
132 */
133int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
134 struct ibmvscsi_host_data *hostdata)
135{
136 return 0;
137}
138
139/**
127 * ibmvscsi_send_crq: - Send a CRQ 140 * ibmvscsi_send_crq: - Send a CRQ
128 * @hostdata: the adapter 141 * @hostdata: the adapter
129 * @word1: the first 64 bits of the data 142 * @word1: the first 64 bits of the data
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index 75db2f5c545e..f47dd87c05e7 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -281,6 +281,28 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
281} 281}
282 282
283/** 283/**
284 * reenable_crq_queue: - reenables a crq after
285 * @queue: crq_queue to initialize and register
286 * @hostdata: ibmvscsi_host_data of host
287 *
288 */
289int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
290 struct ibmvscsi_host_data *hostdata)
291{
292 int rc;
293 struct vio_dev *vdev = to_vio_dev(hostdata->dev);
294
295 /* Re-enable the CRQ */
296 do {
297 rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address);
298 } while ((rc == H_InProgress) || (rc == H_Busy) || (H_isLongBusy(rc)));
299
300 if (rc)
301 printk(KERN_ERR "ibmvscsi: Error %d enabling adapter\n", rc);
302 return rc;
303}
304
305/**
284 * reset_crq_queue: - resets a crq after a failure 306 * reset_crq_queue: - resets a crq after a failure
285 * @queue: crq_queue to initialize and register 307 * @queue: crq_queue to initialize and register
286 * @hostdata: ibmvscsi_host_data of host 308 * @hostdata: ibmvscsi_host_data of host