diff options
Diffstat (limited to 'drivers/scsi/aacraid/commsup.c')
-rw-r--r-- | drivers/scsi/aacraid/commsup.c | 96 |
1 files changed, 73 insertions, 23 deletions
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index cab190af6345..4da574925284 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -208,14 +208,10 @@ struct fib *aac_fib_alloc(struct aac_dev *dev) void aac_fib_free(struct fib *fibptr) { - unsigned long flags, flagsv; + unsigned long flags; - spin_lock_irqsave(&fibptr->event_lock, flagsv); - if (fibptr->done == 2) { - spin_unlock_irqrestore(&fibptr->event_lock, flagsv); + if (fibptr->done == 2) return; - } - spin_unlock_irqrestore(&fibptr->event_lock, flagsv); spin_lock_irqsave(&fibptr->dev->fib_lock, flags); if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) @@ -321,7 +317,7 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr /* Queue is full */ if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { printk(KERN_WARNING "Queue %d full, %u outstanding.\n", - qid, q->numpending); + qid, atomic_read(&q->numpending)); return 0; } else { *entry = q->base + *index; @@ -414,7 +410,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, struct aac_dev * dev = fibptr->dev; struct hw_fib * hw_fib = fibptr->hw_fib_va; unsigned long flags = 0; - unsigned long qflags; unsigned long mflags = 0; unsigned long sflags = 0; @@ -568,9 +563,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, int blink; if (time_is_before_eq_jiffies(timeout)) { struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue]; - spin_lock_irqsave(q->lock, qflags); - q->numpending--; - spin_unlock_irqrestore(q->lock, qflags); + atomic_dec(&q->numpending); if (wait == -1) { printk(KERN_ERR "aacraid: aac_fib_send: first asynchronous command timed out.\n" "Usually a result of a PCI interrupt routing problem;\n" @@ -775,7 +768,6 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) int aac_fib_complete(struct fib *fibptr) { - unsigned long flags; struct hw_fib * hw_fib = fibptr->hw_fib_va; /* @@ -798,12 +790,6 @@ int aac_fib_complete(struct fib *fibptr) * command is complete that we had sent to the adapter and this * cdb could be reused. */ - spin_lock_irqsave(&fibptr->event_lock, flags); - if (fibptr->done == 2) { - spin_unlock_irqrestore(&fibptr->event_lock, flags); - return 0; - } - spin_unlock_irqrestore(&fibptr->event_lock, flags); if((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) && (hw_fib->header.XferState & cpu_to_le32(AdapterProcessed))) @@ -868,7 +854,7 @@ void aac_printf(struct aac_dev *dev, u32 val) * dispatches it to the appropriate routine for handling. */ -#define AIF_SNIFF_TIMEOUT (30*HZ) +#define AIF_SNIFF_TIMEOUT (500*HZ) static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) { struct hw_fib * hw_fib = fibptr->hw_fib_va; @@ -897,6 +883,39 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) switch (le32_to_cpu(aifcmd->command)) { case AifCmdDriverNotify: switch (le32_to_cpu(((__le32 *)aifcmd->data)[0])) { + case AifRawDeviceRemove: + container = le32_to_cpu(((__le32 *)aifcmd->data)[1]); + if ((container >> 28)) { + container = (u32)-1; + break; + } + channel = (container >> 24) & 0xF; + if (channel >= dev->maximum_num_channels) { + container = (u32)-1; + break; + } + id = container & 0xFFFF; + if (id >= dev->maximum_num_physicals) { + container = (u32)-1; + break; + } + lun = (container >> 16) & 0xFF; + container = (u32)-1; + channel = aac_phys_to_logical(channel); + device_config_needed = + (((__le32 *)aifcmd->data)[0] == + cpu_to_le32(AifRawDeviceRemove)) ? DELETE : ADD; + + if (device_config_needed == ADD) { + device = scsi_device_lookup( + dev->scsi_host_ptr, + channel, id, lun); + if (device) { + scsi_remove_device(device); + scsi_device_put(device); + } + } + break; /* * Morph or Expand complete */ @@ -1044,6 +1063,8 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) switch (le32_to_cpu(((__le32 *)aifcmd->data)[3])) { case EM_DRIVE_INSERTION: case EM_DRIVE_REMOVAL: + case EM_SES_DRIVE_INSERTION: + case EM_SES_DRIVE_REMOVAL: container = le32_to_cpu( ((__le32 *)aifcmd->data)[2]); if ((container >> 28)) { @@ -1069,8 +1090,10 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) } channel = aac_phys_to_logical(channel); device_config_needed = - (((__le32 *)aifcmd->data)[3] - == cpu_to_le32(EM_DRIVE_INSERTION)) ? + ((((__le32 *)aifcmd->data)[3] + == cpu_to_le32(EM_DRIVE_INSERTION)) || + (((__le32 *)aifcmd->data)[3] + == cpu_to_le32(EM_SES_DRIVE_INSERTION))) ? ADD : DELETE; break; } @@ -1247,12 +1270,13 @@ retry_next: static int _aac_reset_adapter(struct aac_dev *aac, int forced) { int index, quirks; - int retval; + int retval, i; struct Scsi_Host *host; struct scsi_device *dev; struct scsi_cmnd *command; struct scsi_cmnd *command_list; int jafo = 0; + int cpu; /* * Assumptions: @@ -1315,7 +1339,33 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced) aac->comm_phys = 0; kfree(aac->queues); aac->queues = NULL; - free_irq(aac->pdev->irq, aac); + cpu = cpumask_first(cpu_online_mask); + if (aac->pdev->device == PMC_DEVICE_S6 || + aac->pdev->device == PMC_DEVICE_S7 || + aac->pdev->device == PMC_DEVICE_S8 || + aac->pdev->device == PMC_DEVICE_S9) { + if (aac->max_msix > 1) { + for (i = 0; i < aac->max_msix; i++) { + if (irq_set_affinity_hint( + aac->msixentry[i].vector, + NULL)) { + printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n", + aac->name, + aac->id, + cpu); + } + cpu = cpumask_next(cpu, + cpu_online_mask); + free_irq(aac->msixentry[i].vector, + &(aac->aac_msix[i])); + } + pci_disable_msix(aac->pdev); + } else { + free_irq(aac->pdev->irq, &(aac->aac_msix[0])); + } + } else { + free_irq(aac->pdev->irq, aac); + } if (aac->msi) pci_disable_msi(aac->pdev); kfree(aac->fsa_dev); |