Changeset 8 for trunk/src/ctxhook.c


Ignore:
Timestamp:
Sep 10, 2010, 11:30:39 AM (15 years ago)
Author:
markus
Message:

latest changes by Christian

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/ctxhook.c

    r4 r8  
    8282void restart_ctxhook(ULONG parm)
    8383{
     84  IORB_QUEUE done_queue;
    8485  AD_INFO *ai;
    8586  IORBH _far *problem_iorb;
     
    9293  int a;
    9394  int p;
    94   int d;
    9595
    9696  dprintf("restart_ctxhook() started\n");
     97  memset(&done_queue, 0x00, sizeof(done_queue));
     98
    9799  spin_lock(drv_lock);
    98100
     
    108110    for (p = 0; p <= ai->port_max; p++) {
    109111      if (ports_to_restart[a] & (1UL << p)) {
     112        ports_to_restart[a] &= ~(1UL << p);
    110113
    111114        /* restart this port */
    112         ports_to_restart[a] &= ~(1UL << p);
    113115        port_mmio = port_base(ai, p);
    114116        problem_iorb = NULL;
     
    124126          if (aws->queued_hw) {
    125127            if (ai->ports[p].ncq_cmds != 0) {
     128              /* NCQ commands active; force non-NCQ mode and trigger port reset */
     129              aws->no_ncq = 1;
    126130              need_reset = 1;
    127131            } else if (aws->cmd_slot == ccs) {
     
    129133              problem_iorb = iorb;
    130134            }
    131 
    132             /* requeue this command with the 'no_ncq' flag set */
    133             aws_free(aws);
    134             memset(&iorb->ADDWorkSpace, sizeof(iorb->ADDWorkSpace), 0x00);
    135             aws->no_ncq = 1;
     135            iorb_requeue(iorb);
    136136
    137137            /* remove requeued command from the issued command bitmaps */
     
    166166        ai->busy = 0;
    167167
    168         /* reset port status */
    169         ai->ports[p].cmd_slot = 0;
     168        /* reset internal port status */
    170169        ai->ports[p].ncq_cmds = 0;
    171170        ai->ports[p].reg_cmds = 0;
    172 
    173         if (!need_reset && problem_iorb != NULL) {
    174           /* request sense data for the failing command in cmd slot #0 */
    175           ADD_WORKSPACE _far *aws = add_workspace(problem_iorb);
    176           aws->processing = 1;
    177           aws->queued_hw = 1;
    178           d = iorb_unit_device(problem_iorb);
    179           if (ai->ports[p].devs[d].atapi) {
    180             atapi_req_sense(problem_iorb, 0);
     171        ai->ports[p].cmd_slot = 0;
     172
     173        if (problem_iorb != NULL) {
     174          /* get details about the error that caused this IORB to fail */
     175          if (need_reset) {
     176            /* no way to retrieve error details after a reset */
     177            iorb_seterr(problem_iorb, IOERR_DEVICE_NONSPECIFIC);
     178            iorb_queue_del(&ai->ports[p].iorb_queue, problem_iorb);
     179            iorb_queue_add(&done_queue, problem_iorb);
     180
    181181          } else {
    182             ata_req_sense(problem_iorb, 0);
     182            /* get sense information */
     183            ADD_WORKSPACE _far *aws = add_workspace(problem_iorb);
     184            int d = iorb_unit_device(problem_iorb);
     185            int (*req_sense)(IORBH _far *, int) =
     186              (ai->ports[p].devs[d].atapi) ? atapi_req_sense : ata_req_sense;
     187
     188            aws->processing = 1;
     189            aws->queued_hw = 1;
     190
     191            if (req_sense(problem_iorb, 0) == 0) {
     192              /* execute request sense on slot #0 before anything else comes along */
     193              ai->ports[p].reg_cmds = 1;
     194              writel(port_mmio + PORT_CMD_ISSUE, 1);
     195              readl(port_mmio); /* flush */
     196
     197            } else {
     198              /* IORB is expected to contain the error code; just move to done queue */
     199              iorb_queue_del(&ai->ports[p].iorb_queue, problem_iorb);
     200              iorb_queue_add(&done_queue, problem_iorb);
     201            }
    183202          }
    184           ai->ports[p].reg_cmds = 1;
    185           writel(port_mmio + PORT_CMD_ISSUE, 1);
    186           readl(port_mmio); /* flush */
    187203        }
    188204      }
     
    190206  }
    191207
     208  spin_unlock(drv_lock);
     209
     210  /* call notification routine on all IORBs which have completed */
     211  for (iorb = done_queue.root; iorb != NULL; iorb = next) {
     212    next = iorb->pNxtIORB;
     213    if (iorb->RequestControl & IORB_ASYNC_POST) {
     214      iorb->NotifyAddress(iorb);
     215    }
     216  }
     217
    192218  /* restart engine to resume IORB processing */
     219  spin_lock(drv_lock);
    193220  trigger_engine();
    194221  spin_unlock(drv_lock);
     
    283310    for (p = 0; p <= ai->port_max; p++) {
    284311      if (ports_to_reset[a] & (1UL << p)) {
     312        ports_to_reset[a] &= ~(1UL << p);
     313
    285314        /* Reset this port. Since this is a rather slow operation, we'll
    286315         * release the spinlock while doing so. The adapter is marked as
     
    288317         * interfering.
    289318         */
    290         ports_to_reset[a] &= ~(1UL << p);
    291319        ai->busy = 1;
    292320        spin_unlock(drv_lock);
Note: See TracChangeset for help on using the changeset viewer.