* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6: (22 commits)
[SCSI] ibmvfc: Driver version 1.0.2
[SCSI] ibmvfc: Add details to async event log
[SCSI] ibmvfc: Sanitize response lengths
[SCSI] ibmvfc: Fix for lost async events
[SCSI] ibmvfc: Fixup host state during reinit
[SCSI] ibmvfc: Fix another hang on module removal
[SCSI] ibmvscsi: Fixup desired DMA value for shared memory partitions
[SCSI] megaraid_sas: remove sysfs dbg_lvl world writeable permissions
[SCSI] qla2xxx: Update version number to 8.02.01-k7.
[SCSI] qla2xxx: Explicitly tear-down vports during PCI remove_one().
[SCSI] qla2xxx: Reference proper ha during SBR handling.
[SCSI] qla2xxx: Set npiv_supported flag for FCoE HBAs.
[SCSI] qla2xxx: Don't leak SG-DMA mappings while aborting commands.
[SCSI] qla2xxx: Correct vport-state management issues during ISP-ABORT.
[SCSI] qla2xxx: Correct synchronization of software/firmware fcport states.
[SCSI] scsi_dh: Initialize lun_state in check_ownership()
[SCSI] scsi_dh: Do not use scsilun in rdac hardware handler
[SCSI] megaraid_sas: version and Documentation Update
[SCSI] megaraid_sas: add new controllers (0x78 0x79)
[SCSI] megaraid_sas: add the shutdown DCMD cmd to driver shutdown routine
...
+
+1 Release Date : Thur.July. 24 11:41:51 PST 2008 -
+ (emaild-id:megaraidlinux@lsi.com)
+ Sumant Patro
+ Bo Yang
+
+2 Current Version : 00.00.04.01
+3 Older Version : 00.00.03.22
+
+1. Add the new controller (0078, 0079) support to the driver
+ Those controllers are LSI's next generatation(gen2) SAS controllers.
+
+1 Release Date : Mon.June. 23 10:12:45 PST 2008 -
+ (emaild-id:megaraidlinux@lsi.com)
+ Sumant Patro
+ Bo Yang
+
+2 Current Version : 00.00.03.22
+3 Older Version : 00.00.03.20
+
+1. Add shutdown DCMD cmd to the shutdown routine to make FW shutdown proper.
+2. Unexpected interrupt occurs in HWR Linux driver, add the dumy readl pci flush will fix this issue.
+
1 Release Date : Mon. March 10 11:02:31 PDT 2008 -
(emaild-id:megaraidlinux@lsi.com)
Sumant Patro
if (inqp->page_id[0] != 'e' || inqp->page_id[1] != 'd' ||
inqp->page_id[2] != 'i' || inqp->page_id[3] != 'd')
return SCSI_DH_NOSYS;
- h->lun = scsilun_to_int((struct scsi_lun *)inqp->lun);
+ h->lun = inqp->lun[7]; /* Uses only the last byte */
}
return err;
}
int err;
struct c9_inquiry *inqp;
+ h->lun_state = RDAC_LUN_UNOWNED;
err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h);
if (err == SCSI_DH_OK) {
inqp = &h->inq.c9;
/**
* ibmvfc_init_host - Start host initialization
* @vhost: ibmvfc host struct
+ * @relogin: is this a re-login?
*
* Return value:
* nothing
**/
-static void ibmvfc_init_host(struct ibmvfc_host *vhost)
+static void ibmvfc_init_host(struct ibmvfc_host *vhost, int relogin)
{
struct ibmvfc_target *tgt;
}
if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
+ if (!relogin) {
+ memset(vhost->async_crq.msgs, 0, PAGE_SIZE);
+ vhost->async_crq.cur = 0;
+ }
+
list_for_each_entry(tgt, &vhost->targets, queue)
tgt->need_login = 1;
scsi_block_requests(vhost->host);
static int ibmvfc_wait_while_resetting(struct ibmvfc_host *vhost)
{
long timeout = wait_event_timeout(vhost->init_wait_q,
- (vhost->state == IBMVFC_ACTIVE ||
- vhost->state == IBMVFC_HOST_OFFLINE ||
- vhost->state == IBMVFC_LINK_DEAD),
+ ((vhost->state == IBMVFC_ACTIVE ||
+ vhost->state == IBMVFC_HOST_OFFLINE ||
+ vhost->state == IBMVFC_LINK_DEAD) &&
+ vhost->action == IBMVFC_HOST_ACTION_NONE),
(init_timeout * HZ));
return timeout ? 0 : -EIO;
struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd;
struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
struct scsi_cmnd *cmnd = evt->cmnd;
- int rsp_len = 0;
- int sense_len = rsp->fcp_sense_len;
+ u32 rsp_len = 0;
+ u32 sense_len = rsp->fcp_sense_len;
if (cmnd) {
if (vfc_cmd->response_flags & IBMVFC_ADAPTER_RESID_VALID)
rsp_len = rsp->fcp_rsp_len;
if ((sense_len + rsp_len) > SCSI_SENSE_BUFFERSIZE)
sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len;
- if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len)
+ if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8)
memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len);
ibmvfc_log_error(evt);
{
const char *desc = ibmvfc_get_ae_desc(crq->event);
- ibmvfc_log(vhost, 3, "%s event received\n", desc);
+ ibmvfc_log(vhost, 3, "%s event received. scsi_id: %lx, wwpn: %lx,"
+ " node_name: %lx\n", desc, crq->scsi_id, crq->wwpn, crq->node_name);
switch (crq->event) {
case IBMVFC_AE_LINK_UP:
case IBMVFC_AE_RESUME:
vhost->events_to_log |= IBMVFC_AE_LINKUP;
- ibmvfc_init_host(vhost);
+ ibmvfc_init_host(vhost, 1);
break;
case IBMVFC_AE_SCN_FABRIC:
vhost->events_to_log |= IBMVFC_AE_RSCN;
- ibmvfc_init_host(vhost);
+ ibmvfc_init_host(vhost, 1);
break;
case IBMVFC_AE_SCN_NPORT:
case IBMVFC_AE_SCN_GROUP:
/* Send back a response */
rc = ibmvfc_send_crq_init_complete(vhost);
if (rc == 0)
- ibmvfc_init_host(vhost);
+ ibmvfc_init_host(vhost, 0);
else
dev_err(vhost->dev, "Unable to send init rsp. rc=%ld\n", rc);
break;
case IBMVFC_CRQ_INIT_COMPLETE:
dev_info(vhost->dev, "Partner initialization complete\n");
- ibmvfc_init_host(vhost);
+ ibmvfc_init_host(vhost, 0);
break;
default:
dev_err(vhost->dev, "Unknown crq message type: %d\n", crq->format);
mad->buffer.va = vhost->login_buf_dma;
mad->buffer.len = sizeof(*vhost->login_buf);
- memset(vhost->async_crq.msgs, 0, PAGE_SIZE);
- vhost->async_crq.cur = 0;
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT);
if (!ibmvfc_send_event(evt, vhost, default_timeout))
}
}
- if (vhost->reinit) {
+ if (vhost->reinit && !ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
vhost->reinit = 0;
+ scsi_block_requests(vhost->host);
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
} else {
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
#include "viosrp.h"
#define IBMVFC_NAME "ibmvfc"
-#define IBMVFC_DRIVER_VERSION "1.0.1"
-#define IBMVFC_DRIVER_DATE "(July 11, 2008)"
+#define IBMVFC_DRIVER_VERSION "1.0.2"
+#define IBMVFC_DRIVER_DATE "(August 14, 2008)"
#define IBMVFC_DEFAULT_TIMEOUT 15
#define IBMVFC_INIT_TIMEOUT 30
unsigned long desired_io = max_requests * sizeof(union viosrp_iu);
/* add io space for sg data */
- desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT *
+ desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT * 512 *
IBMVSCSI_CMDS_PER_LUN_DEFAULT);
return desired_io;
* 2 of the License, or (at your option) any later version.
*
* FILE : megaraid_sas.c
- * Version : v00.00.03.20-rc1
+ * Version : v00.00.04.01-rc1
*
* Authors:
* (email-id : megaraidlinux@lsi.com)
/* ppc IOP */
{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
/* ppc IOP */
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078GEN2)},
+ /* gen2*/
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)},
+ /* gen2*/
{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
/* xscale IOP, vega */
{PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
*/
writel(status, ®s->outbound_intr_status);
+ /* Dummy readl to force pci flush */
+ readl(®s->outbound_intr_status);
+
return 0;
}
*/
writel(status, ®s->outbound_doorbell_clear);
+ /* Dummy readl to force pci flush */
+ readl(®s->outbound_doorbell_clear);
+
return 0;
}
/**
.read_fw_status_reg = megasas_read_fw_status_reg_ppc,
};
+/**
+* The following functions are defined for gen2 (deviceid : 0x78 0x79)
+* controllers
+*/
+
+/**
+ * megasas_enable_intr_gen2 - Enables interrupts
+ * @regs: MFI register set
+ */
+static inline void
+megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
+{
+ writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
+
+ /* write ~0x00000005 (4 & 1) to the intr mask*/
+ writel(~MFI_GEN2_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
+
+ /* Dummy readl to force pci flush */
+ readl(®s->outbound_intr_mask);
+}
+
+/**
+ * megasas_disable_intr_gen2 - Disables interrupt
+ * @regs: MFI register set
+ */
+static inline void
+megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs)
+{
+ u32 mask = 0xFFFFFFFF;
+ writel(mask, ®s->outbound_intr_mask);
+ /* Dummy readl to force pci flush */
+ readl(®s->outbound_intr_mask);
+}
+
+/**
+ * megasas_read_fw_status_reg_gen2 - returns the current FW status value
+ * @regs: MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs)
+{
+ return readl(&(regs)->outbound_scratch_pad);
+}
+
+/**
+ * megasas_clear_interrupt_gen2 - Check & clear interrupt
+ * @regs: MFI register set
+ */
+static int
+megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
+{
+ u32 status;
+ /*
+ * Check if it is our interrupt
+ */
+ status = readl(®s->outbound_intr_status);
+
+ if (!(status & MFI_GEN2_ENABLE_INTERRUPT_MASK))
+ return 1;
+
+ /*
+ * Clear the interrupt by writing back the same value
+ */
+ writel(status, ®s->outbound_doorbell_clear);
+
+ /* Dummy readl to force pci flush */
+ readl(®s->outbound_intr_status);
+
+ return 0;
+}
+/**
+ * megasas_fire_cmd_gen2 - Sends command to the FW
+ * @frame_phys_addr : Physical address of cmd
+ * @frame_count : Number of frames for the command
+ * @regs : MFI register set
+ */
+static inline void
+megasas_fire_cmd_gen2(dma_addr_t frame_phys_addr, u32 frame_count,
+ struct megasas_register_set __iomem *regs)
+{
+ writel((frame_phys_addr | (frame_count<<1))|1,
+ &(regs)->inbound_queue_port);
+}
+
+static struct megasas_instance_template megasas_instance_template_gen2 = {
+
+ .fire_cmd = megasas_fire_cmd_gen2,
+ .enable_intr = megasas_enable_intr_gen2,
+ .disable_intr = megasas_disable_intr_gen2,
+ .clear_intr = megasas_clear_intr_gen2,
+ .read_fw_status_reg = megasas_read_fw_status_reg_gen2,
+};
+
/**
* This is the end of set of functions & definitions
* specific to ppc (deviceid : 0x60) controllers
/*
* Map the message registers
*/
- instance->base_addr = pci_resource_start(instance->pdev, 0);
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) {
+ instance->base_addr = pci_resource_start(instance->pdev, 1);
+ } else {
+ instance->base_addr = pci_resource_start(instance->pdev, 0);
+ }
if (pci_request_regions(instance->pdev, "megasas: LSI")) {
printk(KERN_DEBUG "megasas: IO memory region busy!\n");
case PCI_DEVICE_ID_LSI_SAS1078DE:
instance->instancet = &megasas_instance_template_ppc;
break;
+ case PCI_DEVICE_ID_LSI_SAS1078GEN2:
+ case PCI_DEVICE_ID_LSI_SAS0079GEN2:
+ instance->instancet = &megasas_instance_template_gen2;
+ break;
case PCI_DEVICE_ID_LSI_SAS1064R:
case PCI_DEVICE_ID_DELL_PERC5:
default:
{
struct megasas_instance *instance = pci_get_drvdata(pdev);
megasas_flush_cache(instance);
+ megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
}
/**
return retval;
}
-static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl,
+static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
megasas_sysfs_set_dbg_lvl);
static ssize_t
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "00.00.03.20-rc1"
-#define MEGASAS_RELDATE "March 10, 2008"
-#define MEGASAS_EXT_VERSION "Mon. March 10 11:02:31 PDT 2008"
+#define MEGASAS_VERSION "00.00.04.01"
+#define MEGASAS_RELDATE "July 24, 2008"
+#define MEGASAS_EXT_VERSION "Thu July 24 11:41:51 PST 2008"
/*
* Device IDs
#define PCI_DEVICE_ID_LSI_SAS1078R 0x0060
#define PCI_DEVICE_ID_LSI_SAS1078DE 0x007C
#define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413
+#define PCI_DEVICE_ID_LSI_SAS1078GEN2 0x0078
+#define PCI_DEVICE_ID_LSI_SAS0079GEN2 0x0079
/*
* =====================================
#define MEGASAS_COMPLETION_TIMER_INTERVAL (HZ/10)
#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
+#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001
+#define MFI_GEN2_ENABLE_INTERRUPT_MASK (0x00000001 | 0x00000004)
/*
* register set for both 1068 and 1078 controllers
{
fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
+ /*
+ * At this point all fcport's software-states are cleared. Perform any
+ * final cleanup of firmware resources (PCBs and XCBs).
+ */
+ if (fcport->loop_id != FC_NO_LOOP_ID) {
+ fcport->ha->isp_ops->fabric_logout(fcport->ha, fcport->loop_id,
+ fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa);
+ fcport->loop_id = FC_NO_LOOP_ID;
+ }
+
qla2x00_abort_fcport_cmds(fcport);
scsi_target_unblock(&rport->dev);
}
#define REGISTER_FDMI_NEEDED 26
#define FCPORT_UPDATE_NEEDED 27
#define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */
+#define UNLOADING 29
uint32_t device_flags;
#define DFLG_LOCAL_DEVICES BIT_0
&ha->fw_attributes, &ha->fw_memory_size);
qla2x00_resize_request_q(ha);
ha->flags.npiv_supported = 0;
- if ((IS_QLA24XX(ha) || IS_QLA25XX(ha)) &&
- (ha->fw_attributes & BIT_2)) {
+ if ((IS_QLA24XX(ha) || IS_QLA25XX(ha) ||
+ IS_QLA84XX(ha)) &&
+ (ha->fw_attributes & BIT_2)) {
ha->flags.npiv_supported = 1;
if ((!ha->max_npiv_vports) ||
((ha->max_npiv_vports + 1) %
{
int rval;
uint8_t status = 0;
+ scsi_qla_host_t *vha;
if (ha->flags.online) {
ha->flags.online = 0;
if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
atomic_set(&ha->loop_state, LOOP_DOWN);
qla2x00_mark_all_devices_lost(ha, 0);
+ list_for_each_entry(vha, &ha->vp_list, vp_list)
+ qla2x00_mark_all_devices_lost(vha, 0);
} else {
if (!atomic_read(&ha->loop_down_timer))
atomic_set(&ha->loop_down_timer,
sp->request_sense_ptr += sense_len;
sp->request_sense_length -= sense_len;
if (sp->request_sense_length != 0)
- sp->ha->status_srb = sp;
+ sp->fcport->ha->status_srb = sp;
DEBUG5(printk("%s(): Check condition Sense data, scsi(%ld:%d:%d:%d) "
- "cmd=%p pid=%ld\n", __func__, sp->ha->host_no, cp->device->channel,
- cp->device->id, cp->device->lun, cp, cp->serial_number));
+ "cmd=%p pid=%ld\n", __func__, sp->fcport->ha->host_no,
+ cp->device->channel, cp->device->id, cp->device->lun, cp,
+ cp->serial_number));
if (sense_len)
DEBUG5(qla2x00_dump_buffer(cp->sense_buffer,
CMD_ACTUAL_SNSLEN(cp)));
atomic_read(&fcport->state)));
cp->result = DID_BUS_BUSY << 16;
- if (atomic_read(&fcport->state) == FCS_ONLINE) {
- qla2x00_mark_device_lost(ha, fcport, 1, 1);
- }
+ if (atomic_read(&fcport->state) == FCS_ONLINE)
+ qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1);
break;
case CS_RESET:
/* Check to see if logout occurred. */
if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT))
- qla2x00_mark_device_lost(ha, fcport, 1, 1);
+ qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1);
break;
default:
set_bit(VP_IDX_ACQUIRED, &vha->vp_flags);
set_bit(VP_DPC_NEEDED, &ha->dpc_flags);
- wake_up_process(ha->dpc_thread);
+ qla2xxx_wake_dpc(ha);
}
}
sp = pha->outstanding_cmds[cnt];
if (!sp)
continue;
- if (ha->vp_idx != sp->ha->vp_idx)
+
+ if (ha->vp_idx != sp->fcport->ha->vp_idx)
continue;
match = 0;
switch (type) {
sp = ha->outstanding_cmds[cnt];
if (sp) {
ha->outstanding_cmds[cnt] = NULL;
- sp->flags = 0;
sp->cmd->result = res;
- sp->cmd->host_scribble = (unsigned char *)NULL;
qla2x00_sp_compl(ha, sp);
}
}
static void
qla2x00_remove_one(struct pci_dev *pdev)
{
- scsi_qla_host_t *ha;
+ scsi_qla_host_t *ha, *vha, *temp;
ha = pci_get_drvdata(pdev);
+ list_for_each_entry_safe(vha, temp, &ha->vp_list, vp_list)
+ fc_vport_terminate(vha->fc_vport);
+
+ set_bit(UNLOADING, &ha->dpc_flags);
+
qla2x00_dfs_remove(ha);
qla84xx_put_chip(ha);
void
qla2xxx_wake_dpc(scsi_qla_host_t *ha)
{
- if (ha->dpc_thread)
- wake_up_process(ha->dpc_thread);
+ struct task_struct *t = ha->dpc_thread;
+
+ if (!test_bit(UNLOADING, &ha->dpc_flags) && t)
+ wake_up_process(t);
}
/*
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.02.01-k6"
+#define QLA2XXX_VERSION "8.02.01-k7"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 2
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/blkdev.h>
+#include <scsi/scsi.h>
#include <asm/atomic.h>
struct request_queue;
static inline int scsi_device_protection(struct scsi_device *sdev)
{
- return sdev->inquiry[5] & (1<<0);
+ return sdev->scsi_level > SCSI_2 && sdev->inquiry[5] & (1<<0);
}
#define MODULE_ALIAS_SCSI_DEVICE(type) \