提交 e6f194d8 编写于 作者: L Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (60 commits)
  [SCSI] libsas: make ATA functions selectable by a config option
  [SCSI] bsg: unexport sg v3 helper functions
  [SCSI] bsg: fix bsg_unregister_queue
  [SCSI] bsg: make class backlinks
  [SCSI] 3w-9xxx: add support for 9690SA
  [SCSI] bsg: fix bsg_register_queue error path
  [SCSI] ESP: Increase ESP_BUS_TIMEOUT to 275.
  [SCSI] libsas: fix scr_read/write users and update the libata documentation
  [SCSI] mpt fusion: update Kconfig help
  [SCSI] scsi_transport_sas: add destructor for bsg
  [SCSI] iscsi_tcp: buggered kmalloc()
  [SCSI] qla2xxx: Update version number to 8.02.00-k2.
  [SCSI] qla2xxx: Add ISP25XX support.
  [SCSI] qla2xxx: Use pci_try_set_mwi().
  [SCSI] qla2xxx: Use PCI-X/PCI-Express read control interfaces.
  [SCSI] qla2xxx: Re-factor isp_operations to static structures.
  [SCSI] qla2xxx: Validate mid-layer 'underflow' during check-condition handling.
  [SCSI] qla2xxx: Correct setting of 'current' and 'supported' speeds during FDMI registration.
  [SCSI] qla2xxx: Generalize iIDMA support.
  [SCSI] qla2xxx: Generalize FW-Interface-2 support.
  ...
...@@ -456,8 +456,9 @@ void (*irq_clear) (struct ata_port *); ...@@ -456,8 +456,9 @@ void (*irq_clear) (struct ata_port *);
<sect2><title>SATA phy read/write</title> <sect2><title>SATA phy read/write</title>
<programlisting> <programlisting>
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg); int (*scr_read) (struct ata_port *ap, unsigned int sc_reg,
void (*scr_write) (struct ata_port *ap, unsigned int sc_reg, u32 *val);
int (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
u32 val); u32 val);
</programlisting> </programlisting>
......
...@@ -53,7 +53,7 @@ endif # BLOCK ...@@ -53,7 +53,7 @@ endif # BLOCK
config BLK_DEV_BSG config BLK_DEV_BSG
bool "Block layer SG support v4 (EXPERIMENTAL)" bool "Block layer SG support v4 (EXPERIMENTAL)"
depends on (SCSI=y) && EXPERIMENTAL depends on EXPERIMENTAL
---help--- ---help---
Saying Y here will enable generic SG (SCSI generic) v4 support Saying Y here will enable generic SG (SCSI generic) v4 support
for any block device. for any block device.
......
...@@ -932,24 +932,34 @@ void bsg_unregister_queue(struct request_queue *q) ...@@ -932,24 +932,34 @@ void bsg_unregister_queue(struct request_queue *q)
{ {
struct bsg_class_device *bcd = &q->bsg_dev; struct bsg_class_device *bcd = &q->bsg_dev;
WARN_ON(!bcd->class_dev); if (!bcd->class_dev)
return;
mutex_lock(&bsg_mutex); mutex_lock(&bsg_mutex);
sysfs_remove_link(&q->kobj, "bsg"); sysfs_remove_link(&q->kobj, "bsg");
class_device_destroy(bsg_class, MKDEV(bsg_major, bcd->minor)); class_device_unregister(bcd->class_dev);
put_device(bcd->dev);
bcd->class_dev = NULL; bcd->class_dev = NULL;
bcd->dev = NULL;
list_del_init(&bcd->list); list_del_init(&bcd->list);
bsg_device_nr--; bsg_device_nr--;
mutex_unlock(&bsg_mutex); mutex_unlock(&bsg_mutex);
} }
EXPORT_SYMBOL_GPL(bsg_unregister_queue); EXPORT_SYMBOL_GPL(bsg_unregister_queue);
int bsg_register_queue(struct request_queue *q, const char *name) int bsg_register_queue(struct request_queue *q, struct device *gdev,
const char *name)
{ {
struct bsg_class_device *bcd, *__bcd; struct bsg_class_device *bcd, *__bcd;
dev_t dev; dev_t dev;
int ret = -EMFILE; int ret = -EMFILE;
struct class_device *class_dev = NULL; struct class_device *class_dev = NULL;
const char *devname;
if (name)
devname = name;
else
devname = gdev->bus_id;
/* /*
* we need a proper transport to send commands, not a stacked device * we need a proper transport to send commands, not a stacked device
...@@ -982,18 +992,20 @@ int bsg_register_queue(struct request_queue *q, const char *name) ...@@ -982,18 +992,20 @@ int bsg_register_queue(struct request_queue *q, const char *name)
bsg_minor_idx = 0; bsg_minor_idx = 0;
bcd->queue = q; bcd->queue = q;
bcd->dev = get_device(gdev);
dev = MKDEV(bsg_major, bcd->minor); dev = MKDEV(bsg_major, bcd->minor);
class_dev = class_device_create(bsg_class, NULL, dev, bcd->dev, "%s", name); class_dev = class_device_create(bsg_class, NULL, dev, gdev, "%s",
devname);
if (IS_ERR(class_dev)) { if (IS_ERR(class_dev)) {
ret = PTR_ERR(class_dev); ret = PTR_ERR(class_dev);
goto err; goto err_put;
} }
bcd->class_dev = class_dev; bcd->class_dev = class_dev;
if (q->kobj.sd) { if (q->kobj.sd) {
ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg"); ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg");
if (ret) if (ret)
goto err; goto err_unregister;
} }
list_add_tail(&bcd->list, &bsg_class_list); list_add_tail(&bcd->list, &bsg_class_list);
...@@ -1001,37 +1013,17 @@ int bsg_register_queue(struct request_queue *q, const char *name) ...@@ -1001,37 +1013,17 @@ int bsg_register_queue(struct request_queue *q, const char *name)
mutex_unlock(&bsg_mutex); mutex_unlock(&bsg_mutex);
return 0; return 0;
err_unregister:
class_device_unregister(class_dev);
err_put:
put_device(gdev);
err: err:
if (class_dev)
class_device_destroy(bsg_class, MKDEV(bsg_major, bcd->minor));
mutex_unlock(&bsg_mutex); mutex_unlock(&bsg_mutex);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(bsg_register_queue); EXPORT_SYMBOL_GPL(bsg_register_queue);
static int bsg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
{
int ret;
struct scsi_device *sdp = to_scsi_device(cl_dev->dev);
struct request_queue *rq = sdp->request_queue;
if (rq->kobj.parent)
ret = bsg_register_queue(rq, kobject_name(rq->kobj.parent));
else
ret = bsg_register_queue(rq, kobject_name(&sdp->sdev_gendev.kobj));
return ret;
}
static void bsg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
{
bsg_unregister_queue(to_scsi_device(cl_dev->dev)->request_queue);
}
static struct class_interface bsg_intf = {
.add = bsg_add,
.remove = bsg_remove,
};
static struct cdev bsg_cdev = { static struct cdev bsg_cdev = {
.kobj = {.name = "bsg", }, .kobj = {.name = "bsg", },
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -1069,16 +1061,9 @@ static int __init bsg_init(void) ...@@ -1069,16 +1061,9 @@ static int __init bsg_init(void)
if (ret) if (ret)
goto unregister_chrdev; goto unregister_chrdev;
ret = scsi_register_interface(&bsg_intf);
if (ret)
goto remove_cdev;
printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION
" loaded (major %d)\n", bsg_major); " loaded (major %d)\n", bsg_major);
return 0; return 0;
remove_cdev:
printk(KERN_ERR "bsg: failed register scsi interface %d\n", ret);
cdev_del(&bsg_cdev);
unregister_chrdev: unregister_chrdev:
unregister_chrdev_region(MKDEV(bsg_major, 0), BSG_MAX_DEVS); unregister_chrdev_region(MKDEV(bsg_major, 0), BSG_MAX_DEVS);
destroy_bsg_class: destroy_bsg_class:
......
...@@ -214,8 +214,8 @@ int blk_verify_command(unsigned char *cmd, int has_write_perm) ...@@ -214,8 +214,8 @@ int blk_verify_command(unsigned char *cmd, int has_write_perm)
} }
EXPORT_SYMBOL_GPL(blk_verify_command); EXPORT_SYMBOL_GPL(blk_verify_command);
int blk_fill_sghdr_rq(request_queue_t *q, struct request *rq, static int blk_fill_sghdr_rq(request_queue_t *q, struct request *rq,
struct sg_io_hdr *hdr, int has_write_perm) struct sg_io_hdr *hdr, int has_write_perm)
{ {
memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
...@@ -238,22 +238,20 @@ int blk_fill_sghdr_rq(request_queue_t *q, struct request *rq, ...@@ -238,22 +238,20 @@ int blk_fill_sghdr_rq(request_queue_t *q, struct request *rq,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(blk_fill_sghdr_rq);
/* /*
* unmap a request that was previously mapped to this sg_io_hdr. handles * unmap a request that was previously mapped to this sg_io_hdr. handles
* both sg and non-sg sg_io_hdr. * both sg and non-sg sg_io_hdr.
*/ */
int blk_unmap_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr) static int blk_unmap_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr)
{ {
blk_rq_unmap_user(rq->bio); blk_rq_unmap_user(rq->bio);
blk_put_request(rq); blk_put_request(rq);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(blk_unmap_sghdr_rq);
int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
struct bio *bio) struct bio *bio)
{ {
int r, ret = 0; int r, ret = 0;
...@@ -287,7 +285,6 @@ int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, ...@@ -287,7 +285,6 @@ int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
return r; return r;
} }
EXPORT_SYMBOL_GPL(blk_complete_sghdr_rq);
static int sg_io(struct file *file, request_queue_t *q, static int sg_io(struct file *file, request_queue_t *q,
struct gendisk *bd_disk, struct sg_io_hdr *hdr) struct gendisk *bd_disk, struct sg_io_hdr *hdr)
......
...@@ -1160,7 +1160,7 @@ static struct device_attribute *sbp2_scsi_sysfs_attrs[] = { ...@@ -1160,7 +1160,7 @@ static struct device_attribute *sbp2_scsi_sysfs_attrs[] = {
static struct scsi_host_template scsi_driver_template = { static struct scsi_host_template scsi_driver_template = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "SBP-2 IEEE-1394", .name = "SBP-2 IEEE-1394",
.proc_name = (char *)sbp2_driver_name, .proc_name = sbp2_driver_name,
.queuecommand = sbp2_scsi_queuecommand, .queuecommand = sbp2_scsi_queuecommand,
.slave_alloc = sbp2_scsi_slave_alloc, .slave_alloc = sbp2_scsi_slave_alloc,
.slave_configure = sbp2_scsi_slave_configure, .slave_configure = sbp2_scsi_slave_configure,
......
...@@ -37,6 +37,7 @@ config FUSION_FC ...@@ -37,6 +37,7 @@ config FUSION_FC
LSIFC929 LSIFC929
LSIFC929X LSIFC929X
LSIFC929XL LSIFC929XL
Brocade FC 410/420
config FUSION_SAS config FUSION_SAS
tristate "Fusion MPT ScsiHost drivers for SAS" tristate "Fusion MPT ScsiHost drivers for SAS"
......
...@@ -161,6 +161,7 @@ static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); ...@@ -161,6 +161,7 @@ static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
static void mpt_timer_expired(unsigned long data); static void mpt_timer_expired(unsigned long data);
static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc);
static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag); static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
...@@ -1131,6 +1132,248 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) ...@@ -1131,6 +1132,248 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
return -1; return -1;
} }
/**
* mpt_get_product_name - returns product string
* @vendor: pci vendor id
* @device: pci device id
* @revision: pci revision id
* @prod_name: string returned
*
* Returns product string displayed when driver loads,
* in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
*
**/
static void
mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
{
char *product_str = NULL;
if (vendor == PCI_VENDOR_ID_BROCADE) {
switch (device)
{
case MPI_MANUFACTPAGE_DEVICEID_FC949E:
switch (revision)
{
case 0x00:
product_str = "BRE040 A0";
break;
case 0x01:
product_str = "BRE040 A1";
break;
default:
product_str = "BRE040";
break;
}
break;
}
goto out;
}
switch (device)
{
case MPI_MANUFACTPAGE_DEVICEID_FC909:
product_str = "LSIFC909 B1";
break;
case MPI_MANUFACTPAGE_DEVICEID_FC919:
product_str = "LSIFC919 B0";
break;
case MPI_MANUFACTPAGE_DEVICEID_FC929:
product_str = "LSIFC929 B0";
break;
case MPI_MANUFACTPAGE_DEVICEID_FC919X:
if (revision < 0x80)
product_str = "LSIFC919X A0";
else
product_str = "LSIFC919XL A1";
break;
case MPI_MANUFACTPAGE_DEVICEID_FC929X:
if (revision < 0x80)
product_str = "LSIFC929X A0";
else
product_str = "LSIFC929XL A1";
break;
case MPI_MANUFACTPAGE_DEVICEID_FC939X:
product_str = "LSIFC939X A1";
break;
case MPI_MANUFACTPAGE_DEVICEID_FC949X:
product_str = "LSIFC949X A1";
break;
case MPI_MANUFACTPAGE_DEVICEID_FC949E:
switch (revision)
{
case 0x00:
product_str = "LSIFC949E A0";
break;
case 0x01:
product_str = "LSIFC949E A1";
break;
default:
product_str = "LSIFC949E";
break;
}
break;
case MPI_MANUFACTPAGE_DEVID_53C1030:
switch (revision)
{
case 0x00:
product_str = "LSI53C1030 A0";
break;
case 0x01:
product_str = "LSI53C1030 B0";
break;
case 0x03:
product_str = "LSI53C1030 B1";
break;
case 0x07:
product_str = "LSI53C1030 B2";
break;
case 0x08:
product_str = "LSI53C1030 C0";
break;
case 0x80:
product_str = "LSI53C1030T A0";
break;
case 0x83:
product_str = "LSI53C1030T A2";
break;
case 0x87:
product_str = "LSI53C1030T A3";
break;
case 0xc1:
product_str = "LSI53C1020A A1";
break;
default:
product_str = "LSI53C1030";
break;
}
break;
case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
switch (revision)
{
case 0x03:
product_str = "LSI53C1035 A2";
break;
case 0x04:
product_str = "LSI53C1035 B0";
break;
default:
product_str = "LSI53C1035";
break;
}
break;
case MPI_MANUFACTPAGE_DEVID_SAS1064:
switch (revision)
{
case 0x00:
product_str = "LSISAS1064 A1";
break;
case 0x01:
product_str = "LSISAS1064 A2";
break;
case 0x02:
product_str = "LSISAS1064 A3";
break;
case 0x03:
product_str = "LSISAS1064 A4";
break;
default:
product_str = "LSISAS1064";
break;
}
break;
case MPI_MANUFACTPAGE_DEVID_SAS1064E:
switch (revision)
{
case 0x00:
product_str = "LSISAS1064E A0";
break;
case 0x01:
product_str = "LSISAS1064E B0";
break;
case 0x02:
product_str = "LSISAS1064E B1";
break;
case 0x04:
product_str = "LSISAS1064E B2";
break;
case 0x08:
product_str = "LSISAS1064E B3";
break;
default:
product_str = "LSISAS1064E";
break;
}
break;
case MPI_MANUFACTPAGE_DEVID_SAS1068:
switch (revision)
{
case 0x00:
product_str = "LSISAS1068 A0";
break;
case 0x01:
product_str = "LSISAS1068 B0";
break;
case 0x02:
product_str = "LSISAS1068 B1";
break;
default:
product_str = "LSISAS1068";
break;
}
break;
case MPI_MANUFACTPAGE_DEVID_SAS1068E:
switch (revision)
{
case 0x00:
product_str = "LSISAS1068E A0";
break;
case 0x01:
product_str = "LSISAS1068E B0";
break;
case 0x02:
product_str = "LSISAS1068E B1";
break;
case 0x04:
product_str = "LSISAS1068E B2";
break;
case 0x08:
product_str = "LSISAS1068E B3";
break;
default:
product_str = "LSISAS1068E";
break;
}
break;
case MPI_MANUFACTPAGE_DEVID_SAS1078:
switch (revision)
{
case 0x00:
product_str = "LSISAS1078 A0";
break;
case 0x01:
product_str = "LSISAS1078 B0";
break;
case 0x02:
product_str = "LSISAS1078 C0";
break;
case 0x03:
product_str = "LSISAS1078 C1";
break;
case 0x04:
product_str = "LSISAS1078 C2";
break;
default:
product_str = "LSISAS1078";
break;
}
break;
}
out:
if (product_str)
sprintf(prod_name, "%s", product_str);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/** /**
* mpt_attach - Install a PCI intelligent MPT adapter. * mpt_attach - Install a PCI intelligent MPT adapter.
...@@ -1274,23 +1517,23 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1274,23 +1517,23 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->pio_chip = (SYSIF_REGS __iomem *)pmem; ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
} }
if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) { pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
ioc->prod_name = "LSIFC909"; mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name);
ioc->bus_type = FC;
} switch (pdev->device)
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) { {
ioc->prod_name = "LSIFC929"; case MPI_MANUFACTPAGE_DEVICEID_FC939X:
ioc->bus_type = FC; case MPI_MANUFACTPAGE_DEVICEID_FC949X:
} ioc->errata_flag_1064 = 1;
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) { case MPI_MANUFACTPAGE_DEVICEID_FC909:
ioc->prod_name = "LSIFC919"; case MPI_MANUFACTPAGE_DEVICEID_FC929:
ioc->bus_type = FC; case MPI_MANUFACTPAGE_DEVICEID_FC919:
} case MPI_MANUFACTPAGE_DEVICEID_FC949E:
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
ioc->bus_type = FC; ioc->bus_type = FC;
break;
case MPI_MANUFACTPAGE_DEVICEID_FC929X:
if (revision < XL_929) { if (revision < XL_929) {
ioc->prod_name = "LSIFC929X";
/* 929X Chip Fix. Set Split transactions level /* 929X Chip Fix. Set Split transactions level
* for PCIX. Set MOST bits to zero. * for PCIX. Set MOST bits to zero.
*/ */
...@@ -1298,75 +1541,46 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1298,75 +1541,46 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
pcixcmd &= 0x8F; pcixcmd &= 0x8F;
pci_write_config_byte(pdev, 0x6a, pcixcmd); pci_write_config_byte(pdev, 0x6a, pcixcmd);
} else { } else {
ioc->prod_name = "LSIFC929XL";
/* 929XL Chip Fix. Set MMRBC to 0x08. /* 929XL Chip Fix. Set MMRBC to 0x08.
*/ */
pci_read_config_byte(pdev, 0x6a, &pcixcmd); pci_read_config_byte(pdev, 0x6a, &pcixcmd);
pcixcmd |= 0x08; pcixcmd |= 0x08;
pci_write_config_byte(pdev, 0x6a, pcixcmd); pci_write_config_byte(pdev, 0x6a, pcixcmd);
} }
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
ioc->prod_name = "LSIFC919X";
ioc->bus_type = FC; ioc->bus_type = FC;
break;
case MPI_MANUFACTPAGE_DEVICEID_FC919X:
/* 919X Chip Fix. Set Split transactions level /* 919X Chip Fix. Set Split transactions level
* for PCIX. Set MOST bits to zero. * for PCIX. Set MOST bits to zero.
*/ */
pci_read_config_byte(pdev, 0x6a, &pcixcmd); pci_read_config_byte(pdev, 0x6a, &pcixcmd);
pcixcmd &= 0x8F; pcixcmd &= 0x8F;
pci_write_config_byte(pdev, 0x6a, pcixcmd); pci_write_config_byte(pdev, 0x6a, pcixcmd);
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
ioc->prod_name = "LSIFC939X";
ioc->bus_type = FC;
ioc->errata_flag_1064 = 1;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
ioc->prod_name = "LSIFC949X";
ioc->bus_type = FC; ioc->bus_type = FC;
ioc->errata_flag_1064 = 1; break;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) { case MPI_MANUFACTPAGE_DEVID_53C1030:
ioc->prod_name = "LSIFC949E";
ioc->bus_type = FC;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
ioc->prod_name = "LSI53C1030";
ioc->bus_type = SPI;
/* 1030 Chip Fix. Disable Split transactions /* 1030 Chip Fix. Disable Split transactions
* for PCIX. Set MOST bits to zero if Rev < C0( = 8). * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
*/ */
pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
if (revision < C0_1030) { if (revision < C0_1030) {
pci_read_config_byte(pdev, 0x6a, &pcixcmd); pci_read_config_byte(pdev, 0x6a, &pcixcmd);
pcixcmd &= 0x8F; pcixcmd &= 0x8F;
pci_write_config_byte(pdev, 0x6a, pcixcmd); pci_write_config_byte(pdev, 0x6a, pcixcmd);
} }
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) { case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
ioc->prod_name = "LSI53C1035";
ioc->bus_type = SPI; ioc->bus_type = SPI;
} break;
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
ioc->prod_name = "LSISAS1064"; case MPI_MANUFACTPAGE_DEVID_SAS1064:
ioc->bus_type = SAS; case MPI_MANUFACTPAGE_DEVID_SAS1068:
ioc->errata_flag_1064 = 1;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) {
ioc->prod_name = "LSISAS1068";
ioc->bus_type = SAS;
ioc->errata_flag_1064 = 1; ioc->errata_flag_1064 = 1;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) { case MPI_MANUFACTPAGE_DEVID_SAS1064E:
ioc->prod_name = "LSISAS1064E"; case MPI_MANUFACTPAGE_DEVID_SAS1068E:
ioc->bus_type = SAS; case MPI_MANUFACTPAGE_DEVID_SAS1078:
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) {
ioc->prod_name = "LSISAS1068E";
ioc->bus_type = SAS;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
ioc->prod_name = "LSISAS1078";
ioc->bus_type = SAS; ioc->bus_type = SAS;
} }
...@@ -1880,6 +2094,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) ...@@ -1880,6 +2094,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
} }
GetIoUnitPage2(ioc); GetIoUnitPage2(ioc);
mpt_get_manufacturing_pg_0(ioc);
} }
/* /*
...@@ -2138,8 +2353,8 @@ MptDisplayIocCapabilities(MPT_ADAPTER *ioc) ...@@ -2138,8 +2353,8 @@ MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
int i = 0; int i = 0;
printk(KERN_INFO "%s: ", ioc->name); printk(KERN_INFO "%s: ", ioc->name);
if (ioc->prod_name && strlen(ioc->prod_name) > 3) if (ioc->prod_name)
printk("%s: ", ioc->prod_name+3); printk("%s: ", ioc->prod_name);
printk("Capabilities={"); printk("Capabilities={");
if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
...@@ -5190,6 +5405,49 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc) ...@@ -5190,6 +5405,49 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
return; return;
} }
static void
mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc)
{
CONFIGPARMS cfg;
ConfigPageHeader_t hdr;
dma_addr_t buf_dma;
ManufacturingPage0_t *pbuf = NULL;
memset(&cfg, 0 , sizeof(CONFIGPARMS));
memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.timeout = 10;
if (mpt_config(ioc, &cfg) != 0)
goto out;
if (!cfg.cfghdr.hdr->PageLength)
goto out;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
if (!pbuf)
goto out;
cfg.physAddr = buf_dma;
if (mpt_config(ioc, &cfg) != 0)
goto out;
memcpy(ioc->board_name, pbuf->BoardName, sizeof(ioc->board_name));
memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly));
memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer));
out:
if (pbuf)
pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/** /**
* SendEventNotification - Send EventNotification (on or off) request to adapter * SendEventNotification - Send EventNotification (on or off) request to adapter
......
...@@ -537,7 +537,14 @@ typedef struct _MPT_ADAPTER ...@@ -537,7 +537,14 @@ typedef struct _MPT_ADAPTER
int id; /* Unique adapter id N {0,1,2,...} */ int id; /* Unique adapter id N {0,1,2,...} */
int pci_irq; /* This irq */ int pci_irq; /* This irq */
char name[MPT_NAME_LENGTH]; /* "iocN" */ char name[MPT_NAME_LENGTH]; /* "iocN" */
char *prod_name; /* "LSIFC9x9" */ char prod_name[MPT_NAME_LENGTH]; /* "LSIFC9x9" */
char board_name[16];
char board_assembly[16];
char board_tracer[16];
u16 nvdata_version_persistent;
u16 nvdata_version_default;
u8 io_missing_delay;
u8 device_missing_delay;
SYSIF_REGS __iomem *chip; /* == c8817000 (mmap) */ SYSIF_REGS __iomem *chip; /* == c8817000 (mmap) */
SYSIF_REGS __iomem *pio_chip; /* Programmed IO (downloadboot) */ SYSIF_REGS __iomem *pio_chip; /* Programmed IO (downloadboot) */
u8 bus_type; u8 bus_type;
......
...@@ -130,6 +130,7 @@ static struct scsi_host_template mptfc_driver_template = { ...@@ -130,6 +130,7 @@ static struct scsi_host_template mptfc_driver_template = {
.max_sectors = 8192, .max_sectors = 8192,
.cmd_per_lun = 7, .cmd_per_lun = 7,
.use_clustering = ENABLE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING,
.shost_attrs = mptscsih_host_attrs,
}; };
/**************************************************************************** /****************************************************************************
...@@ -153,6 +154,8 @@ static struct pci_device_id mptfc_pci_table[] = { ...@@ -153,6 +154,8 @@ static struct pci_device_id mptfc_pci_table[] = {
PCI_ANY_ID, PCI_ANY_ID }, PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E, { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
PCI_ANY_ID, PCI_ANY_ID }, PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_BROCADE, MPI_MANUFACTPAGE_DEVICEID_FC949E,
PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */ {0} /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(pci, mptfc_pci_table); MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
......
...@@ -1119,6 +1119,7 @@ static struct scsi_host_template mptsas_driver_template = { ...@@ -1119,6 +1119,7 @@ static struct scsi_host_template mptsas_driver_template = {
.max_sectors = 8192, .max_sectors = 8192,
.cmd_per_lun = 7, .cmd_per_lun = 7,
.use_clustering = ENABLE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING,
.shost_attrs = mptscsih_host_attrs,
}; };
static int mptsas_get_linkerrors(struct sas_phy *phy) static int mptsas_get_linkerrors(struct sas_phy *phy)
...@@ -1390,6 +1391,11 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) ...@@ -1390,6 +1391,11 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
goto out_free_consistent; goto out_free_consistent;
} }
ioc->nvdata_version_persistent =
le16_to_cpu(buffer->NvdataVersionPersistent);
ioc->nvdata_version_default =
le16_to_cpu(buffer->NvdataVersionDefault);
for (i = 0; i < port_info->num_phys; i++) { for (i = 0; i < port_info->num_phys; i++) {
mptsas_print_phy_data(&buffer->PhyData[i]); mptsas_print_phy_data(&buffer->PhyData[i]);
port_info->phy_info[i].phy_id = i; port_info->phy_info[i].phy_id = i;
...@@ -1409,6 +1415,63 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) ...@@ -1409,6 +1415,63 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
return error; return error;
} }
static int
mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
{
ConfigExtendedPageHeader_t hdr;
CONFIGPARMS cfg;
SasIOUnitPage1_t *buffer;
dma_addr_t dma_handle;
int error;
u16 device_missing_delay;
memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
memset(&cfg, 0, sizeof(CONFIGPARMS));
cfg.cfghdr.ehdr = &hdr;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.timeout = 10;
cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
cfg.cfghdr.ehdr->PageNumber = 1;
error = mpt_config(ioc, &cfg);
if (error)
goto out;
if (!hdr.ExtPageLength) {
error = -ENXIO;
goto out;
}
buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
&dma_handle);
if (!buffer) {
error = -ENOMEM;
goto out;
}
cfg.physAddr = dma_handle;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
error = mpt_config(ioc, &cfg);
if (error)
goto out_free_consistent;
ioc->io_missing_delay =
le16_to_cpu(buffer->IODeviceMissingDelay);
device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay);
ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
(device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
out_free_consistent:
pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
buffer, dma_handle);
out:
return error;
}
static int static int
mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
u32 form, u32 form_specific) u32 form, u32 form_specific)
...@@ -1990,6 +2053,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) ...@@ -1990,6 +2053,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
if (error) if (error)
goto out_free_port_info; goto out_free_port_info;
mptsas_sas_io_unit_pg1(ioc);
mutex_lock(&ioc->sas_topology_mutex); mutex_lock(&ioc->sas_topology_mutex);
ioc->handle = hba->phy_info[0].handle; ioc->handle = hba->phy_info[0].handle;
port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle); port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
...@@ -3237,6 +3301,8 @@ static struct pci_driver mptsas_driver = { ...@@ -3237,6 +3301,8 @@ static struct pci_driver mptsas_driver = {
static int __init static int __init
mptsas_init(void) mptsas_init(void)
{ {
int error;
show_mptmod_ver(my_NAME, my_VERSION); show_mptmod_ver(my_NAME, my_VERSION);
mptsas_transport_template = mptsas_transport_template =
...@@ -3260,7 +3326,11 @@ mptsas_init(void) ...@@ -3260,7 +3326,11 @@ mptsas_init(void)
": Registered for IOC reset notifications\n")); ": Registered for IOC reset notifications\n"));
} }
return pci_register_driver(&mptsas_driver); error = pci_register_driver(&mptsas_driver);
if (error)
sas_release_transport(mptsas_transport_template);
return error;
} }
static void __exit static void __exit
......
...@@ -3187,6 +3187,159 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) ...@@ -3187,6 +3187,159 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
mptscsih_do_cmd(hd, &iocmd); mptscsih_do_cmd(hd, &iocmd);
} }
static ssize_t
mptscsih_version_fw_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
MPT_ADAPTER *ioc = hd->ioc;
return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
(ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
(ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
(ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
ioc->facts.FWVersion.Word & 0x000000FF);
}
static CLASS_DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
static ssize_t
mptscsih_version_bios_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
MPT_ADAPTER *ioc = hd->ioc;
return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
(ioc->biosVersion & 0xFF000000) >> 24,
(ioc->biosVersion & 0x00FF0000) >> 16,
(ioc->biosVersion & 0x0000FF00) >> 8,
ioc->biosVersion & 0x000000FF);
}
static CLASS_DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
static ssize_t
mptscsih_version_mpi_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
MPT_ADAPTER *ioc = hd->ioc;
return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
}
static CLASS_DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
static ssize_t
mptscsih_version_product_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
MPT_ADAPTER *ioc = hd->ioc;
return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
}
static CLASS_DEVICE_ATTR(version_product, S_IRUGO,
mptscsih_version_product_show, NULL);
static ssize_t
mptscsih_version_nvdata_persistent_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
MPT_ADAPTER *ioc = hd->ioc;
return snprintf(buf, PAGE_SIZE, "%02xh\n",
ioc->nvdata_version_persistent);
}
static CLASS_DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
mptscsih_version_nvdata_persistent_show, NULL);
static ssize_t
mptscsih_version_nvdata_default_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
MPT_ADAPTER *ioc = hd->ioc;
return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
}
static CLASS_DEVICE_ATTR(version_nvdata_default, S_IRUGO,
mptscsih_version_nvdata_default_show, NULL);
static ssize_t
mptscsih_board_name_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
MPT_ADAPTER *ioc = hd->ioc;
return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
}
static CLASS_DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
static ssize_t
mptscsih_board_assembly_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
MPT_ADAPTER *ioc = hd->ioc;
return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
}
static CLASS_DEVICE_ATTR(board_assembly, S_IRUGO,
mptscsih_board_assembly_show, NULL);
static ssize_t
mptscsih_board_tracer_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
MPT_ADAPTER *ioc = hd->ioc;
return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
}
static CLASS_DEVICE_ATTR(board_tracer, S_IRUGO,
mptscsih_board_tracer_show, NULL);
static ssize_t
mptscsih_io_delay_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
MPT_ADAPTER *ioc = hd->ioc;
return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
}
static CLASS_DEVICE_ATTR(io_delay, S_IRUGO,
mptscsih_io_delay_show, NULL);
static ssize_t
mptscsih_device_delay_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
MPT_ADAPTER *ioc = hd->ioc;
return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
}
static CLASS_DEVICE_ATTR(device_delay, S_IRUGO,
mptscsih_device_delay_show, NULL);
struct class_device_attribute *mptscsih_host_attrs[] = {
&class_device_attr_version_fw,
&class_device_attr_version_bios,
&class_device_attr_version_mpi,
&class_device_attr_version_product,
&class_device_attr_version_nvdata_persistent,
&class_device_attr_version_nvdata_default,
&class_device_attr_board_name,
&class_device_attr_board_assembly,
&class_device_attr_board_tracer,
&class_device_attr_io_delay,
&class_device_attr_device_delay,
NULL,
};
EXPORT_SYMBOL(mptscsih_host_attrs);
EXPORT_SYMBOL(mptscsih_remove); EXPORT_SYMBOL(mptscsih_remove);
EXPORT_SYMBOL(mptscsih_shutdown); EXPORT_SYMBOL(mptscsih_shutdown);
#ifdef CONFIG_PM #ifdef CONFIG_PM
......
...@@ -129,3 +129,4 @@ extern void mptscsih_timer_expired(unsigned long data); ...@@ -129,3 +129,4 @@ extern void mptscsih_timer_expired(unsigned long data);
extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id); extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id); extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
extern struct class_device_attribute *mptscsih_host_attrs[];
...@@ -821,6 +821,7 @@ static struct scsi_host_template mptspi_driver_template = { ...@@ -821,6 +821,7 @@ static struct scsi_host_template mptspi_driver_template = {
.max_sectors = 8192, .max_sectors = 8192,
.cmd_per_lun = 7, .cmd_per_lun = 7,
.use_clustering = ENABLE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING,
.shost_attrs = mptscsih_host_attrs,
}; };
static int mptspi_write_spi_device_pg1(struct scsi_target *starget, static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
...@@ -1523,6 +1524,8 @@ static struct pci_driver mptspi_driver = { ...@@ -1523,6 +1524,8 @@ static struct pci_driver mptspi_driver = {
static int __init static int __init
mptspi_init(void) mptspi_init(void)
{ {
int error;
show_mptmod_ver(my_NAME, my_VERSION); show_mptmod_ver(my_NAME, my_VERSION);
mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions); mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions);
...@@ -1543,7 +1546,11 @@ mptspi_init(void) ...@@ -1543,7 +1546,11 @@ mptspi_init(void)
": Registered for IOC reset notifications\n")); ": Registered for IOC reset notifications\n"));
} }
return pci_register_driver(&mptspi_driver); error = pci_register_driver(&mptspi_driver);
if (error)
spi_release_transport(mptspi_transport_template);
return error;
} }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......
...@@ -1526,15 +1526,12 @@ zfcp_gid_pn_buffers_alloc(struct zfcp_gid_pn_data **gid_pn, mempool_t *pool) ...@@ -1526,15 +1526,12 @@ zfcp_gid_pn_buffers_alloc(struct zfcp_gid_pn_data **gid_pn, mempool_t *pool)
* zfcp_gid_pn_buffers_free - free buffers for GID_PN nameserver request * zfcp_gid_pn_buffers_free - free buffers for GID_PN nameserver request
* @gid_pn: pointer to struct zfcp_gid_pn_data which has to be freed * @gid_pn: pointer to struct zfcp_gid_pn_data which has to be freed
*/ */
static void static void zfcp_gid_pn_buffers_free(struct zfcp_gid_pn_data *gid_pn)
zfcp_gid_pn_buffers_free(struct zfcp_gid_pn_data *gid_pn)
{ {
if ((gid_pn->ct.pool != 0)) if (gid_pn->ct.pool)
mempool_free(gid_pn, gid_pn->ct.pool); mempool_free(gid_pn, gid_pn->ct.pool);
else else
kfree(gid_pn); kfree(gid_pn);
return;
} }
/** /**
......
...@@ -126,6 +126,7 @@ zfcp_address_to_sg(void *address, struct scatterlist *list) ...@@ -126,6 +126,7 @@ zfcp_address_to_sg(void *address, struct scatterlist *list)
#define ZFCP_MIN_OUTPUT_THRESHOLD 1 /* ignored by QDIO layer */ #define ZFCP_MIN_OUTPUT_THRESHOLD 1 /* ignored by QDIO layer */
#define QDIO_SCSI_QFMT 1 /* 1 for FSF */ #define QDIO_SCSI_QFMT 1 /* 1 for FSF */
#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer))
/********************* FSF SPECIFIC DEFINES *********************************/ /********************* FSF SPECIFIC DEFINES *********************************/
......
...@@ -1626,7 +1626,7 @@ zfcp_erp_schedule_work(struct zfcp_unit *unit) ...@@ -1626,7 +1626,7 @@ zfcp_erp_schedule_work(struct zfcp_unit *unit)
{ {
struct zfcp_erp_add_work *p; struct zfcp_erp_add_work *p;
p = kmalloc(sizeof(*p), GFP_KERNEL); p = kzalloc(sizeof(*p), GFP_KERNEL);
if (!p) { if (!p) {
ZFCP_LOG_NORMAL("error: Out of resources. Could not register " ZFCP_LOG_NORMAL("error: Out of resources. Could not register "
"the FCP-LUN 0x%Lx connected to " "the FCP-LUN 0x%Lx connected to "
...@@ -1639,7 +1639,6 @@ zfcp_erp_schedule_work(struct zfcp_unit *unit) ...@@ -1639,7 +1639,6 @@ zfcp_erp_schedule_work(struct zfcp_unit *unit)
} }
zfcp_unit_get(unit); zfcp_unit_get(unit);
memset(p, 0, sizeof(*p));
atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
INIT_WORK(&p->work, zfcp_erp_scsi_scan); INIT_WORK(&p->work, zfcp_erp_scsi_scan);
p->unit = unit; p->unit = unit;
......
...@@ -1930,7 +1930,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) ...@@ -1930,7 +1930,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
skip_fsfstatus: skip_fsfstatus:
send_els->status = retval; send_els->status = retval;
if (send_els->handler != 0) if (send_els->handler)
send_els->handler(send_els->handler_data); send_els->handler(send_els->handler_data);
return retval; return retval;
......
...@@ -47,103 +47,56 @@ static int zfcp_qdio_handler_error_check(struct zfcp_adapter *, ...@@ -47,103 +47,56 @@ static int zfcp_qdio_handler_error_check(struct zfcp_adapter *,
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_QDIO #define ZFCP_LOG_AREA ZFCP_LOG_AREA_QDIO
/* /*
* Allocates BUFFER memory to each of the pointers of the qdio_buffer_t * Frees BUFFER memory for each of the pointers of the struct qdio_buffer array
* array in the adapter struct. * in the adapter struct sbuf is the pointer array.
* Cur_buf is the pointer array and count can be any number of required
* buffers, the page-fitting arithmetic is done entirely within this funciton.
* *
* returns: number of buffers allocated
* locks: must only be called with zfcp_data.config_sema taken * locks: must only be called with zfcp_data.config_sema taken
*/ */
static int static void
zfcp_qdio_buffers_enqueue(struct qdio_buffer **cur_buf, int count) zfcp_qdio_buffers_dequeue(struct qdio_buffer **sbuf)
{ {
int buf_pos; int pos;
int qdio_buffers_per_page;
int page_pos = 0;
struct qdio_buffer *first_in_page = NULL;
qdio_buffers_per_page = PAGE_SIZE / sizeof (struct qdio_buffer);
ZFCP_LOG_TRACE("buffers_per_page=%d\n", qdio_buffers_per_page);
for (buf_pos = 0; buf_pos < count; buf_pos++) {
if (page_pos == 0) {
cur_buf[buf_pos] = (struct qdio_buffer *)
get_zeroed_page(GFP_KERNEL);
if (cur_buf[buf_pos] == NULL) {
ZFCP_LOG_INFO("error: allocation of "
"QDIO buffer failed \n");
goto out;
}
first_in_page = cur_buf[buf_pos];
} else {
cur_buf[buf_pos] = first_in_page + page_pos;
} for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos += QBUFF_PER_PAGE)
/* was initialised to zero */ free_page((unsigned long) sbuf[pos]);
page_pos++;
page_pos %= qdio_buffers_per_page;
}
out:
return buf_pos;
} }
/* /*
* Frees BUFFER memory for each of the pointers of the struct qdio_buffer array * Allocates BUFFER memory to each of the pointers of the qdio_buffer_t
* in the adapter struct cur_buf is the pointer array and count can be any * array in the adapter struct.
* number of buffers in the array that should be freed starting from buffer 0 * Cur_buf is the pointer array
* *
* returns: zero on success else -ENOMEM
* locks: must only be called with zfcp_data.config_sema taken * locks: must only be called with zfcp_data.config_sema taken
*/ */
static void static int
zfcp_qdio_buffers_dequeue(struct qdio_buffer **cur_buf, int count) zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbuf)
{ {
int buf_pos; int pos;
int qdio_buffers_per_page;
qdio_buffers_per_page = PAGE_SIZE / sizeof (struct qdio_buffer);
ZFCP_LOG_TRACE("buffers_per_page=%d\n", qdio_buffers_per_page);
for (buf_pos = 0; buf_pos < count; buf_pos += qdio_buffers_per_page) for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos += QBUFF_PER_PAGE) {
free_page((unsigned long) cur_buf[buf_pos]); sbuf[pos] = (struct qdio_buffer *) get_zeroed_page(GFP_KERNEL);
return; if (!sbuf[pos]) {
zfcp_qdio_buffers_dequeue(sbuf);
return -ENOMEM;
}
}
for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos++)
if (pos % QBUFF_PER_PAGE)
sbuf[pos] = sbuf[pos - 1] + 1;
return 0;
} }
/* locks: must only be called with zfcp_data.config_sema taken */ /* locks: must only be called with zfcp_data.config_sema taken */
int int
zfcp_qdio_allocate_queues(struct zfcp_adapter *adapter) zfcp_qdio_allocate_queues(struct zfcp_adapter *adapter)
{ {
int buffer_count; int ret;
int retval = 0;
buffer_count = ret = zfcp_qdio_buffers_enqueue(adapter->request_queue.buffer);
zfcp_qdio_buffers_enqueue(&(adapter->request_queue.buffer[0]), if (ret)
QDIO_MAX_BUFFERS_PER_Q); return ret;
if (buffer_count < QDIO_MAX_BUFFERS_PER_Q) { return zfcp_qdio_buffers_enqueue(adapter->response_queue.buffer);
ZFCP_LOG_DEBUG("only %d QDIO buffers allocated for request "
"queue\n", buffer_count);
zfcp_qdio_buffers_dequeue(&(adapter->request_queue.buffer[0]),
buffer_count);
retval = -ENOMEM;
goto out;
}
buffer_count =
zfcp_qdio_buffers_enqueue(&(adapter->response_queue.buffer[0]),
QDIO_MAX_BUFFERS_PER_Q);
if (buffer_count < QDIO_MAX_BUFFERS_PER_Q) {
ZFCP_LOG_DEBUG("only %d QDIO buffers allocated for response "
"queue", buffer_count);
zfcp_qdio_buffers_dequeue(&(adapter->response_queue.buffer[0]),
buffer_count);
ZFCP_LOG_TRACE("freeing request_queue buffers\n");
zfcp_qdio_buffers_dequeue(&(adapter->request_queue.buffer[0]),
QDIO_MAX_BUFFERS_PER_Q);
retval = -ENOMEM;
goto out;
}
out:
return retval;
} }
/* locks: must only be called with zfcp_data.config_sema taken */ /* locks: must only be called with zfcp_data.config_sema taken */
...@@ -151,12 +104,10 @@ void ...@@ -151,12 +104,10 @@ void
zfcp_qdio_free_queues(struct zfcp_adapter *adapter) zfcp_qdio_free_queues(struct zfcp_adapter *adapter)
{ {
ZFCP_LOG_TRACE("freeing request_queue buffers\n"); ZFCP_LOG_TRACE("freeing request_queue buffers\n");
zfcp_qdio_buffers_dequeue(&(adapter->request_queue.buffer[0]), zfcp_qdio_buffers_dequeue(adapter->request_queue.buffer);
QDIO_MAX_BUFFERS_PER_Q);
ZFCP_LOG_TRACE("freeing response_queue buffers\n"); ZFCP_LOG_TRACE("freeing response_queue buffers\n");
zfcp_qdio_buffers_dequeue(&(adapter->response_queue.buffer[0]), zfcp_qdio_buffers_dequeue(adapter->response_queue.buffer);
QDIO_MAX_BUFFERS_PER_Q);
} }
int int
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
Written By: Adam Radford <linuxraid@amcc.com> Written By: Adam Radford <linuxraid@amcc.com>
Modifications By: Tom Couch <linuxraid@amcc.com> Modifications By: Tom Couch <linuxraid@amcc.com>
Copyright (C) 2004-2006 Applied Micro Circuits Corporation. Copyright (C) 2004-2007 Applied Micro Circuits Corporation.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -69,6 +69,8 @@ ...@@ -69,6 +69,8 @@
2.26.02.008 - Free irq handler in __twa_shutdown(). 2.26.02.008 - Free irq handler in __twa_shutdown().
Serialize reset code. Serialize reset code.
Add support for 9650SE controllers. Add support for 9650SE controllers.
2.26.02.009 - Fix dma mask setting to fallback to 32-bit if 64-bit fails.
2.26.02.010 - Add support for 9690SA controllers.
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -92,7 +94,7 @@ ...@@ -92,7 +94,7 @@
#include "3w-9xxx.h" #include "3w-9xxx.h"
/* Globals */ /* Globals */
#define TW_DRIVER_VERSION "2.26.02.008" #define TW_DRIVER_VERSION "2.26.02.010"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count; static unsigned int twa_device_extension_count;
static int twa_major = -1; static int twa_major = -1;
...@@ -124,11 +126,11 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits, ...@@ -124,11 +126,11 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits,
unsigned short *fw_on_ctlr_branch, unsigned short *fw_on_ctlr_branch,
unsigned short *fw_on_ctlr_build, unsigned short *fw_on_ctlr_build,
u32 *init_connect_result); u32 *init_connect_result);
static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length); static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length);
static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds); static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds);
static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds); static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds);
static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal); static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal);
static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset); static int twa_reset_device_extension(TW_Device_Extension *tw_dev);
static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset);
static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg);
static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id);
...@@ -683,7 +685,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -683,7 +685,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
full_command_packet = &tw_ioctl->firmware_command; full_command_packet = &tw_ioctl->firmware_command;
/* Load request id and sglist for both command types */ /* Load request id and sglist for both command types */
twa_load_sgl(full_command_packet, request_id, dma_handle, data_buffer_length_adjusted); twa_load_sgl(tw_dev, full_command_packet, request_id, dma_handle, data_buffer_length_adjusted);
memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full)); memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full));
...@@ -700,10 +702,10 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -700,10 +702,10 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
/* Now we need to reset the board */ /* Now we need to reset the board */
printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n", printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n",
tw_dev->host->host_no, TW_DRIVER, 0xc, tw_dev->host->host_no, TW_DRIVER, 0x37,
cmd); cmd);
retval = TW_IOCTL_ERROR_OS_EIO; retval = TW_IOCTL_ERROR_OS_EIO;
twa_reset_device_extension(tw_dev, 1); twa_reset_device_extension(tw_dev);
goto out3; goto out3;
} }
...@@ -890,7 +892,9 @@ static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value) ...@@ -890,7 +892,9 @@ static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value)
} }
if (status_reg_value & TW_STATUS_QUEUE_ERROR) { if (status_reg_value & TW_STATUS_QUEUE_ERROR) {
if ((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) || (!test_bit(TW_IN_RESET, &tw_dev->flags))) if (((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) &&
(tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9690SA)) ||
(!test_bit(TW_IN_RESET, &tw_dev->flags)))
TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing"); TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing");
writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
} }
...@@ -935,8 +939,7 @@ static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev) ...@@ -935,8 +939,7 @@ static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev)
unsigned long before; unsigned long before;
int retval = 1; int retval = 1;
if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) || if (tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9000) {
(tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE)) {
before = jiffies; before = jiffies;
while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) { while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) {
response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev));
...@@ -1195,7 +1198,6 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) ...@@ -1195,7 +1198,6 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
u32 status_reg_value; u32 status_reg_value;
TW_Response_Queue response_que; TW_Response_Queue response_que;
TW_Command_Full *full_command_packet; TW_Command_Full *full_command_packet;
TW_Command *command_packet;
TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;
int handled = 0; int handled = 0;
...@@ -1273,7 +1275,6 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) ...@@ -1273,7 +1275,6 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
request_id = TW_RESID_OUT(response_que.response_id); request_id = TW_RESID_OUT(response_que.response_id);
full_command_packet = tw_dev->command_packet_virt[request_id]; full_command_packet = tw_dev->command_packet_virt[request_id];
error = 0; error = 0;
command_packet = &full_command_packet->command.oldcommand;
/* Check for command packet errors */ /* Check for command packet errors */
if (full_command_packet->command.newcommand.status != 0) { if (full_command_packet->command.newcommand.status != 0) {
if (tw_dev->srb[request_id] != 0) { if (tw_dev->srb[request_id] != 0) {
...@@ -1352,11 +1353,15 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) ...@@ -1352,11 +1353,15 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
} /* End twa_interrupt() */ } /* End twa_interrupt() */
/* This function will load the request id and various sgls for ioctls */ /* This function will load the request id and various sgls for ioctls */
static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length) static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length)
{ {
TW_Command *oldcommand; TW_Command *oldcommand;
TW_Command_Apache *newcommand; TW_Command_Apache *newcommand;
TW_SG_Entry *sgl; TW_SG_Entry *sgl;
unsigned int pae = 0;
if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4))
pae = 1;
if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) {
newcommand = &full_command_packet->command.newcommand; newcommand = &full_command_packet->command.newcommand;
...@@ -1372,12 +1377,14 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d ...@@ -1372,12 +1377,14 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) {
/* Load the sg list */ /* Load the sg list */
sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)
sgl = (TW_SG_Entry *)((u32 *)oldcommand+oldcommand->size - (sizeof(TW_SG_Entry)/4) + pae);
else
sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset));
sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
sgl->length = cpu_to_le32(length); sgl->length = cpu_to_le32(length);
if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) oldcommand->size += pae;
oldcommand->size += 1;
} }
} }
} /* End twa_load_sgl() */ } /* End twa_load_sgl() */
...@@ -1506,7 +1513,8 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, ...@@ -1506,7 +1513,8 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id,
command_que_value = tw_dev->command_packet_phys[request_id]; command_que_value = tw_dev->command_packet_phys[request_id];
/* For 9650SE write low 4 bytes first */ /* For 9650SE write low 4 bytes first */
if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) ||
(tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)) {
command_que_value += TW_COMMAND_OFFSET; command_que_value += TW_COMMAND_OFFSET;
writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev)); writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev));
} }
...@@ -1537,7 +1545,8 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, ...@@ -1537,7 +1545,8 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id,
TW_UNMASK_COMMAND_INTERRUPT(tw_dev); TW_UNMASK_COMMAND_INTERRUPT(tw_dev);
goto out; goto out;
} else { } else {
if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) ||
(tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)) {
/* Now write upper 4 bytes */ /* Now write upper 4 bytes */
writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4); writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4);
} else { } else {
...@@ -1561,7 +1570,7 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, ...@@ -1561,7 +1570,7 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id,
} /* End twa_post_command_packet() */ } /* End twa_post_command_packet() */
/* This function will reset a device extension */ /* This function will reset a device extension */
static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset) static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
{ {
int i = 0; int i = 0;
int retval = 1; int retval = 1;
...@@ -1719,7 +1728,7 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt) ...@@ -1719,7 +1728,7 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
mutex_lock(&tw_dev->ioctl_lock); mutex_lock(&tw_dev->ioctl_lock);
/* Now reset the card and some of the device extension data */ /* Now reset the card and some of the device extension data */
if (twa_reset_device_extension(tw_dev, 0)) { if (twa_reset_device_extension(tw_dev)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset"); TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset");
goto out; goto out;
} }
...@@ -2001,11 +2010,14 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id ...@@ -2001,11 +2010,14 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
pci_set_master(pdev); pci_set_master(pdev);
retval = pci_set_dma_mask(pdev, sizeof(dma_addr_t) > 4 ? DMA_64BIT_MASK : DMA_32BIT_MASK); if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)
if (retval) { || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)
goto out_disable_device; || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
} TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask");
retval = -ENODEV;
goto out_disable_device;
}
host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension));
if (!host) { if (!host) {
...@@ -2053,7 +2065,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id ...@@ -2053,7 +2065,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
goto out_iounmap; goto out_iounmap;
/* Set host specific parameters */ /* Set host specific parameters */
if (pdev->device == PCI_DEVICE_ID_3WARE_9650SE) if ((pdev->device == PCI_DEVICE_ID_3WARE_9650SE) ||
(pdev->device == PCI_DEVICE_ID_3WARE_9690SA))
host->max_id = TW_MAX_UNITS_9650SE; host->max_id = TW_MAX_UNITS_9650SE;
else else
host->max_id = TW_MAX_UNITS; host->max_id = TW_MAX_UNITS;
...@@ -2160,6 +2173,8 @@ static struct pci_device_id twa_pci_tbl[] __devinitdata = { ...@@ -2160,6 +2173,8 @@ static struct pci_device_id twa_pci_tbl[] __devinitdata = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE, { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9690SA,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ } { }
}; };
MODULE_DEVICE_TABLE(pci, twa_pci_tbl); MODULE_DEVICE_TABLE(pci, twa_pci_tbl);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
Written By: Adam Radford <linuxraid@amcc.com> Written By: Adam Radford <linuxraid@amcc.com>
Modifications By: Tom Couch <linuxraid@amcc.com> Modifications By: Tom Couch <linuxraid@amcc.com>
Copyright (C) 2004-2006 Applied Micro Circuits Corporation. Copyright (C) 2004-2007 Applied Micro Circuits Corporation.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -419,6 +419,9 @@ static twa_message_type twa_error_table[] = { ...@@ -419,6 +419,9 @@ static twa_message_type twa_error_table[] = {
#ifndef PCI_DEVICE_ID_3WARE_9650SE #ifndef PCI_DEVICE_ID_3WARE_9650SE
#define PCI_DEVICE_ID_3WARE_9650SE 0x1004 #define PCI_DEVICE_ID_3WARE_9650SE 0x1004
#endif #endif
#ifndef PCI_DEVICE_ID_3WARE_9690SA
#define PCI_DEVICE_ID_3WARE_9690SA 0x1005
#endif
/* Bitmask macros to eliminate bitfields */ /* Bitmask macros to eliminate bitfields */
......
...@@ -282,7 +282,7 @@ config SCSI_ISCSI_ATTRS ...@@ -282,7 +282,7 @@ config SCSI_ISCSI_ATTRS
config SCSI_SAS_ATTRS config SCSI_SAS_ATTRS
tristate "SAS Transport Attributes" tristate "SAS Transport Attributes"
depends on SCSI depends on SCSI && BLK_DEV_BSG
help help
If you wish to export transport-specific information about If you wish to export transport-specific information about
each attached SAS device to sysfs, say Y. each attached SAS device to sysfs, say Y.
...@@ -291,8 +291,12 @@ source "drivers/scsi/libsas/Kconfig" ...@@ -291,8 +291,12 @@ source "drivers/scsi/libsas/Kconfig"
endmenu endmenu
menu "SCSI low-level drivers" menuconfig SCSI_LOWLEVEL
bool "SCSI low-level drivers"
depends on SCSI!=n depends on SCSI!=n
default y
if SCSI_LOWLEVEL
config ISCSI_TCP config ISCSI_TCP
tristate "iSCSI Initiator over TCP/IP" tristate "iSCSI Initiator over TCP/IP"
...@@ -1800,7 +1804,7 @@ config SCSI_SRP ...@@ -1800,7 +1804,7 @@ config SCSI_SRP
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called libsrp. module will be called libsrp.
endmenu endif # SCSI_LOWLEVEL
source "drivers/scsi/pcmcia/Kconfig" source "drivers/scsi/pcmcia/Kconfig"
......
...@@ -79,6 +79,7 @@ static int __devinit a4000t_probe(struct device *dev) ...@@ -79,6 +79,7 @@ static int __devinit a4000t_probe(struct device *dev)
goto out_put_host; goto out_put_host;
} }
dev_set_drvdata(dev, host);
scsi_scan_host(host); scsi_scan_host(host);
return 0; return 0;
...@@ -95,7 +96,7 @@ static int __devinit a4000t_probe(struct device *dev) ...@@ -95,7 +96,7 @@ static int __devinit a4000t_probe(struct device *dev)
static __devexit int a4000t_device_remove(struct device *dev) static __devexit int a4000t_device_remove(struct device *dev)
{ {
struct Scsi_Host *host = dev_to_shost(dev); struct Scsi_Host *host = dev_get_drvdata(dev);
struct NCR_700_Host_Parameters *hostdata = shost_priv(host); struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
scsi_remove_host(host); scsi_remove_host(host);
......
...@@ -751,6 +751,101 @@ static void setinqstr(struct aac_dev *dev, void *data, int tindex) ...@@ -751,6 +751,101 @@ static void setinqstr(struct aac_dev *dev, void *data, int tindex)
inqstrcpy ("V1.0", str->prl); inqstrcpy ("V1.0", str->prl);
} }
static void get_container_serial_callback(void *context, struct fib * fibptr)
{
struct aac_get_serial_resp * get_serial_reply;
struct scsi_cmnd * scsicmd;
BUG_ON(fibptr == NULL);
scsicmd = (struct scsi_cmnd *) context;
if (!aac_valid_context(scsicmd, fibptr))
return;
get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr);
/* Failure is irrelevant, using default value instead */
if (le32_to_cpu(get_serial_reply->status) == CT_OK) {
char sp[13];
/* EVPD bit set */
sp[0] = INQD_PDT_DA;
sp[1] = scsicmd->cmnd[2];
sp[2] = 0;
sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X",
le32_to_cpu(get_serial_reply->uid));
aac_internal_transfer(scsicmd, sp, 0, sizeof(sp));
}
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
aac_fib_complete(fibptr);
aac_fib_free(fibptr);
scsicmd->scsi_done(scsicmd);
}
/**
* aac_get_container_serial - get container serial, none blocking.
*/
static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
{
int status;
struct aac_get_serial *dinfo;
struct fib * cmd_fibcontext;
struct aac_dev * dev;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
if (!(cmd_fibcontext = aac_fib_alloc(dev)))
return -ENOMEM;
aac_fib_init(cmd_fibcontext);
dinfo = (struct aac_get_serial *) fib_data(cmd_fibcontext);
dinfo->command = cpu_to_le32(VM_ContainerConfig);
dinfo->type = cpu_to_le32(CT_CID_TO_32BITS_UID);
dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
sizeof (struct aac_get_serial),
FsaNormal,
0, 1,
(fib_callback) get_container_serial_callback,
(void *) scsicmd);
/*
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS) {
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
return 0;
}
printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with status: %d.\n", status);
aac_fib_complete(cmd_fibcontext);
aac_fib_free(cmd_fibcontext);
return -1;
}
/* Function: setinqserial
*
* Arguments: [1] pointer to void [1] int
*
* Purpose: Sets SCSI Unit Serial number.
* This is a fake. We should read a proper
* serial number from the container. <SuSE>But
* without docs it's quite hard to do it :-)
* So this will have to do in the meantime.</SuSE>
*/
static int setinqserial(struct aac_dev *dev, void *data, int cid)
{
/*
* This breaks array migration.
*/
return snprintf((char *)(data), sizeof(struct scsi_inq) - 4, "%08X%02X",
le32_to_cpu(dev->adapter_info.serial[0]), cid);
}
static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code, static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
u8 a_sense_code, u8 incorrect_length, u8 a_sense_code, u8 incorrect_length,
u8 bit_pointer, u16 field_pointer, u8 bit_pointer, u16 field_pointer,
...@@ -1798,6 +1893,49 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) ...@@ -1798,6 +1893,49 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid)); dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid));
memset(&inq_data, 0, sizeof (struct inquiry_data)); memset(&inq_data, 0, sizeof (struct inquiry_data));
if (scsicmd->cmnd[1] & 0x1 ) {
char *arr = (char *)&inq_data;
/* EVPD bit set */
arr[0] = (scmd_id(scsicmd) == host->this_id) ?
INQD_PDT_PROC : INQD_PDT_DA;
if (scsicmd->cmnd[2] == 0) {
/* supported vital product data pages */
arr[3] = 2;
arr[4] = 0x0;
arr[5] = 0x80;
arr[1] = scsicmd->cmnd[2];
aac_internal_transfer(scsicmd, &inq_data, 0,
sizeof(inq_data));
scsicmd->result = DID_OK << 16 |
COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
} else if (scsicmd->cmnd[2] == 0x80) {
/* unit serial number page */
arr[3] = setinqserial(dev, &arr[4],
scmd_id(scsicmd));
arr[1] = scsicmd->cmnd[2];
aac_internal_transfer(scsicmd, &inq_data, 0,
sizeof(inq_data));
return aac_get_container_serial(scsicmd);
} else {
/* vpd page not implemented */
scsicmd->result = DID_OK << 16 |
COMMAND_COMPLETE << 8 |
SAM_STAT_CHECK_CONDITION;
set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
ILLEGAL_REQUEST,
SENCODE_INVALID_CDB_FIELD,
ASENCODE_NO_SENSE, 0, 7, 2, 0);
memcpy(scsicmd->sense_buffer,
&dev->fsa_dev[cid].sense_data,
(sizeof(dev->fsa_dev[cid].sense_data) >
sizeof(scsicmd->sense_buffer))
? sizeof(scsicmd->sense_buffer)
: sizeof(dev->fsa_dev[cid].sense_data));
}
scsicmd->scsi_done(scsicmd);
return 0;
}
inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */
inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
inq_data.inqd_len = 31; inq_data.inqd_len = 31;
...@@ -2070,7 +2208,7 @@ static int query_disk(struct aac_dev *dev, void __user *arg) ...@@ -2070,7 +2208,7 @@ static int query_disk(struct aac_dev *dev, void __user *arg)
} }
else return -EINVAL; else return -EINVAL;
qd.valid = fsa_dev_ptr[qd.cnum].valid; qd.valid = fsa_dev_ptr[qd.cnum].valid != 0;
qd.locked = fsa_dev_ptr[qd.cnum].locked; qd.locked = fsa_dev_ptr[qd.cnum].locked;
qd.deleted = fsa_dev_ptr[qd.cnum].deleted; qd.deleted = fsa_dev_ptr[qd.cnum].deleted;
......
...@@ -1567,6 +1567,20 @@ struct aac_get_name_resp { ...@@ -1567,6 +1567,20 @@ struct aac_get_name_resp {
u8 data[16]; u8 data[16];
}; };
#define CT_CID_TO_32BITS_UID 165
struct aac_get_serial {
__le32 command; /* VM_ContainerConfig */
__le32 type; /* CT_CID_TO_32BITS_UID */
__le32 cid;
};
struct aac_get_serial_resp {
__le32 dummy0;
__le32 dummy1;
__le32 status; /* CT_OK */
__le32 uid;
};
/* /*
* The following command is sent to shut down each container. * The following command is sent to shut down each container.
*/ */
......
...@@ -80,7 +80,11 @@ static int fib_map_alloc(struct aac_dev *dev) ...@@ -80,7 +80,11 @@ static int fib_map_alloc(struct aac_dev *dev)
void aac_fib_map_free(struct aac_dev *dev) void aac_fib_map_free(struct aac_dev *dev)
{ {
pci_free_consistent(dev->pdev, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), dev->hw_fib_va, dev->hw_fib_pa); pci_free_consistent(dev->pdev,
dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB),
dev->hw_fib_va, dev->hw_fib_pa);
dev->hw_fib_va = NULL;
dev->hw_fib_pa = 0;
} }
/** /**
...@@ -1087,8 +1091,6 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced) ...@@ -1087,8 +1091,6 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced)
* case. * case.
*/ */
aac_fib_map_free(aac); aac_fib_map_free(aac);
aac->hw_fib_va = NULL;
aac->hw_fib_pa = 0;
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
aac->comm_addr = NULL; aac->comm_addr = NULL;
aac->comm_phys = 0; aac->comm_phys = 0;
...@@ -1098,12 +1100,12 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced) ...@@ -1098,12 +1100,12 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced)
kfree(aac->fsa_dev); kfree(aac->fsa_dev);
aac->fsa_dev = NULL; aac->fsa_dev = NULL;
if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) { if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) {
if (((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) || if (((retval = pci_set_dma_mask(aac->pdev, DMA_31BIT_MASK))) ||
((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_32BIT_MASK)))) ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_31BIT_MASK))))
goto out; goto out;
} else { } else {
if (((retval = pci_set_dma_mask(aac->pdev, 0x7FFFFFFFULL))) || if (((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) ||
((retval = pci_set_consistent_dma_mask(aac->pdev, 0x7FFFFFFFULL)))) ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_32BIT_MASK))))
goto out; goto out;
} }
if ((retval = (*(aac_get_driver_ident(index)->init))(aac))) if ((retval = (*(aac_get_driver_ident(index)->init))(aac)))
......
...@@ -126,7 +126,7 @@ static inline int asd_init_sata(struct domain_device *dev) ...@@ -126,7 +126,7 @@ static inline int asd_init_sata(struct domain_device *dev)
if (w76 & 0x100) /* NCQ? */ if (w76 & 0x100) /* NCQ? */
qdepth = (w75 & 0x1F) + 1; qdepth = (w75 & 0x1F) + 1;
asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK, asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK,
(1<<qdepth)-1); (1ULL<<qdepth)-1);
asd_ddbsite_write_byte(asd_ha, ddb, NUM_SATA_TAGS, qdepth); asd_ddbsite_write_byte(asd_ha, ddb, NUM_SATA_TAGS, qdepth);
} }
if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM || if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM ||
......
...@@ -81,6 +81,9 @@ static struct scsi_host_template aic94xx_sht = { ...@@ -81,6 +81,9 @@ static struct scsi_host_template aic94xx_sht = {
.use_clustering = ENABLE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING,
.eh_device_reset_handler = sas_eh_device_reset_handler, .eh_device_reset_handler = sas_eh_device_reset_handler,
.eh_bus_reset_handler = sas_eh_bus_reset_handler, .eh_bus_reset_handler = sas_eh_bus_reset_handler,
.slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
}; };
static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha) static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha)
......
...@@ -74,8 +74,13 @@ static inline int asd_map_scatterlist(struct sas_task *task, ...@@ -74,8 +74,13 @@ static inline int asd_map_scatterlist(struct sas_task *task,
return 0; return 0;
} }
num_sg = pci_map_sg(asd_ha->pcidev, task->scatter, task->num_scatter, /* STP tasks come from libata which has already mapped
task->data_dir); * the SG list */
if (sas_protocol_ata(task->task_proto))
num_sg = task->num_scatter;
else
num_sg = pci_map_sg(asd_ha->pcidev, task->scatter,
task->num_scatter, task->data_dir);
if (num_sg == 0) if (num_sg == 0)
return -ENOMEM; return -ENOMEM;
...@@ -120,8 +125,9 @@ static inline int asd_map_scatterlist(struct sas_task *task, ...@@ -120,8 +125,9 @@ static inline int asd_map_scatterlist(struct sas_task *task,
return 0; return 0;
err_unmap: err_unmap:
pci_unmap_sg(asd_ha->pcidev, task->scatter, task->num_scatter, if (sas_protocol_ata(task->task_proto))
task->data_dir); pci_unmap_sg(asd_ha->pcidev, task->scatter, task->num_scatter,
task->data_dir);
return res; return res;
} }
...@@ -142,8 +148,9 @@ static inline void asd_unmap_scatterlist(struct asd_ascb *ascb) ...@@ -142,8 +148,9 @@ static inline void asd_unmap_scatterlist(struct asd_ascb *ascb)
} }
asd_free_coherent(asd_ha, ascb->sg_arr); asd_free_coherent(asd_ha, ascb->sg_arr);
pci_unmap_sg(asd_ha->pcidev, task->scatter, task->num_scatter, if (task->task_proto != SAS_PROTOCOL_STP)
task->data_dir); pci_unmap_sg(asd_ha->pcidev, task->scatter, task->num_scatter,
task->data_dir);
} }
/* ---------- Task complete tasklet ---------- */ /* ---------- Task complete tasklet ---------- */
...@@ -391,7 +398,6 @@ static int asd_build_ata_ascb(struct asd_ascb *ascb, struct sas_task *task, ...@@ -391,7 +398,6 @@ static int asd_build_ata_ascb(struct asd_ascb *ascb, struct sas_task *task,
scb->ata_task.total_xfer_len = cpu_to_le32(task->total_xfer_len); scb->ata_task.total_xfer_len = cpu_to_le32(task->total_xfer_len);
scb->ata_task.fis = task->ata_task.fis; scb->ata_task.fis = task->ata_task.fis;
scb->ata_task.fis.fis_type = 0x27;
if (likely(!task->ata_task.device_control_reg_update)) if (likely(!task->ata_task.device_control_reg_update))
scb->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */ scb->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */
scb->ata_task.fis.flags &= 0xF0; /* PM_PORT field shall be 0 */ scb->ata_task.fis.flags &= 0xF0; /* PM_PORT field shall be 0 */
......
...@@ -74,6 +74,7 @@ bvme6000_probe(struct device *dev) ...@@ -74,6 +74,7 @@ bvme6000_probe(struct device *dev)
goto out_put_host; goto out_put_host;
} }
dev_set_drvdata(dev, host);
scsi_scan_host(host); scsi_scan_host(host);
return 0; return 0;
...@@ -89,7 +90,7 @@ bvme6000_probe(struct device *dev) ...@@ -89,7 +90,7 @@ bvme6000_probe(struct device *dev)
static __devexit int static __devexit int
bvme6000_device_remove(struct device *dev) bvme6000_device_remove(struct device *dev)
{ {
struct Scsi_Host *host = dev_to_shost(dev); struct Scsi_Host *host = dev_get_drvdata(dev);
struct NCR_700_Host_Parameters *hostdata = shost_priv(host); struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
scsi_remove_host(host); scsi_remove_host(host);
......
...@@ -220,7 +220,7 @@ ...@@ -220,7 +220,7 @@
#define ESP_BUSID_RESELID 0x10 #define ESP_BUSID_RESELID 0x10
#define ESP_BUSID_CTR32BIT 0x40 #define ESP_BUSID_CTR32BIT 0x40
#define ESP_BUS_TIMEOUT 250 /* In milli-seconds */ #define ESP_BUS_TIMEOUT 275 /* In milli-seconds */
#define ESP_TIMEO_CONST 8192 #define ESP_TIMEO_CONST 8192
#define ESP_NEG_DEFP(mhz, cfact) \ #define ESP_NEG_DEFP(mhz, cfact) \
((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact))) ((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact)))
......
...@@ -30,6 +30,13 @@ config SCSI_SAS_LIBSAS ...@@ -30,6 +30,13 @@ config SCSI_SAS_LIBSAS
This provides transport specific helpers for SAS drivers which This provides transport specific helpers for SAS drivers which
use the domain device construct (like the aic94xxx). use the domain device construct (like the aic94xxx).
config SCSI_SAS_ATA
bool "ATA support for libsas (requires libata)"
depends on SCSI_SAS_LIBSAS && ATA
help
Builds in ATA support into libsas. Will necessitate
the loading of libata along with libsas.
config SCSI_SAS_LIBSAS_DEBUG config SCSI_SAS_LIBSAS_DEBUG
bool "Compile the SAS Domain Transport Attributes in debug mode" bool "Compile the SAS Domain Transport Attributes in debug mode"
default y default y
......
...@@ -34,3 +34,4 @@ libsas-y += sas_init.o \ ...@@ -34,3 +34,4 @@ libsas-y += sas_init.o \
sas_discover.o \ sas_discover.o \
sas_expander.o \ sas_expander.o \
sas_scsi_host.o sas_scsi_host.o
libsas-$(CONFIG_SCSI_SAS_ATA) += sas_ata.o
此差异已折叠。
...@@ -55,149 +55,6 @@ void sas_init_dev(struct domain_device *dev) ...@@ -55,149 +55,6 @@ void sas_init_dev(struct domain_device *dev)
} }
} }
static void sas_task_timedout(unsigned long _task)
{
struct sas_task *task = (void *) _task;
unsigned long flags;
spin_lock_irqsave(&task->task_state_lock, flags);
if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
spin_unlock_irqrestore(&task->task_state_lock, flags);
complete(&task->completion);
}
static void sas_disc_task_done(struct sas_task *task)
{
if (!del_timer(&task->timer))
return;
complete(&task->completion);
}
#define SAS_DEV_TIMEOUT 10
/**
* sas_execute_task -- Basic task processing for discovery
* @task: the task to be executed
* @buffer: pointer to buffer to do I/O
* @size: size of @buffer
* @pci_dma_dir: PCI_DMA_...
*/
static int sas_execute_task(struct sas_task *task, void *buffer, int size,
int pci_dma_dir)
{
int res = 0;
struct scatterlist *scatter = NULL;
struct task_status_struct *ts = &task->task_status;
int num_scatter = 0;
int retries = 0;
struct sas_internal *i =
to_sas_internal(task->dev->port->ha->core.shost->transportt);
if (pci_dma_dir != PCI_DMA_NONE) {
scatter = kzalloc(sizeof(*scatter), GFP_KERNEL);
if (!scatter)
goto out;
sg_init_one(scatter, buffer, size);
num_scatter = 1;
}
task->task_proto = task->dev->tproto;
task->scatter = scatter;
task->num_scatter = num_scatter;
task->total_xfer_len = size;
task->data_dir = pci_dma_dir;
task->task_done = sas_disc_task_done;
for (retries = 0; retries < 5; retries++) {
task->task_state_flags = SAS_TASK_STATE_PENDING;
init_completion(&task->completion);
task->timer.data = (unsigned long) task;
task->timer.function = sas_task_timedout;
task->timer.expires = jiffies + SAS_DEV_TIMEOUT*HZ;
add_timer(&task->timer);
res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL);
if (res) {
del_timer(&task->timer);
SAS_DPRINTK("executing SAS discovery task failed:%d\n",
res);
goto ex_err;
}
wait_for_completion(&task->completion);
res = -ETASK;
if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
int res2;
SAS_DPRINTK("task aborted, flags:0x%x\n",
task->task_state_flags);
res2 = i->dft->lldd_abort_task(task);
SAS_DPRINTK("came back from abort task\n");
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
if (res2 == TMF_RESP_FUNC_COMPLETE)
continue; /* Retry the task */
else
goto ex_err;
}
}
if (task->task_status.stat == SAM_BUSY ||
task->task_status.stat == SAM_TASK_SET_FULL ||
task->task_status.stat == SAS_QUEUE_FULL) {
SAS_DPRINTK("task: q busy, sleeping...\n");
schedule_timeout_interruptible(HZ);
} else if (task->task_status.stat == SAM_CHECK_COND) {
struct scsi_sense_hdr shdr;
if (!scsi_normalize_sense(ts->buf, ts->buf_valid_size,
&shdr)) {
SAS_DPRINTK("couldn't normalize sense\n");
continue;
}
if ((shdr.sense_key == 6 && shdr.asc == 0x29) ||
(shdr.sense_key == 2 && shdr.asc == 4 &&
shdr.ascq == 1)) {
SAS_DPRINTK("device %016llx LUN: %016llx "
"powering up or not ready yet, "
"sleeping...\n",
SAS_ADDR(task->dev->sas_addr),
SAS_ADDR(task->ssp_task.LUN));
schedule_timeout_interruptible(5*HZ);
} else if (shdr.sense_key == 1) {
res = 0;
break;
} else if (shdr.sense_key == 5) {
break;
} else {
SAS_DPRINTK("dev %016llx LUN: %016llx "
"sense key:0x%x ASC:0x%x ASCQ:0x%x"
"\n",
SAS_ADDR(task->dev->sas_addr),
SAS_ADDR(task->ssp_task.LUN),
shdr.sense_key,
shdr.asc, shdr.ascq);
}
} else if (task->task_status.resp != SAS_TASK_COMPLETE ||
task->task_status.stat != SAM_GOOD) {
SAS_DPRINTK("task finished with resp:0x%x, "
"stat:0x%x\n",
task->task_status.resp,
task->task_status.stat);
goto ex_err;
} else {
res = 0;
break;
}
}
ex_err:
if (pci_dma_dir != PCI_DMA_NONE)
kfree(scatter);
out:
return res;
}
/* ---------- Domain device discovery ---------- */ /* ---------- Domain device discovery ---------- */
/** /**
...@@ -255,6 +112,7 @@ static int sas_get_port_device(struct asd_sas_port *port) ...@@ -255,6 +112,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
switch (dev->dev_type) { switch (dev->dev_type) {
case SAS_END_DEV: case SAS_END_DEV:
case SATA_DEV:
rphy = sas_end_device_alloc(port->port); rphy = sas_end_device_alloc(port->port);
break; break;
case EDGE_DEV: case EDGE_DEV:
...@@ -265,7 +123,6 @@ static int sas_get_port_device(struct asd_sas_port *port) ...@@ -265,7 +123,6 @@ static int sas_get_port_device(struct asd_sas_port *port)
rphy = sas_expander_alloc(port->port, rphy = sas_expander_alloc(port->port,
SAS_FANOUT_EXPANDER_DEVICE); SAS_FANOUT_EXPANDER_DEVICE);
break; break;
case SATA_DEV:
default: default:
printk("ERROR: Unidentified device type %d\n", dev->dev_type); printk("ERROR: Unidentified device type %d\n", dev->dev_type);
rphy = NULL; rphy = NULL;
...@@ -292,207 +149,15 @@ static int sas_get_port_device(struct asd_sas_port *port) ...@@ -292,207 +149,15 @@ static int sas_get_port_device(struct asd_sas_port *port)
port->disc.max_level = 0; port->disc.max_level = 0;
dev->rphy = rphy; dev->rphy = rphy;
spin_lock(&port->dev_list_lock); spin_lock_irq(&port->dev_list_lock);
list_add_tail(&dev->dev_list_node, &port->dev_list); list_add_tail(&dev->dev_list_node, &port->dev_list);
spin_unlock(&port->dev_list_lock); spin_unlock_irq(&port->dev_list_lock);
return 0; return 0;
} }
/* ---------- Discover and Revalidate ---------- */ /* ---------- Discover and Revalidate ---------- */
/* ---------- SATA ---------- */
static void sas_get_ata_command_set(struct domain_device *dev)
{
struct dev_to_host_fis *fis =
(struct dev_to_host_fis *) dev->frame_rcvd;
if ((fis->sector_count == 1 && /* ATA */
fis->lbal == 1 &&
fis->lbam == 0 &&
fis->lbah == 0 &&
fis->device == 0)
||
(fis->sector_count == 0 && /* CE-ATA (mATA) */
fis->lbal == 0 &&
fis->lbam == 0xCE &&
fis->lbah == 0xAA &&
(fis->device & ~0x10) == 0))
dev->sata_dev.command_set = ATA_COMMAND_SET;
else if ((fis->interrupt_reason == 1 && /* ATAPI */
fis->lbal == 1 &&
fis->byte_count_low == 0x14 &&
fis->byte_count_high == 0xEB &&
(fis->device & ~0x10) == 0))
dev->sata_dev.command_set = ATAPI_COMMAND_SET;
else if ((fis->sector_count == 1 && /* SEMB */
fis->lbal == 1 &&
fis->lbam == 0x3C &&
fis->lbah == 0xC3 &&
fis->device == 0)
||
(fis->interrupt_reason == 1 && /* SATA PM */
fis->lbal == 1 &&
fis->byte_count_low == 0x69 &&
fis->byte_count_high == 0x96 &&
(fis->device & ~0x10) == 0))
/* Treat it as a superset? */
dev->sata_dev.command_set = ATAPI_COMMAND_SET;
}
/**
* sas_issue_ata_cmd -- Basic SATA command processing for discovery
* @dev: the device to send the command to
* @command: the command register
* @features: the features register
* @buffer: pointer to buffer to do I/O
* @size: size of @buffer
* @pci_dma_dir: PCI_DMA_...
*/
static int sas_issue_ata_cmd(struct domain_device *dev, u8 command,
u8 features, void *buffer, int size,
int pci_dma_dir)
{
int res = 0;
struct sas_task *task;
struct dev_to_host_fis *d2h_fis = (struct dev_to_host_fis *)
&dev->frame_rcvd[0];
res = -ENOMEM;
task = sas_alloc_task(GFP_KERNEL);
if (!task)
goto out;
task->dev = dev;
task->ata_task.fis.command = command;
task->ata_task.fis.features = features;
task->ata_task.fis.device = d2h_fis->device;
task->ata_task.retry_count = 1;
res = sas_execute_task(task, buffer, size, pci_dma_dir);
sas_free_task(task);
out:
return res;
}
static void sas_sata_propagate_sas_addr(struct domain_device *dev)
{
unsigned long flags;
struct asd_sas_port *port = dev->port;
struct asd_sas_phy *phy;
BUG_ON(dev->parent);
memcpy(port->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE);
spin_lock_irqsave(&port->phy_list_lock, flags);
list_for_each_entry(phy, &port->phy_list, port_phy_el)
memcpy(phy->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE);
spin_unlock_irqrestore(&port->phy_list_lock, flags);
}
#define ATA_IDENTIFY_DEV 0xEC
#define ATA_IDENTIFY_PACKET_DEV 0xA1
#define ATA_SET_FEATURES 0xEF
#define ATA_FEATURE_PUP_STBY_SPIN_UP 0x07
/**
* sas_discover_sata_dev -- discover a STP/SATA device (SATA_DEV)
* @dev: STP/SATA device of interest (ATA/ATAPI)
*
* The LLDD has already been notified of this device, so that we can
* send FISes to it. Here we try to get IDENTIFY DEVICE or IDENTIFY
* PACKET DEVICE, if ATAPI device, so that the LLDD can fine-tune its
* performance for this device.
*/
static int sas_discover_sata_dev(struct domain_device *dev)
{
int res;
__le16 *identify_x;
u8 command;
identify_x = kzalloc(512, GFP_KERNEL);
if (!identify_x)
return -ENOMEM;
if (dev->sata_dev.command_set == ATA_COMMAND_SET) {
dev->sata_dev.identify_device = identify_x;
command = ATA_IDENTIFY_DEV;
} else {
dev->sata_dev.identify_packet_device = identify_x;
command = ATA_IDENTIFY_PACKET_DEV;
}
res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512,
PCI_DMA_FROMDEVICE);
if (res)
goto out_err;
/* lives on the media? */
if (le16_to_cpu(identify_x[0]) & 4) {
/* incomplete response */
SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to "
"dev %llx\n", SAS_ADDR(dev->sas_addr));
if (!le16_to_cpu(identify_x[83] & (1<<6)))
goto cont1;
res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES,
ATA_FEATURE_PUP_STBY_SPIN_UP,
NULL, 0, PCI_DMA_NONE);
if (res)
goto cont1;
schedule_timeout_interruptible(5*HZ); /* More time? */
res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512,
PCI_DMA_FROMDEVICE);
if (res)
goto out_err;
}
cont1:
/* Get WWN */
if (dev->port->oob_mode != SATA_OOB_MODE) {
memcpy(dev->sas_addr, dev->sata_dev.rps_resp.rps.stp_sas_addr,
SAS_ADDR_SIZE);
} else if (dev->sata_dev.command_set == ATA_COMMAND_SET &&
(le16_to_cpu(dev->sata_dev.identify_device[108]) & 0xF000)
== 0x5000) {
int i;
for (i = 0; i < 4; i++) {
dev->sas_addr[2*i] =
(le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0xFF00) >> 8;
dev->sas_addr[2*i+1] =
le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0x00FF;
}
}
sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr);
if (!dev->parent)
sas_sata_propagate_sas_addr(dev);
/* XXX Hint: register this SATA device with SATL.
When this returns, dev->sata_dev->lu is alive and
present.
sas_satl_register_dev(dev);
*/
return 0;
out_err:
dev->sata_dev.identify_packet_device = NULL;
dev->sata_dev.identify_device = NULL;
kfree(identify_x);
return res;
}
static int sas_discover_sata_pm(struct domain_device *dev)
{
return -ENODEV;
}
int sas_notify_lldd_dev_found(struct domain_device *dev) int sas_notify_lldd_dev_found(struct domain_device *dev)
{ {
int res = 0; int res = 0;
...@@ -525,60 +190,6 @@ void sas_notify_lldd_dev_gone(struct domain_device *dev) ...@@ -525,60 +190,6 @@ void sas_notify_lldd_dev_gone(struct domain_device *dev)
/* ---------- Common/dispatchers ---------- */ /* ---------- Common/dispatchers ---------- */
/**
* sas_discover_sata -- discover an STP/SATA domain device
* @dev: pointer to struct domain_device of interest
*
* First we notify the LLDD of this device, so we can send frames to
* it. Then depending on the type of device we call the appropriate
* discover functions. Once device discover is done, we notify the
* LLDD so that it can fine-tune its parameters for the device, by
* removing it and then adding it. That is, the second time around,
* the driver would have certain fields, that it is looking at, set.
* Finally we initialize the kobj so that the device can be added to
* the system at registration time. Devices directly attached to a HA
* port, have no parents. All other devices do, and should have their
* "parent" pointer set appropriately before calling this function.
*/
int sas_discover_sata(struct domain_device *dev)
{
int res;
sas_get_ata_command_set(dev);
res = sas_notify_lldd_dev_found(dev);
if (res)
goto out_err2;
switch (dev->dev_type) {
case SATA_DEV:
res = sas_discover_sata_dev(dev);
break;
case SATA_PM:
res = sas_discover_sata_pm(dev);
break;
default:
break;
}
if (res)
goto out_err;
sas_notify_lldd_dev_gone(dev);
res = sas_notify_lldd_dev_found(dev);
if (res)
goto out_err2;
res = sas_rphy_add(dev->rphy);
if (res)
goto out_err;
return res;
out_err:
sas_notify_lldd_dev_gone(dev);
out_err2:
return res;
}
/** /**
* sas_discover_end_dev -- discover an end device (SSP, etc) * sas_discover_end_dev -- discover an end device (SSP, etc)
...@@ -685,11 +296,14 @@ static void sas_discover_domain(struct work_struct *work) ...@@ -685,11 +296,14 @@ static void sas_discover_domain(struct work_struct *work)
case FANOUT_DEV: case FANOUT_DEV:
error = sas_discover_root_expander(dev); error = sas_discover_root_expander(dev);
break; break;
#ifdef CONFIG_SCSI_SAS_ATA
case SATA_DEV: case SATA_DEV:
case SATA_PM: case SATA_PM:
error = sas_discover_sata(dev); error = sas_discover_sata(dev);
break; break;
#endif
default: default:
error = -ENXIO;
SAS_DPRINTK("unhandled device %d\n", dev->dev_type); SAS_DPRINTK("unhandled device %d\n", dev->dev_type);
break; break;
} }
...@@ -698,9 +312,9 @@ static void sas_discover_domain(struct work_struct *work) ...@@ -698,9 +312,9 @@ static void sas_discover_domain(struct work_struct *work)
sas_rphy_free(dev->rphy); sas_rphy_free(dev->rphy);
dev->rphy = NULL; dev->rphy = NULL;
spin_lock(&port->dev_list_lock); spin_lock_irq(&port->dev_list_lock);
list_del_init(&dev->dev_list_node); list_del_init(&dev->dev_list_node);
spin_unlock(&port->dev_list_lock); spin_unlock_irq(&port->dev_list_lock);
kfree(dev); /* not kobject_register-ed yet */ kfree(dev); /* not kobject_register-ed yet */
port->port_dev = NULL; port->port_dev = NULL;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
*/ */
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/blkdev.h>
#include "sas_internal.h" #include "sas_internal.h"
...@@ -36,14 +37,6 @@ static int sas_configure_phy(struct domain_device *dev, int phy_id, ...@@ -36,14 +37,6 @@ static int sas_configure_phy(struct domain_device *dev, int phy_id,
u8 *sas_addr, int include); u8 *sas_addr, int include);
static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr); static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr);
#if 0
/* FIXME: smp needs to migrate into the sas class */
static ssize_t smp_portal_read(struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
static ssize_t smp_portal_write(struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
#endif
/* ---------- SMP task management ---------- */ /* ---------- SMP task management ---------- */
static void smp_task_timedout(unsigned long _task) static void smp_task_timedout(unsigned long _task)
...@@ -220,6 +213,36 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, ...@@ -220,6 +213,36 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
#define DISCOVER_REQ_SIZE 16 #define DISCOVER_REQ_SIZE 16
#define DISCOVER_RESP_SIZE 56 #define DISCOVER_RESP_SIZE 56
static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req,
u8 *disc_resp, int single)
{
int i, res;
disc_req[9] = single;
for (i = 1 ; i < 3; i++) {
struct discover_resp *dr;
res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE,
disc_resp, DISCOVER_RESP_SIZE);
if (res)
return res;
/* This is detecting a failure to transmit inital
* dev to host FIS as described in section G.5 of
* sas-2 r 04b */
dr = &((struct smp_resp *)disc_resp)->disc;
if (!(dr->attached_dev_type == 0 &&
dr->attached_sata_dev))
break;
/* In order to generate the dev to host FIS, we
* send a link reset to the expander port */
sas_smp_phy_control(dev, single, PHY_FUNC_LINK_RESET, NULL);
/* Wait for the reset to trigger the negotiation */
msleep(500);
}
sas_set_ex_phy(dev, single, disc_resp);
return 0;
}
static int sas_ex_phy_discover(struct domain_device *dev, int single) static int sas_ex_phy_discover(struct domain_device *dev, int single)
{ {
struct expander_device *ex = &dev->ex_dev; struct expander_device *ex = &dev->ex_dev;
...@@ -240,23 +263,15 @@ static int sas_ex_phy_discover(struct domain_device *dev, int single) ...@@ -240,23 +263,15 @@ static int sas_ex_phy_discover(struct domain_device *dev, int single)
disc_req[1] = SMP_DISCOVER; disc_req[1] = SMP_DISCOVER;
if (0 <= single && single < ex->num_phys) { if (0 <= single && single < ex->num_phys) {
disc_req[9] = single; res = sas_ex_phy_discover_helper(dev, disc_req, disc_resp, single);
res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE,
disc_resp, DISCOVER_RESP_SIZE);
if (res)
goto out_err;
sas_set_ex_phy(dev, single, disc_resp);
} else { } else {
int i; int i;
for (i = 0; i < ex->num_phys; i++) { for (i = 0; i < ex->num_phys; i++) {
disc_req[9] = i; res = sas_ex_phy_discover_helper(dev, disc_req,
res = smp_execute_task(dev, disc_req, disc_resp, i);
DISCOVER_REQ_SIZE, disc_resp,
DISCOVER_RESP_SIZE);
if (res) if (res)
goto out_err; goto out_err;
sas_set_ex_phy(dev, i, disc_resp);
} }
} }
out_err: out_err:
...@@ -520,6 +535,8 @@ int sas_smp_get_phy_events(struct sas_phy *phy) ...@@ -520,6 +535,8 @@ int sas_smp_get_phy_events(struct sas_phy *phy)
} }
#ifdef CONFIG_SCSI_SAS_ATA
#define RPS_REQ_SIZE 16 #define RPS_REQ_SIZE 16
#define RPS_RESP_SIZE 60 #define RPS_RESP_SIZE 60
...@@ -529,6 +546,7 @@ static int sas_get_report_phy_sata(struct domain_device *dev, ...@@ -529,6 +546,7 @@ static int sas_get_report_phy_sata(struct domain_device *dev,
{ {
int res; int res;
u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE); u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE);
u8 *resp = (u8 *)rps_resp;
if (!rps_req) if (!rps_req)
return -ENOMEM; return -ENOMEM;
...@@ -539,9 +557,30 @@ static int sas_get_report_phy_sata(struct domain_device *dev, ...@@ -539,9 +557,30 @@ static int sas_get_report_phy_sata(struct domain_device *dev,
res = smp_execute_task(dev, rps_req, RPS_REQ_SIZE, res = smp_execute_task(dev, rps_req, RPS_REQ_SIZE,
rps_resp, RPS_RESP_SIZE); rps_resp, RPS_RESP_SIZE);
/* 0x34 is the FIS type for the D2H fis. There's a potential
* standards cockup here. sas-2 explicitly specifies the FIS
* should be encoded so that FIS type is in resp[24].
* However, some expanders endian reverse this. Undo the
* reversal here */
if (!res && resp[27] == 0x34 && resp[24] != 0x34) {
int i;
for (i = 0; i < 5; i++) {
int j = 24 + (i*4);
u8 a, b;
a = resp[j + 0];
b = resp[j + 1];
resp[j + 0] = resp[j + 3];
resp[j + 1] = resp[j + 2];
resp[j + 2] = b;
resp[j + 3] = a;
}
}
kfree(rps_req); kfree(rps_req);
return 0; return res;
} }
#endif
static void sas_ex_get_linkrate(struct domain_device *parent, static void sas_ex_get_linkrate(struct domain_device *parent,
struct domain_device *child, struct domain_device *child,
...@@ -609,6 +648,7 @@ static struct domain_device *sas_ex_discover_end_dev( ...@@ -609,6 +648,7 @@ static struct domain_device *sas_ex_discover_end_dev(
} }
sas_ex_get_linkrate(parent, child, phy); sas_ex_get_linkrate(parent, child, phy);
#ifdef CONFIG_SCSI_SAS_ATA
if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) {
child->dev_type = SATA_DEV; child->dev_type = SATA_DEV;
if (phy->attached_tproto & SAS_PROTO_STP) if (phy->attached_tproto & SAS_PROTO_STP)
...@@ -625,16 +665,30 @@ static struct domain_device *sas_ex_discover_end_dev( ...@@ -625,16 +665,30 @@ static struct domain_device *sas_ex_discover_end_dev(
} }
memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis, memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis,
sizeof(struct dev_to_host_fis)); sizeof(struct dev_to_host_fis));
rphy = sas_end_device_alloc(phy->port);
if (unlikely(!rphy))
goto out_free;
sas_init_dev(child); sas_init_dev(child);
child->rphy = rphy;
spin_lock_irq(&parent->port->dev_list_lock);
list_add_tail(&child->dev_list_node, &parent->port->dev_list);
spin_unlock_irq(&parent->port->dev_list_lock);
res = sas_discover_sata(child); res = sas_discover_sata(child);
if (res) { if (res) {
SAS_DPRINTK("sas_discover_sata() for device %16llx at " SAS_DPRINTK("sas_discover_sata() for device %16llx at "
"%016llx:0x%x returned 0x%x\n", "%016llx:0x%x returned 0x%x\n",
SAS_ADDR(child->sas_addr), SAS_ADDR(child->sas_addr),
SAS_ADDR(parent->sas_addr), phy_id, res); SAS_ADDR(parent->sas_addr), phy_id, res);
goto out_free; goto out_list_del;
} }
} else if (phy->attached_tproto & SAS_PROTO_SSP) { } else
#endif
if (phy->attached_tproto & SAS_PROTO_SSP) {
child->dev_type = SAS_END_DEV; child->dev_type = SAS_END_DEV;
rphy = sas_end_device_alloc(phy->port); rphy = sas_end_device_alloc(phy->port);
/* FIXME: error handling */ /* FIXME: error handling */
...@@ -646,9 +700,9 @@ static struct domain_device *sas_ex_discover_end_dev( ...@@ -646,9 +700,9 @@ static struct domain_device *sas_ex_discover_end_dev(
child->rphy = rphy; child->rphy = rphy;
sas_fill_in_rphy(child, rphy); sas_fill_in_rphy(child, rphy);
spin_lock(&parent->port->dev_list_lock); spin_lock_irq(&parent->port->dev_list_lock);
list_add_tail(&child->dev_list_node, &parent->port->dev_list); list_add_tail(&child->dev_list_node, &parent->port->dev_list);
spin_unlock(&parent->port->dev_list_lock); spin_unlock_irq(&parent->port->dev_list_lock);
res = sas_discover_end_dev(child); res = sas_discover_end_dev(child);
if (res) { if (res) {
...@@ -662,6 +716,7 @@ static struct domain_device *sas_ex_discover_end_dev( ...@@ -662,6 +716,7 @@ static struct domain_device *sas_ex_discover_end_dev(
SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n",
phy->attached_tproto, SAS_ADDR(parent->sas_addr), phy->attached_tproto, SAS_ADDR(parent->sas_addr),
phy_id); phy_id);
goto out_free;
} }
list_add_tail(&child->siblings, &parent_ex->children); list_add_tail(&child->siblings, &parent_ex->children);
...@@ -761,9 +816,9 @@ static struct domain_device *sas_ex_discover_expander( ...@@ -761,9 +816,9 @@ static struct domain_device *sas_ex_discover_expander(
sas_fill_in_rphy(child, rphy); sas_fill_in_rphy(child, rphy);
sas_rphy_add(rphy); sas_rphy_add(rphy);
spin_lock(&parent->port->dev_list_lock); spin_lock_irq(&parent->port->dev_list_lock);
list_add_tail(&child->dev_list_node, &parent->port->dev_list); list_add_tail(&child->dev_list_node, &parent->port->dev_list);
spin_unlock(&parent->port->dev_list_lock); spin_unlock_irq(&parent->port->dev_list_lock);
res = sas_discover_expander(child); res = sas_discover_expander(child);
if (res) { if (res) {
...@@ -1359,30 +1414,6 @@ static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr) ...@@ -1359,30 +1414,6 @@ static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr)
return 0; return 0;
} }
#if 0
#define SMP_BIN_ATTR_NAME "smp_portal"
static void sas_ex_smp_hook(struct domain_device *dev)
{
struct expander_device *ex_dev = &dev->ex_dev;
struct bin_attribute *bin_attr = &ex_dev->smp_bin_attr;
memset(bin_attr, 0, sizeof(*bin_attr));
bin_attr->attr.name = SMP_BIN_ATTR_NAME;
bin_attr->attr.mode = 0600;
bin_attr->size = 0;
bin_attr->private = NULL;
bin_attr->read = smp_portal_read;
bin_attr->write= smp_portal_write;
bin_attr->mmap = NULL;
ex_dev->smp_portal_pid = -1;
init_MUTEX(&ex_dev->smp_sema);
}
#endif
/** /**
* sas_discover_expander -- expander discovery * sas_discover_expander -- expander discovery
* @ex: pointer to expander domain device * @ex: pointer to expander domain device
...@@ -1844,76 +1875,49 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) ...@@ -1844,76 +1875,49 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev)
return res; return res;
} }
#if 0 int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
/* ---------- SMP portal ---------- */ struct request *req)
static ssize_t smp_portal_write(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t offs, size_t size)
{ {
struct domain_device *dev = to_dom_device(kobj); struct domain_device *dev;
struct expander_device *ex = &dev->ex_dev; int ret, type = rphy->identify.device_type;
struct request *rsp = req->next_rq;
if (offs != 0)
return -EFBIG;
else if (size == 0)
return 0;
down_interruptible(&ex->smp_sema); if (!rsp) {
if (ex->smp_req) printk("%s: space for a smp response is missing\n",
kfree(ex->smp_req); __FUNCTION__);
ex->smp_req = kzalloc(size, GFP_USER); return -EINVAL;
if (!ex->smp_req) {
up(&ex->smp_sema);
return -ENOMEM;
} }
memcpy(ex->smp_req, buf, size);
ex->smp_req_size = size;
ex->smp_portal_pid = current->pid;
up(&ex->smp_sema);
return size; /* seems aic94xx doesn't support */
} if (!rphy) {
printk("%s: can we send a smp request to a host?\n",
static ssize_t smp_portal_read(struct kobject *kobj, __FUNCTION__);
struct bin_attribute *bin_attr, return -EINVAL;
char *buf, loff_t offs, size_t size) }
{
struct domain_device *dev = to_dom_device(kobj);
struct expander_device *ex = &dev->ex_dev;
u8 *smp_resp;
int res = -EINVAL;
/* XXX: sysfs gives us an offset of 0x10 or 0x8 while in fact
* it should be 0.
*/
down_interruptible(&ex->smp_sema); if (type != SAS_EDGE_EXPANDER_DEVICE &&
if (!ex->smp_req || ex->smp_portal_pid != current->pid) type != SAS_FANOUT_EXPANDER_DEVICE) {
goto out; printk("%s: can we send a smp request to a device?\n",
__FUNCTION__);
return -EINVAL;
}
res = 0; dev = sas_find_dev_by_rphy(rphy);
if (size == 0) if (!dev) {
goto out; printk("%s: fail to find a domain_device?\n", __FUNCTION__);
return -EINVAL;
}
res = -ENOMEM; /* do we need to support multiple segments? */
smp_resp = alloc_smp_resp(size); if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
if (!smp_resp) printk("%s: multiple segments req %u %u, rsp %u %u\n",
goto out; __FUNCTION__, req->bio->bi_vcnt, req->data_len,
res = smp_execute_task(dev, ex->smp_req, ex->smp_req_size, rsp->bio->bi_vcnt, rsp->data_len);
smp_resp, size); return -EINVAL;
if (!res) {
memcpy(buf, smp_resp, size);
res = size;
} }
kfree(smp_resp); ret = smp_execute_task(dev, bio_data(req->bio), req->data_len,
out: bio_data(rsp->bio), rsp->data_len);
kfree(ex->smp_req);
ex->smp_req = NULL; return ret;
ex->smp_req_size = 0;
ex->smp_portal_pid = -1;
up(&ex->smp_sema);
return res;
} }
#endif
...@@ -259,6 +259,7 @@ static struct sas_function_template sft = { ...@@ -259,6 +259,7 @@ static struct sas_function_template sft = {
.phy_reset = sas_phy_reset, .phy_reset = sas_phy_reset,
.set_phy_speed = sas_set_phy_speed, .set_phy_speed = sas_set_phy_speed,
.get_linkerrors = sas_get_linkerrors, .get_linkerrors = sas_get_linkerrors,
.smp_handler = sas_smp_handler,
}; };
struct scsi_transport_template * struct scsi_transport_template *
......
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
#define SAS_DPRINTK(fmt, ...) #define SAS_DPRINTK(fmt, ...)
#endif #endif
#define TO_SAS_TASK(_scsi_cmd) ((void *)(_scsi_cmd)->host_scribble)
#define ASSIGN_SAS_TASK(_sc, _t) do { (_sc)->host_scribble = (void *) _t; } while (0)
void sas_scsi_recover_host(struct Scsi_Host *shost); void sas_scsi_recover_host(struct Scsi_Host *shost);
int sas_show_class(enum sas_class class, char *buf); int sas_show_class(enum sas_class class, char *buf);
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <scsi/scsi_eh.h> #include <scsi/scsi_eh.h>
#include <scsi/scsi_transport.h> #include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h> #include <scsi/scsi_transport_sas.h>
#include <scsi/sas_ata.h>
#include "../scsi_sas_internal.h" #include "../scsi_sas_internal.h"
#include "../scsi_transport_api.h" #include "../scsi_transport_api.h"
#include "../scsi_priv.h" #include "../scsi_priv.h"
...@@ -42,12 +43,10 @@ ...@@ -42,12 +43,10 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/freezer.h> #include <linux/freezer.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/libata.h>
/* ---------- SCSI Host glue ---------- */ /* ---------- SCSI Host glue ---------- */
#define TO_SAS_TASK(_scsi_cmd) ((void *)(_scsi_cmd)->host_scribble)
#define ASSIGN_SAS_TASK(_sc, _t) do { (_sc)->host_scribble = (void *) _t; } while (0)
static void sas_scsi_task_done(struct sas_task *task) static void sas_scsi_task_done(struct sas_task *task)
{ {
struct task_status_struct *ts = &task->task_status; struct task_status_struct *ts = &task->task_status;
...@@ -172,7 +171,7 @@ static struct sas_task *sas_create_task(struct scsi_cmnd *cmd, ...@@ -172,7 +171,7 @@ static struct sas_task *sas_create_task(struct scsi_cmnd *cmd,
return task; return task;
} }
static int sas_queue_up(struct sas_task *task) int sas_queue_up(struct sas_task *task)
{ {
struct sas_ha_struct *sas_ha = task->dev->port->ha; struct sas_ha_struct *sas_ha = task->dev->port->ha;
struct scsi_core *core = &sas_ha->core; struct scsi_core *core = &sas_ha->core;
...@@ -213,6 +212,16 @@ int sas_queuecommand(struct scsi_cmnd *cmd, ...@@ -213,6 +212,16 @@ int sas_queuecommand(struct scsi_cmnd *cmd,
struct sas_ha_struct *sas_ha = dev->port->ha; struct sas_ha_struct *sas_ha = dev->port->ha;
struct sas_task *task; struct sas_task *task;
if (dev_is_sata(dev)) {
unsigned long flags;
spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
res = ata_sas_queuecmd(cmd, scsi_done,
dev->sata_dev.ap);
spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags);
goto out;
}
res = -ENOMEM; res = -ENOMEM;
task = sas_create_task(cmd, dev, GFP_ATOMIC); task = sas_create_task(cmd, dev, GFP_ATOMIC);
if (!task) if (!task)
...@@ -684,6 +693,16 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) ...@@ -684,6 +693,16 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
return EH_NOT_HANDLED; return EH_NOT_HANDLED;
} }
int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
{
struct domain_device *dev = sdev_to_domain_dev(sdev);
if (dev_is_sata(dev))
return ata_scsi_ioctl(sdev, cmd, arg);
return -EINVAL;
}
struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy) struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy)
{ {
struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent); struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent);
...@@ -723,10 +742,17 @@ static inline struct domain_device *sas_find_target(struct scsi_target *starget) ...@@ -723,10 +742,17 @@ static inline struct domain_device *sas_find_target(struct scsi_target *starget)
int sas_target_alloc(struct scsi_target *starget) int sas_target_alloc(struct scsi_target *starget)
{ {
struct domain_device *found_dev = sas_find_target(starget); struct domain_device *found_dev = sas_find_target(starget);
int res;
if (!found_dev) if (!found_dev)
return -ENODEV; return -ENODEV;
if (dev_is_sata(found_dev)) {
res = sas_ata_init_host_and_port(found_dev, starget);
if (res)
return res;
}
starget->hostdata = found_dev; starget->hostdata = found_dev;
return 0; return 0;
} }
...@@ -741,6 +767,11 @@ int sas_slave_configure(struct scsi_device *scsi_dev) ...@@ -741,6 +767,11 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
BUG_ON(dev->rphy->identify.device_type != SAS_END_DEVICE); BUG_ON(dev->rphy->identify.device_type != SAS_END_DEVICE);
if (dev_is_sata(dev)) {
ata_sas_slave_configure(scsi_dev, dev->sata_dev.ap);
return 0;
}
sas_ha = dev->port->ha; sas_ha = dev->port->ha;
sas_read_port_mode_page(scsi_dev); sas_read_port_mode_page(scsi_dev);
...@@ -764,6 +795,10 @@ int sas_slave_configure(struct scsi_device *scsi_dev) ...@@ -764,6 +795,10 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
void sas_slave_destroy(struct scsi_device *scsi_dev) void sas_slave_destroy(struct scsi_device *scsi_dev)
{ {
struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
if (dev_is_sata(dev))
ata_port_disable(dev->sata_dev.ap);
} }
int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth) int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth)
...@@ -980,10 +1015,38 @@ void sas_task_abort(struct sas_task *task) ...@@ -980,10 +1015,38 @@ void sas_task_abort(struct sas_task *task)
return; return;
} }
if (dev_is_sata(task->dev)) {
sas_ata_task_abort(task);
return;
}
scsi_req_abort_cmd(sc); scsi_req_abort_cmd(sc);
scsi_schedule_eh(sc->device->host); scsi_schedule_eh(sc->device->host);
} }
int sas_slave_alloc(struct scsi_device *scsi_dev)
{
struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
if (dev_is_sata(dev))
return ata_sas_port_init(dev->sata_dev.ap);
return 0;
}
void sas_target_destroy(struct scsi_target *starget)
{
struct domain_device *found_dev = sas_find_target(starget);
if (!found_dev)
return;
if (dev_is_sata(found_dev))
ata_sas_port_destroy(found_dev->sata_dev.ap);
return;
}
EXPORT_SYMBOL_GPL(sas_queuecommand); EXPORT_SYMBOL_GPL(sas_queuecommand);
EXPORT_SYMBOL_GPL(sas_target_alloc); EXPORT_SYMBOL_GPL(sas_target_alloc);
EXPORT_SYMBOL_GPL(sas_slave_configure); EXPORT_SYMBOL_GPL(sas_slave_configure);
...@@ -997,3 +1060,6 @@ EXPORT_SYMBOL_GPL(sas_phy_reset); ...@@ -997,3 +1060,6 @@ EXPORT_SYMBOL_GPL(sas_phy_reset);
EXPORT_SYMBOL_GPL(sas_phy_enable); EXPORT_SYMBOL_GPL(sas_phy_enable);
EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler);
EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler);
EXPORT_SYMBOL_GPL(sas_slave_alloc);
EXPORT_SYMBOL_GPL(sas_target_destroy);
EXPORT_SYMBOL_GPL(sas_ioctl);
...@@ -89,6 +89,7 @@ mvme16x_probe(struct device *dev) ...@@ -89,6 +89,7 @@ mvme16x_probe(struct device *dev)
out_be32(0xfff4202c, v); out_be32(0xfff4202c, v);
} }
dev_set_drvdata(dev, host);
scsi_scan_host(host); scsi_scan_host(host);
return 0; return 0;
...@@ -104,7 +105,7 @@ mvme16x_probe(struct device *dev) ...@@ -104,7 +105,7 @@ mvme16x_probe(struct device *dev)
static __devexit int static __devexit int
mvme16x_device_remove(struct device *dev) mvme16x_device_remove(struct device *dev)
{ {
struct Scsi_Host *host = dev_to_shost(dev); struct Scsi_Host *host = dev_get_drvdata(dev);
struct NCR_700_Host_Parameters *hostdata = shost_priv(host); struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
/* Disable scsi chip ints */ /* Disable scsi chip ints */
......
...@@ -2,9 +2,12 @@ ...@@ -2,9 +2,12 @@
# PCMCIA SCSI adapter configuration # PCMCIA SCSI adapter configuration
# #
menu "PCMCIA SCSI adapter support" menuconfig SCSI_LOWLEVEL_PCMCIA
bool "PCMCIA SCSI adapter support"
depends on SCSI!=n && PCMCIA!=n depends on SCSI!=n && PCMCIA!=n
if SCSI_LOWLEVEL_PCMCIA && SCSI && PCMCIA
config PCMCIA_AHA152X config PCMCIA_AHA152X
tristate "Adaptec AHA152X PCMCIA support" tristate "Adaptec AHA152X PCMCIA support"
depends on !64BIT depends on !64BIT
...@@ -77,4 +80,4 @@ config PCMCIA_SYM53C500 ...@@ -77,4 +80,4 @@ config PCMCIA_SYM53C500
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called sym53c500_cs. module will be called sym53c500_cs.
endmenu endif # SCSI_LOWLEVEL_PCMCIA
...@@ -98,7 +98,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, ...@@ -98,7 +98,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj,
/* Read NVRAM. */ /* Read NVRAM. */
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->nvram_base, ha->isp_ops->read_nvram(ha, (uint8_t *)buf, ha->nvram_base,
ha->nvram_size); ha->nvram_size);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
...@@ -119,7 +119,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, ...@@ -119,7 +119,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
return 0; return 0;
/* Checksum NVRAM. */ /* Checksum NVRAM. */
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
uint32_t *iter; uint32_t *iter;
uint32_t chksum; uint32_t chksum;
...@@ -143,7 +143,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, ...@@ -143,7 +143,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
/* Write NVRAM. */ /* Write NVRAM. */
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
...@@ -206,7 +206,7 @@ static struct bin_attribute sysfs_optrom_attr = { ...@@ -206,7 +206,7 @@ static struct bin_attribute sysfs_optrom_attr = {
.name = "optrom", .name = "optrom",
.mode = S_IRUSR | S_IWUSR, .mode = S_IRUSR | S_IWUSR,
}, },
.size = OPTROM_SIZE_24XX, .size = 0,
.read = qla2x00_sysfs_read_optrom, .read = qla2x00_sysfs_read_optrom,
.write = qla2x00_sysfs_write_optrom, .write = qla2x00_sysfs_write_optrom,
}; };
...@@ -252,7 +252,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, ...@@ -252,7 +252,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
} }
memset(ha->optrom_buffer, 0, ha->optrom_size); memset(ha->optrom_buffer, 0, ha->optrom_size);
ha->isp_ops.read_optrom(ha, ha->optrom_buffer, 0, ha->isp_ops->read_optrom(ha, ha->optrom_buffer, 0,
ha->optrom_size); ha->optrom_size);
break; break;
case 2: case 2:
...@@ -275,7 +275,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, ...@@ -275,7 +275,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
if (ha->optrom_state != QLA_SWRITING) if (ha->optrom_state != QLA_SWRITING)
break; break;
ha->isp_ops.write_optrom(ha, ha->optrom_buffer, 0, ha->isp_ops->write_optrom(ha, ha->optrom_buffer, 0,
ha->optrom_size); ha->optrom_size);
break; break;
} }
...@@ -305,7 +305,8 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, ...@@ -305,7 +305,8 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj,
/* Read NVRAM. */ /* Read NVRAM. */
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->vpd_base, ha->vpd_size); ha->isp_ops->read_nvram(ha, (uint8_t *)buf, ha->vpd_base,
ha->vpd_size);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
return ha->vpd_size; return ha->vpd_size;
...@@ -325,7 +326,7 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, ...@@ -325,7 +326,7 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj,
/* Write NVRAM. */ /* Write NVRAM. */
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
return count; return count;
...@@ -410,7 +411,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) ...@@ -410,7 +411,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
int ret; int ret;
for (iter = bin_file_entries; iter->name; iter++) { for (iter = bin_file_entries; iter->name; iter++) {
if (iter->is4GBp_only && (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))) if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha))
continue; continue;
ret = sysfs_create_bin_file(&host->shost_gendev.kobj, ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
...@@ -429,7 +430,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) ...@@ -429,7 +430,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
struct sysfs_entry *iter; struct sysfs_entry *iter;
for (iter = bin_file_entries; iter->name; iter++) { for (iter = bin_file_entries; iter->name; iter++) {
if (iter->is4GBp_only && (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))) if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha))
continue; continue;
sysfs_remove_bin_file(&host->shost_gendev.kobj, sysfs_remove_bin_file(&host->shost_gendev.kobj,
...@@ -437,7 +438,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) ...@@ -437,7 +438,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
} }
if (ha->beacon_blink_led == 1) if (ha->beacon_blink_led == 1)
ha->isp_ops.beacon_off(ha); ha->isp_ops->beacon_off(ha);
} }
/* Scsi_Host attributes. */ /* Scsi_Host attributes. */
...@@ -455,7 +456,7 @@ qla2x00_fw_version_show(struct class_device *cdev, char *buf) ...@@ -455,7 +456,7 @@ qla2x00_fw_version_show(struct class_device *cdev, char *buf)
char fw_str[30]; char fw_str[30];
return snprintf(buf, PAGE_SIZE, "%s\n", return snprintf(buf, PAGE_SIZE, "%s\n",
ha->isp_ops.fw_version_str(ha, fw_str)); ha->isp_ops->fw_version_str(ha, fw_str));
} }
static ssize_t static ssize_t
...@@ -507,7 +508,7 @@ qla2x00_pci_info_show(struct class_device *cdev, char *buf) ...@@ -507,7 +508,7 @@ qla2x00_pci_info_show(struct class_device *cdev, char *buf)
char pci_info[30]; char pci_info[30];
return snprintf(buf, PAGE_SIZE, "%s\n", return snprintf(buf, PAGE_SIZE, "%s\n",
ha->isp_ops.pci_info_str(ha, pci_info)); ha->isp_ops->pci_info_str(ha, pci_info));
} }
static ssize_t static ssize_t
...@@ -652,9 +653,9 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf, ...@@ -652,9 +653,9 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf,
return -EINVAL; return -EINVAL;
if (val) if (val)
rval = ha->isp_ops.beacon_on(ha); rval = ha->isp_ops->beacon_on(ha);
else else
rval = ha->isp_ops.beacon_off(ha); rval = ha->isp_ops->beacon_off(ha);
if (rval != QLA_SUCCESS) if (rval != QLA_SUCCESS)
count = 0; count = 0;
...@@ -898,7 +899,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) ...@@ -898,7 +899,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
pfc_host_stat = &ha->fc_host_stat; pfc_host_stat = &ha->fc_host_stat;
memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf,
sizeof(stat_buf) / 4, mb_stat); sizeof(stat_buf) / 4, mb_stat);
} else if (atomic_read(&ha->loop_state) == LOOP_READY && } else if (atomic_read(&ha->loop_state) == LOOP_READY &&
......
此差异已折叠。
...@@ -213,6 +213,43 @@ struct qla24xx_fw_dump { ...@@ -213,6 +213,43 @@ struct qla24xx_fw_dump {
uint32_t ext_mem[1]; uint32_t ext_mem[1];
}; };
struct qla25xx_fw_dump {
uint32_t host_status;
uint32_t host_reg[32];
uint32_t shadow_reg[11];
uint32_t risc_io_reg;
uint16_t mailbox_reg[32];
uint32_t xseq_gp_reg[128];
uint32_t xseq_0_reg[48];
uint32_t xseq_1_reg[16];
uint32_t rseq_gp_reg[128];
uint32_t rseq_0_reg[32];
uint32_t rseq_1_reg[16];
uint32_t rseq_2_reg[16];
uint32_t aseq_gp_reg[128];
uint32_t aseq_0_reg[32];
uint32_t aseq_1_reg[16];
uint32_t aseq_2_reg[16];
uint32_t cmd_dma_reg[16];
uint32_t req0_dma_reg[15];
uint32_t resp0_dma_reg[15];
uint32_t req1_dma_reg[15];
uint32_t xmt0_dma_reg[32];
uint32_t xmt1_dma_reg[32];
uint32_t xmt2_dma_reg[32];
uint32_t xmt3_dma_reg[32];
uint32_t xmt4_dma_reg[32];
uint32_t xmt_data_dma_reg[16];
uint32_t rcvt0_data_dma_reg[32];
uint32_t rcvt1_data_dma_reg[32];
uint32_t risc_gp_reg[128];
uint32_t lmc_reg[128];
uint32_t fpm_hdw_reg[192];
uint32_t fb_hdw_reg[192];
uint32_t code_ram[0x2000];
uint32_t ext_mem[1];
};
#define EFT_NUM_BUFFERS 4 #define EFT_NUM_BUFFERS 4
#define EFT_BYTES_PER_BUFFER 0x4000 #define EFT_BYTES_PER_BUFFER 0x4000
#define EFT_SIZE ((EFT_BYTES_PER_BUFFER) * (EFT_NUM_BUFFERS)) #define EFT_SIZE ((EFT_BYTES_PER_BUFFER) * (EFT_NUM_BUFFERS))
...@@ -246,5 +283,6 @@ struct qla2xxx_fw_dump { ...@@ -246,5 +283,6 @@ struct qla2xxx_fw_dump {
struct qla2100_fw_dump isp21; struct qla2100_fw_dump isp21;
struct qla2300_fw_dump isp23; struct qla2300_fw_dump isp23;
struct qla24xx_fw_dump isp24; struct qla24xx_fw_dump isp24;
struct qla25xx_fw_dump isp25;
} isp; } isp;
}; };
...@@ -1711,6 +1711,14 @@ struct ct_fdmi_hba_attributes { ...@@ -1711,6 +1711,14 @@ struct ct_fdmi_hba_attributes {
#define FDMI_PORT_OS_DEVICE_NAME 5 #define FDMI_PORT_OS_DEVICE_NAME 5
#define FDMI_PORT_HOST_NAME 6 #define FDMI_PORT_HOST_NAME 6
#define FDMI_PORT_SPEED_1GB 0x1
#define FDMI_PORT_SPEED_2GB 0x2
#define FDMI_PORT_SPEED_10GB 0x4
#define FDMI_PORT_SPEED_4GB 0x8
#define FDMI_PORT_SPEED_8GB 0x10
#define FDMI_PORT_SPEED_16GB 0x20
#define FDMI_PORT_SPEED_UNKNOWN 0x8000
struct ct_fdmi_port_attr { struct ct_fdmi_port_attr {
uint16_t type; uint16_t type;
uint16_t len; uint16_t len;
...@@ -2201,6 +2209,7 @@ typedef struct scsi_qla_host { ...@@ -2201,6 +2209,7 @@ typedef struct scsi_qla_host {
#define SWITCH_FOUND BIT_3 #define SWITCH_FOUND BIT_3
#define DFLG_NO_CABLE BIT_4 #define DFLG_NO_CABLE BIT_4
#define PCI_DEVICE_ID_QLOGIC_ISP2532 0x2532
uint32_t device_type; uint32_t device_type;
#define DT_ISP2100 BIT_0 #define DT_ISP2100 BIT_0
#define DT_ISP2200 BIT_1 #define DT_ISP2200 BIT_1
...@@ -2213,8 +2222,11 @@ typedef struct scsi_qla_host { ...@@ -2213,8 +2222,11 @@ typedef struct scsi_qla_host {
#define DT_ISP2432 BIT_8 #define DT_ISP2432 BIT_8
#define DT_ISP5422 BIT_9 #define DT_ISP5422 BIT_9
#define DT_ISP5432 BIT_10 #define DT_ISP5432 BIT_10
#define DT_ISP_LAST (DT_ISP5432 << 1) #define DT_ISP2532 BIT_11
#define DT_ISP_LAST (DT_ISP2532 << 1)
#define DT_IIDMA BIT_26
#define DT_FWI2 BIT_27
#define DT_ZIO_SUPPORTED BIT_28 #define DT_ZIO_SUPPORTED BIT_28
#define DT_OEM_001 BIT_29 #define DT_OEM_001 BIT_29
#define DT_ISP2200A BIT_30 #define DT_ISP2200A BIT_30
...@@ -2232,12 +2244,16 @@ typedef struct scsi_qla_host { ...@@ -2232,12 +2244,16 @@ typedef struct scsi_qla_host {
#define IS_QLA2432(ha) (DT_MASK(ha) & DT_ISP2432) #define IS_QLA2432(ha) (DT_MASK(ha) & DT_ISP2432)
#define IS_QLA5422(ha) (DT_MASK(ha) & DT_ISP5422) #define IS_QLA5422(ha) (DT_MASK(ha) & DT_ISP5422)
#define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432) #define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432)
#define IS_QLA2532(ha) (DT_MASK(ha) & DT_ISP2532)
#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
IS_QLA6312(ha) || IS_QLA6322(ha)) IS_QLA6312(ha) || IS_QLA6322(ha))
#define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha)) #define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha))
#define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha)) #define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha))
#define IS_QLA25XX(ha) (IS_QLA2532(ha))
#define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA)
#define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2)
#define IS_ZIO_SUPPORTED(ha) ((ha)->device_type & DT_ZIO_SUPPORTED) #define IS_ZIO_SUPPORTED(ha) ((ha)->device_type & DT_ZIO_SUPPORTED)
#define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001) #define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001)
#define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS)
...@@ -2274,7 +2290,7 @@ typedef struct scsi_qla_host { ...@@ -2274,7 +2290,7 @@ typedef struct scsi_qla_host {
uint16_t rsp_ring_index; /* Current index. */ uint16_t rsp_ring_index; /* Current index. */
uint16_t response_q_length; uint16_t response_q_length;
struct isp_operations isp_ops; struct isp_operations *isp_ops;
/* Outstandings ISP commands. */ /* Outstandings ISP commands. */
srb_t *outstanding_cmds[MAX_OUTSTANDING_COMMANDS]; srb_t *outstanding_cmds[MAX_OUTSTANDING_COMMANDS];
...@@ -2298,6 +2314,7 @@ typedef struct scsi_qla_host { ...@@ -2298,6 +2314,7 @@ typedef struct scsi_qla_host {
#define PORT_SPEED_1GB 0x00 #define PORT_SPEED_1GB 0x00
#define PORT_SPEED_2GB 0x01 #define PORT_SPEED_2GB 0x01
#define PORT_SPEED_4GB 0x03 #define PORT_SPEED_4GB 0x03
#define PORT_SPEED_8GB 0x04
uint16_t link_data_rate; /* F/W operating speed */ uint16_t link_data_rate; /* F/W operating speed */
uint8_t current_topology; uint8_t current_topology;
...@@ -2564,6 +2581,7 @@ typedef struct scsi_qla_host { ...@@ -2564,6 +2581,7 @@ typedef struct scsi_qla_host {
#define OPTROM_SIZE_2300 0x20000 #define OPTROM_SIZE_2300 0x20000
#define OPTROM_SIZE_2322 0x100000 #define OPTROM_SIZE_2322 0x100000
#define OPTROM_SIZE_24XX 0x100000 #define OPTROM_SIZE_24XX 0x100000
#define OPTROM_SIZE_25XX 0x200000
#include "qla_gbl.h" #include "qla_gbl.h"
#include "qla_dbg.h" #include "qla_dbg.h"
......
...@@ -8,14 +8,17 @@ ...@@ -8,14 +8,17 @@
#define __QLA_FW_H #define __QLA_FW_H
#define MBS_CHECKSUM_ERROR 0x4010 #define MBS_CHECKSUM_ERROR 0x4010
#define MBS_INVALID_PRODUCT_KEY 0x4020
/* /*
* Firmware Options. * Firmware Options.
*/ */
#define FO1_ENABLE_PUREX BIT_10 #define FO1_ENABLE_PUREX BIT_10
#define FO1_DISABLE_LED_CTRL BIT_6 #define FO1_DISABLE_LED_CTRL BIT_6
#define FO1_ENABLE_8016 BIT_0
#define FO2_ENABLE_SEL_CLASS2 BIT_5 #define FO2_ENABLE_SEL_CLASS2 BIT_5
#define FO3_NO_ABTS_ON_LINKDOWN BIT_14 #define FO3_NO_ABTS_ON_LINKDOWN BIT_14
#define FO3_HOLD_STS_IOCB BIT_12
/* /*
* Port Database structure definition for ISP 24xx. * Port Database structure definition for ISP 24xx.
...@@ -341,7 +344,9 @@ struct init_cb_24xx { ...@@ -341,7 +344,9 @@ struct init_cb_24xx {
* BIT 10 = Reserved * BIT 10 = Reserved
* BIT 11 = Enable FC-SP Security * BIT 11 = Enable FC-SP Security
* BIT 12 = FC Tape Enable * BIT 12 = FC Tape Enable
* BIT 13-31 = Reserved * BIT 13 = Reserved
* BIT 14 = Enable Target PRLI Control
* BIT 15-31 = Reserved
*/ */
uint32_t firmware_options_2; uint32_t firmware_options_2;
...@@ -363,7 +368,8 @@ struct init_cb_24xx { ...@@ -363,7 +368,8 @@ struct init_cb_24xx {
* BIT 13 = Data Rate bit 0 * BIT 13 = Data Rate bit 0
* BIT 14 = Data Rate bit 1 * BIT 14 = Data Rate bit 1
* BIT 15 = Data Rate bit 2 * BIT 15 = Data Rate bit 2
* BIT 16-31 = Reserved * BIT 16 = Enable 75 ohm Termination Select
* BIT 17-31 = Reserved
*/ */
uint32_t firmware_options_3; uint32_t firmware_options_3;
...@@ -435,6 +441,7 @@ struct cmd_type_7 { ...@@ -435,6 +441,7 @@ struct cmd_type_7 {
#define TMF_LUN_RESET BIT_12 #define TMF_LUN_RESET BIT_12
#define TMF_CLEAR_TASK_SET BIT_10 #define TMF_CLEAR_TASK_SET BIT_10
#define TMF_ABORT_TASK_SET BIT_9 #define TMF_ABORT_TASK_SET BIT_9
#define TMF_DSD_LIST_ENABLE BIT_2
#define TMF_READ_DATA BIT_1 #define TMF_READ_DATA BIT_1
#define TMF_WRITE_DATA BIT_0 #define TMF_WRITE_DATA BIT_0
...@@ -589,7 +596,7 @@ struct els_entry_24xx { ...@@ -589,7 +596,7 @@ struct els_entry_24xx {
#define EST_SOFI3 (1 << 4) #define EST_SOFI3 (1 << 4)
#define EST_SOFI2 (3 << 4) #define EST_SOFI2 (3 << 4)
uint32_t rx_xchg_address[2]; /* Receive exchange address. */ uint32_t rx_xchg_address; /* Receive exchange address. */
uint16_t rx_dsd_count; uint16_t rx_dsd_count;
uint8_t opcode; uint8_t opcode;
...@@ -650,6 +657,7 @@ struct logio_entry_24xx { ...@@ -650,6 +657,7 @@ struct logio_entry_24xx {
uint16_t control_flags; /* Control flags. */ uint16_t control_flags; /* Control flags. */
/* Modifiers. */ /* Modifiers. */
#define LCF_INCLUDE_SNS BIT_10 /* Include SNS (FFFFFC) during LOGO. */
#define LCF_FCP2_OVERRIDE BIT_9 /* Set/Reset word 3 of PRLI. */ #define LCF_FCP2_OVERRIDE BIT_9 /* Set/Reset word 3 of PRLI. */
#define LCF_CLASS_2 BIT_8 /* Enable class 2 during PLOGI. */ #define LCF_CLASS_2 BIT_8 /* Enable class 2 during PLOGI. */
#define LCF_FREE_NPORT BIT_7 /* Release NPORT handle after LOGO. */ #define LCF_FREE_NPORT BIT_7 /* Release NPORT handle after LOGO. */
...@@ -779,6 +787,15 @@ struct device_reg_24xx { ...@@ -779,6 +787,15 @@ struct device_reg_24xx {
#define FA_RISC_CODE_ADDR 0x20000 #define FA_RISC_CODE_ADDR 0x20000
#define FA_RISC_CODE_SEGMENTS 2 #define FA_RISC_CODE_SEGMENTS 2
#define FA_FW_AREA_ADDR 0x40000
#define FA_VPD_NVRAM_ADDR 0x48000
#define FA_FEATURE_ADDR 0x4C000
#define FA_FLASH_DESCR_ADDR 0x50000
#define FA_HW_EVENT_ADDR 0x54000
#define FA_BOOT_LOG_ADDR 0x58000
#define FA_FW_DUMP0_ADDR 0x60000
#define FA_FW_DUMP1_ADDR 0x70000
uint32_t flash_data; /* Flash/NVRAM BIOS data. */ uint32_t flash_data; /* Flash/NVRAM BIOS data. */
uint32_t ctrl_status; /* Control/Status. */ uint32_t ctrl_status; /* Control/Status. */
...@@ -859,10 +876,13 @@ struct device_reg_24xx { ...@@ -859,10 +876,13 @@ struct device_reg_24xx {
#define HCCRX_CLR_RISC_INT 0xA0000000 #define HCCRX_CLR_RISC_INT 0xA0000000
uint32_t gpiod; /* GPIO Data register. */ uint32_t gpiod; /* GPIO Data register. */
/* LED update mask. */ /* LED update mask. */
#define GPDX_LED_UPDATE_MASK (BIT_20|BIT_19|BIT_18) #define GPDX_LED_UPDATE_MASK (BIT_20|BIT_19|BIT_18)
/* Data update mask. */ /* Data update mask. */
#define GPDX_DATA_UPDATE_MASK (BIT_17|BIT_16) #define GPDX_DATA_UPDATE_MASK (BIT_17|BIT_16)
/* Data update mask. */
#define GPDX_DATA_UPDATE_2_MASK (BIT_28|BIT_27|BIT_26|BIT_17|BIT_16)
/* LED control mask. */ /* LED control mask. */
#define GPDX_LED_COLOR_MASK (BIT_4|BIT_3|BIT_2) #define GPDX_LED_COLOR_MASK (BIT_4|BIT_3|BIT_2)
/* LED bit values. Color names as /* LED bit values. Color names as
...@@ -877,6 +897,8 @@ struct device_reg_24xx { ...@@ -877,6 +897,8 @@ struct device_reg_24xx {
uint32_t gpioe; /* GPIO Enable register. */ uint32_t gpioe; /* GPIO Enable register. */
/* Enable update mask. */ /* Enable update mask. */
#define GPEX_ENABLE_UPDATE_MASK (BIT_17|BIT_16) #define GPEX_ENABLE_UPDATE_MASK (BIT_17|BIT_16)
/* Enable update mask. */
#define GPEX_ENABLE_UPDATE_2_MASK (BIT_28|BIT_27|BIT_26|BIT_17|BIT_16)
/* Enable. */ /* Enable. */
#define GPEX_ENABLE (BIT_1|BIT_0) #define GPEX_ENABLE (BIT_1|BIT_0)
...@@ -916,6 +938,14 @@ struct device_reg_24xx { ...@@ -916,6 +938,14 @@ struct device_reg_24xx {
uint16_t mailbox29; uint16_t mailbox29;
uint16_t mailbox30; uint16_t mailbox30;
uint16_t mailbox31; uint16_t mailbox31;
uint32_t iobase_window;
uint32_t unused_4[8]; /* Gap. */
uint32_t iobase_q;
uint32_t unused_5[2]; /* Gap. */
uint32_t iobase_select;
uint32_t unused_6[2]; /* Gap. */
uint32_t iobase_sdata;
}; };
/* MID Support ***************************************************************/ /* MID Support ***************************************************************/
......
...@@ -17,6 +17,7 @@ extern int qla2x00_initialize_adapter(scsi_qla_host_t *); ...@@ -17,6 +17,7 @@ extern int qla2x00_initialize_adapter(scsi_qla_host_t *);
extern int qla2100_pci_config(struct scsi_qla_host *); extern int qla2100_pci_config(struct scsi_qla_host *);
extern int qla2300_pci_config(struct scsi_qla_host *); extern int qla2300_pci_config(struct scsi_qla_host *);
extern int qla24xx_pci_config(scsi_qla_host_t *); extern int qla24xx_pci_config(scsi_qla_host_t *);
extern int qla25xx_pci_config(scsi_qla_host_t *);
extern void qla2x00_reset_chip(struct scsi_qla_host *); extern void qla2x00_reset_chip(struct scsi_qla_host *);
extern void qla24xx_reset_chip(struct scsi_qla_host *); extern void qla24xx_reset_chip(struct scsi_qla_host *);
extern int qla2x00_chip_diag(struct scsi_qla_host *); extern int qla2x00_chip_diag(struct scsi_qla_host *);
...@@ -281,6 +282,10 @@ extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, ...@@ -281,6 +282,10 @@ extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
uint32_t); uint32_t);
extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
uint32_t); uint32_t);
extern uint8_t *qla25xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
uint32_t);
extern int qla25xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
uint32_t);
extern int qla2x00_beacon_on(struct scsi_qla_host *); extern int qla2x00_beacon_on(struct scsi_qla_host *);
extern int qla2x00_beacon_off(struct scsi_qla_host *); extern int qla2x00_beacon_off(struct scsi_qla_host *);
...@@ -307,6 +312,7 @@ extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); ...@@ -307,6 +312,7 @@ extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);
extern void qla2100_fw_dump(scsi_qla_host_t *, int); extern void qla2100_fw_dump(scsi_qla_host_t *, int);
extern void qla2300_fw_dump(scsi_qla_host_t *, int); extern void qla2300_fw_dump(scsi_qla_host_t *, int);
extern void qla24xx_fw_dump(scsi_qla_host_t *, int); extern void qla24xx_fw_dump(scsi_qla_host_t *, int);
extern void qla25xx_fw_dump(scsi_qla_host_t *, int);
extern void qla2x00_dump_regs(scsi_qla_host_t *); extern void qla2x00_dump_regs(scsi_qla_host_t *);
extern void qla2x00_dump_buffer(uint8_t *, uint32_t); extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *); extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *);
......
...@@ -127,7 +127,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *ha, ms_iocb_entry_t *ms_pkt, ...@@ -127,7 +127,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *ha, ms_iocb_entry_t *ms_pkt,
DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n", DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n",
ha->host_no, routine, ms_pkt->entry_status)); ha->host_no, routine, ms_pkt->entry_status));
} else { } else {
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
comp_status = le16_to_cpu( comp_status = le16_to_cpu(
((struct ct_entry_24xx *)ms_pkt)->comp_status); ((struct ct_entry_24xx *)ms_pkt)->comp_status);
else else
...@@ -180,7 +180,8 @@ qla2x00_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport) ...@@ -180,7 +180,8 @@ qla2x00_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport)
/* Issue GA_NXT */ /* Issue GA_NXT */
/* Prepare common MS IOCB */ /* Prepare common MS IOCB */
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GA_NXT_REQ_SIZE, GA_NXT_RSP_SIZE); ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GA_NXT_REQ_SIZE,
GA_NXT_RSP_SIZE);
/* Prepare CT request */ /* Prepare CT request */
ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD, ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD,
...@@ -266,7 +267,8 @@ qla2x00_gid_pt(scsi_qla_host_t *ha, sw_info_t *list) ...@@ -266,7 +267,8 @@ qla2x00_gid_pt(scsi_qla_host_t *ha, sw_info_t *list)
/* Issue GID_PT */ /* Issue GID_PT */
/* Prepare common MS IOCB */ /* Prepare common MS IOCB */
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GID_PT_REQ_SIZE, GID_PT_RSP_SIZE); ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GID_PT_REQ_SIZE,
GID_PT_RSP_SIZE);
/* Prepare CT request */ /* Prepare CT request */
ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD, ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD,
...@@ -338,7 +340,7 @@ qla2x00_gpn_id(scsi_qla_host_t *ha, sw_info_t *list) ...@@ -338,7 +340,7 @@ qla2x00_gpn_id(scsi_qla_host_t *ha, sw_info_t *list)
for (i = 0; i < MAX_FIBRE_DEVICES; i++) { for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
/* Issue GPN_ID */ /* Issue GPN_ID */
/* Prepare common MS IOCB */ /* Prepare common MS IOCB */
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GPN_ID_REQ_SIZE, ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GPN_ID_REQ_SIZE,
GPN_ID_RSP_SIZE); GPN_ID_RSP_SIZE);
/* Prepare CT request */ /* Prepare CT request */
...@@ -399,7 +401,7 @@ qla2x00_gnn_id(scsi_qla_host_t *ha, sw_info_t *list) ...@@ -399,7 +401,7 @@ qla2x00_gnn_id(scsi_qla_host_t *ha, sw_info_t *list)
for (i = 0; i < MAX_FIBRE_DEVICES; i++) { for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
/* Issue GNN_ID */ /* Issue GNN_ID */
/* Prepare common MS IOCB */ /* Prepare common MS IOCB */
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GNN_ID_REQ_SIZE, ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GNN_ID_REQ_SIZE,
GNN_ID_RSP_SIZE); GNN_ID_RSP_SIZE);
/* Prepare CT request */ /* Prepare CT request */
...@@ -473,7 +475,8 @@ qla2x00_rft_id(scsi_qla_host_t *ha) ...@@ -473,7 +475,8 @@ qla2x00_rft_id(scsi_qla_host_t *ha)
/* Issue RFT_ID */ /* Issue RFT_ID */
/* Prepare common MS IOCB */ /* Prepare common MS IOCB */
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RFT_ID_REQ_SIZE, RFT_ID_RSP_SIZE); ms_pkt = ha->isp_ops->prep_ms_iocb(ha, RFT_ID_REQ_SIZE,
RFT_ID_RSP_SIZE);
/* Prepare CT request */ /* Prepare CT request */
ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD, ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD,
...@@ -528,7 +531,8 @@ qla2x00_rff_id(scsi_qla_host_t *ha) ...@@ -528,7 +531,8 @@ qla2x00_rff_id(scsi_qla_host_t *ha)
/* Issue RFF_ID */ /* Issue RFF_ID */
/* Prepare common MS IOCB */ /* Prepare common MS IOCB */
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RFF_ID_REQ_SIZE, RFF_ID_RSP_SIZE); ms_pkt = ha->isp_ops->prep_ms_iocb(ha, RFF_ID_REQ_SIZE,
RFF_ID_RSP_SIZE);
/* Prepare CT request */ /* Prepare CT request */
ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD, ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD,
...@@ -582,7 +586,8 @@ qla2x00_rnn_id(scsi_qla_host_t *ha) ...@@ -582,7 +586,8 @@ qla2x00_rnn_id(scsi_qla_host_t *ha)
/* Issue RNN_ID */ /* Issue RNN_ID */
/* Prepare common MS IOCB */ /* Prepare common MS IOCB */
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RNN_ID_REQ_SIZE, RNN_ID_RSP_SIZE); ms_pkt = ha->isp_ops->prep_ms_iocb(ha, RNN_ID_REQ_SIZE,
RNN_ID_RSP_SIZE);
/* Prepare CT request */ /* Prepare CT request */
ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD, ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD,
...@@ -645,7 +650,7 @@ qla2x00_rsnn_nn(scsi_qla_host_t *ha) ...@@ -645,7 +650,7 @@ qla2x00_rsnn_nn(scsi_qla_host_t *ha)
/* Issue RSNN_NN */ /* Issue RSNN_NN */
/* Prepare common MS IOCB */ /* Prepare common MS IOCB */
/* Request size adjusted after CT preparation */ /* Request size adjusted after CT preparation */
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE); ms_pkt = ha->isp_ops->prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE);
/* Prepare CT request */ /* Prepare CT request */
ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD, ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD,
...@@ -1102,7 +1107,7 @@ qla2x00_mgmt_svr_login(scsi_qla_host_t *ha) ...@@ -1102,7 +1107,7 @@ qla2x00_mgmt_svr_login(scsi_qla_host_t *ha)
if (ha->flags.management_server_logged_in) if (ha->flags.management_server_logged_in)
return ret; return ret;
ha->isp_ops.fabric_login(ha, ha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa, ha->isp_ops->fabric_login(ha, ha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa,
mb, BIT_1); mb, BIT_1);
if (mb[0] != MBS_COMMAND_COMPLETE) { if (mb[0] != MBS_COMMAND_COMPLETE) {
DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: " DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: "
...@@ -1198,7 +1203,7 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size) ...@@ -1198,7 +1203,7 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size)
ms_iocb_entry_t *ms_pkt = ha->ms_iocb; ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb; struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
ct_pkt->cmd_byte_count = cpu_to_le32(req_size); ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
} else { } else {
...@@ -1253,7 +1258,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *ha) ...@@ -1253,7 +1258,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *ha)
/* Issue RHBA */ /* Issue RHBA */
/* Prepare common MS IOCB */ /* Prepare common MS IOCB */
/* Request size adjusted after CT preparation */ /* Request size adjusted after CT preparation */
ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RHBA_RSP_SIZE); ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(ha, 0, RHBA_RSP_SIZE);
/* Prepare CT request */ /* Prepare CT request */
ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD, ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD,
...@@ -1373,7 +1378,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *ha) ...@@ -1373,7 +1378,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *ha)
/* Firmware version */ /* Firmware version */
eiter = (struct ct_fdmi_hba_attr *) (entries + size); eiter = (struct ct_fdmi_hba_attr *) (entries + size);
eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
ha->isp_ops.fw_version_str(ha, eiter->a.fw_version); ha->isp_ops->fw_version_str(ha, eiter->a.fw_version);
alen = strlen(eiter->a.fw_version); alen = strlen(eiter->a.fw_version);
alen += (alen & 3) ? (4 - (alen & 3)) : 4; alen += (alen & 3) ? (4 - (alen & 3)) : 4;
eiter->len = cpu_to_be16(4 + alen); eiter->len = cpu_to_be16(4 + alen);
...@@ -1439,7 +1444,7 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *ha) ...@@ -1439,7 +1444,7 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *ha)
/* Issue RPA */ /* Issue RPA */
/* Prepare common MS IOCB */ /* Prepare common MS IOCB */
ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, DHBA_REQ_SIZE, ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(ha, DHBA_REQ_SIZE,
DHBA_RSP_SIZE); DHBA_RSP_SIZE);
/* Prepare CT request */ /* Prepare CT request */
...@@ -1497,7 +1502,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) ...@@ -1497,7 +1502,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
/* Issue RPA */ /* Issue RPA */
/* Prepare common MS IOCB */ /* Prepare common MS IOCB */
/* Request size adjusted after CT preparation */ /* Request size adjusted after CT preparation */
ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RPA_RSP_SIZE); ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(ha, 0, RPA_RSP_SIZE);
/* Prepare CT request */ /* Prepare CT request */
ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD, ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD,
...@@ -1527,12 +1532,20 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) ...@@ -1527,12 +1532,20 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter = (struct ct_fdmi_port_attr *) (entries + size);
eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
eiter->len = __constant_cpu_to_be16(4 + 4); eiter->len = __constant_cpu_to_be16(4 + 4);
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_QLA25XX(ha))
eiter->a.sup_speed = __constant_cpu_to_be32(4); eiter->a.sup_speed = __constant_cpu_to_be32(
FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
else if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
eiter->a.sup_speed = __constant_cpu_to_be32(
FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
FDMI_PORT_SPEED_4GB);
else if (IS_QLA23XX(ha)) else if (IS_QLA23XX(ha))
eiter->a.sup_speed = __constant_cpu_to_be32(2); eiter->a.sup_speed =__constant_cpu_to_be32(
FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB);
else else
eiter->a.sup_speed = __constant_cpu_to_be32(1); eiter->a.sup_speed = __constant_cpu_to_be32(
FDMI_PORT_SPEED_1GB);
size += 4 + 4; size += 4 + 4;
DEBUG13(printk("%s(%ld): SUPPORTED_SPEED=%x.\n", __func__, ha->host_no, DEBUG13(printk("%s(%ld): SUPPORTED_SPEED=%x.\n", __func__, ha->host_no,
...@@ -1543,14 +1556,25 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) ...@@ -1543,14 +1556,25 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED); eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
eiter->len = __constant_cpu_to_be16(4 + 4); eiter->len = __constant_cpu_to_be16(4 + 4);
switch (ha->link_data_rate) { switch (ha->link_data_rate) {
case 0: case PORT_SPEED_1GB:
eiter->a.cur_speed = __constant_cpu_to_be32(1); eiter->a.cur_speed =
__constant_cpu_to_be32(FDMI_PORT_SPEED_1GB);
break;
case PORT_SPEED_2GB:
eiter->a.cur_speed =
__constant_cpu_to_be32(FDMI_PORT_SPEED_2GB);
break;
case PORT_SPEED_4GB:
eiter->a.cur_speed =
__constant_cpu_to_be32(FDMI_PORT_SPEED_4GB);
break; break;
case 1: case PORT_SPEED_8GB:
eiter->a.cur_speed = __constant_cpu_to_be32(2); eiter->a.cur_speed =
__constant_cpu_to_be32(FDMI_PORT_SPEED_8GB);
break; break;
case 3: default:
eiter->a.cur_speed = __constant_cpu_to_be32(4); eiter->a.cur_speed =
__constant_cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
break; break;
} }
size += 4 + 4; size += 4 + 4;
...@@ -1562,7 +1586,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) ...@@ -1562,7 +1586,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter = (struct ct_fdmi_port_attr *) (entries + size);
eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
eiter->len = __constant_cpu_to_be16(4 + 4); eiter->len = __constant_cpu_to_be16(4 + 4);
max_frame_size = IS_QLA24XX(ha) || IS_QLA54XX(ha) ? max_frame_size = IS_FWI2_CAPABLE(ha) ?
(uint32_t) icb24->frame_payload_size: (uint32_t) icb24->frame_payload_size:
(uint32_t) ha->init_cb->frame_payload_size; (uint32_t) ha->init_cb->frame_payload_size;
eiter->a.max_frame_size = cpu_to_be32(max_frame_size); eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
...@@ -1678,7 +1702,7 @@ qla2x00_gfpn_id(scsi_qla_host_t *ha, sw_info_t *list) ...@@ -1678,7 +1702,7 @@ qla2x00_gfpn_id(scsi_qla_host_t *ha, sw_info_t *list)
struct ct_sns_req *ct_req; struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp; struct ct_sns_rsp *ct_rsp;
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) if (!IS_IIDMA_CAPABLE(ha))
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
for (i = 0; i < MAX_FIBRE_DEVICES; i++) { for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
...@@ -1686,7 +1710,7 @@ qla2x00_gfpn_id(scsi_qla_host_t *ha, sw_info_t *list) ...@@ -1686,7 +1710,7 @@ qla2x00_gfpn_id(scsi_qla_host_t *ha, sw_info_t *list)
memset(list[i].fabric_port_name, 0, WWN_SIZE); memset(list[i].fabric_port_name, 0, WWN_SIZE);
/* Prepare common MS IOCB */ /* Prepare common MS IOCB */
ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GFPN_ID_REQ_SIZE, ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GFPN_ID_REQ_SIZE,
GFPN_ID_RSP_SIZE); GFPN_ID_RSP_SIZE);
/* Prepare CT request */ /* Prepare CT request */
...@@ -1786,7 +1810,7 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list) ...@@ -1786,7 +1810,7 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list)
struct ct_sns_req *ct_req; struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp; struct ct_sns_rsp *ct_rsp;
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) if (!IS_IIDMA_CAPABLE(ha))
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
if (!ha->flags.gpsc_supported) if (!ha->flags.gpsc_supported)
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
......
...@@ -79,20 +79,20 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ...@@ -79,20 +79,20 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); qla_printk(KERN_INFO, ha, "Configuring PCI space...\n");
rval = ha->isp_ops.pci_config(ha); rval = ha->isp_ops->pci_config(ha);
if (rval) { if (rval) {
DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n", DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n",
ha->host_no)); ha->host_no));
return (rval); return (rval);
} }
ha->isp_ops.reset_chip(ha); ha->isp_ops->reset_chip(ha);
ha->isp_ops.get_flash_version(ha, ha->request_ring); ha->isp_ops->get_flash_version(ha, ha->request_ring);
qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n");
ha->isp_ops.nvram_config(ha); ha->isp_ops->nvram_config(ha);
if (ha->flags.disable_serdes) { if (ha->flags.disable_serdes) {
/* Mask HBA via NVRAM settings? */ /* Mask HBA via NVRAM settings? */
...@@ -108,7 +108,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ...@@ -108,7 +108,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n");
if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) {
rval = ha->isp_ops.chip_diag(ha); rval = ha->isp_ops->chip_diag(ha);
if (rval) if (rval)
return (rval); return (rval);
rval = qla2x00_setup_chip(ha); rval = qla2x00_setup_chip(ha);
...@@ -129,14 +129,13 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ...@@ -129,14 +129,13 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
int int
qla2100_pci_config(scsi_qla_host_t *ha) qla2100_pci_config(scsi_qla_host_t *ha)
{ {
int ret;
uint16_t w; uint16_t w;
uint32_t d; uint32_t d;
unsigned long flags; unsigned long flags;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
pci_set_master(ha->pdev); pci_set_master(ha->pdev);
ret = pci_set_mwi(ha->pdev); pci_try_set_mwi(ha->pdev);
pci_read_config_word(ha->pdev, PCI_COMMAND, &w); pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
...@@ -164,7 +163,6 @@ qla2100_pci_config(scsi_qla_host_t *ha) ...@@ -164,7 +163,6 @@ qla2100_pci_config(scsi_qla_host_t *ha)
int int
qla2300_pci_config(scsi_qla_host_t *ha) qla2300_pci_config(scsi_qla_host_t *ha)
{ {
int ret;
uint16_t w; uint16_t w;
uint32_t d; uint32_t d;
unsigned long flags = 0; unsigned long flags = 0;
...@@ -172,7 +170,7 @@ qla2300_pci_config(scsi_qla_host_t *ha) ...@@ -172,7 +170,7 @@ qla2300_pci_config(scsi_qla_host_t *ha)
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
pci_set_master(ha->pdev); pci_set_master(ha->pdev);
ret = pci_set_mwi(ha->pdev); pci_try_set_mwi(ha->pdev);
pci_read_config_word(ha->pdev, PCI_COMMAND, &w); pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
...@@ -250,15 +248,13 @@ qla2300_pci_config(scsi_qla_host_t *ha) ...@@ -250,15 +248,13 @@ qla2300_pci_config(scsi_qla_host_t *ha)
int int
qla24xx_pci_config(scsi_qla_host_t *ha) qla24xx_pci_config(scsi_qla_host_t *ha)
{ {
int ret;
uint16_t w; uint16_t w;
uint32_t d; uint32_t d;
unsigned long flags = 0; unsigned long flags = 0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
int pcix_cmd_reg, pcie_dctl_reg;
pci_set_master(ha->pdev); pci_set_master(ha->pdev);
ret = pci_set_mwi(ha->pdev); pci_try_set_mwi(ha->pdev);
pci_read_config_word(ha->pdev, PCI_COMMAND, &w); pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
...@@ -268,28 +264,12 @@ qla24xx_pci_config(scsi_qla_host_t *ha) ...@@ -268,28 +264,12 @@ qla24xx_pci_config(scsi_qla_host_t *ha)
pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
/* PCI-X -- adjust Maximum Memory Read Byte Count (2048). */ /* PCI-X -- adjust Maximum Memory Read Byte Count (2048). */
pcix_cmd_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_PCIX); if (pci_find_capability(ha->pdev, PCI_CAP_ID_PCIX))
if (pcix_cmd_reg) { pcix_set_mmrbc(ha->pdev, 2048);
uint16_t pcix_cmd;
pcix_cmd_reg += PCI_X_CMD;
pci_read_config_word(ha->pdev, pcix_cmd_reg, &pcix_cmd);
pcix_cmd &= ~PCI_X_CMD_MAX_READ;
pcix_cmd |= 0x0008;
pci_write_config_word(ha->pdev, pcix_cmd_reg, pcix_cmd);
}
/* PCIe -- adjust Maximum Read Request Size (2048). */ /* PCIe -- adjust Maximum Read Request Size (2048). */
pcie_dctl_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP); if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP))
if (pcie_dctl_reg) { pcie_set_readrq(ha->pdev, 2048);
uint16_t pcie_dctl;
pcie_dctl_reg += PCI_EXP_DEVCTL;
pci_read_config_word(ha->pdev, pcie_dctl_reg, &pcie_dctl);
pcie_dctl &= ~PCI_EXP_DEVCTL_READRQ;
pcie_dctl |= 0x4000;
pci_write_config_word(ha->pdev, pcie_dctl_reg, pcie_dctl);
}
/* Reset expansion ROM address decode enable */ /* Reset expansion ROM address decode enable */
pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
...@@ -306,6 +286,40 @@ qla24xx_pci_config(scsi_qla_host_t *ha) ...@@ -306,6 +286,40 @@ qla24xx_pci_config(scsi_qla_host_t *ha)
return QLA_SUCCESS; return QLA_SUCCESS;
} }
/**
* qla25xx_pci_config() - Setup ISP25xx PCI configuration registers.
* @ha: HA context
*
* Returns 0 on success.
*/
int
qla25xx_pci_config(scsi_qla_host_t *ha)
{
uint16_t w;
uint32_t d;
pci_set_master(ha->pdev);
pci_try_set_mwi(ha->pdev);
pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
w &= ~PCI_COMMAND_INTX_DISABLE;
pci_write_config_word(ha->pdev, PCI_COMMAND, w);
/* PCIe -- adjust Maximum Read Request Size (2048). */
if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP))
pcie_set_readrq(ha->pdev, 2048);
/* Reset expansion ROM address decode enable */
pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
d &= ~PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
ha->chip_revision = ha->pdev->revision;
return QLA_SUCCESS;
}
/** /**
* qla2x00_isp_firmware() - Choose firmware image. * qla2x00_isp_firmware() - Choose firmware image.
* @ha: HA context * @ha: HA context
...@@ -351,7 +365,7 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) ...@@ -351,7 +365,7 @@ qla2x00_reset_chip(scsi_qla_host_t *ha)
uint32_t cnt; uint32_t cnt;
uint16_t cmd; uint16_t cmd;
ha->isp_ops.disable_intrs(ha); ha->isp_ops->disable_intrs(ha);
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
...@@ -551,7 +565,7 @@ qla24xx_reset_risc(scsi_qla_host_t *ha) ...@@ -551,7 +565,7 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
void void
qla24xx_reset_chip(scsi_qla_host_t *ha) qla24xx_reset_chip(scsi_qla_host_t *ha)
{ {
ha->isp_ops.disable_intrs(ha); ha->isp_ops->disable_intrs(ha);
/* Perform RISC reset. */ /* Perform RISC reset. */
qla24xx_reset_risc(ha); qla24xx_reset_risc(ha);
...@@ -736,8 +750,10 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) ...@@ -736,8 +750,10 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
fixed_size = offsetof(struct qla2300_fw_dump, data_ram); fixed_size = offsetof(struct qla2300_fw_dump, data_ram);
mem_size = (ha->fw_memory_size - 0x11000 + 1) * mem_size = (ha->fw_memory_size - 0x11000 + 1) *
sizeof(uint16_t); sizeof(uint16_t);
} else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { } else if (IS_FWI2_CAPABLE(ha)) {
fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem); fixed_size = IS_QLA25XX(ha) ?
offsetof(struct qla25xx_fw_dump, ext_mem):
offsetof(struct qla24xx_fw_dump, ext_mem);
mem_size = (ha->fw_memory_size - 0x100000 + 1) * mem_size = (ha->fw_memory_size - 0x100000 + 1) *
sizeof(uint32_t); sizeof(uint32_t);
...@@ -879,7 +895,7 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) ...@@ -879,7 +895,7 @@ qla2x00_setup_chip(scsi_qla_host_t *ha)
uint32_t srisc_address = 0; uint32_t srisc_address = 0;
/* Load firmware sequences */ /* Load firmware sequences */
rval = ha->isp_ops.load_risc(ha, &srisc_address); rval = ha->isp_ops->load_risc(ha, &srisc_address);
if (rval == QLA_SUCCESS) { if (rval == QLA_SUCCESS) {
DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC " DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC "
"code.\n", ha->host_no)); "code.\n", ha->host_no));
...@@ -1130,12 +1146,12 @@ qla2x00_init_rings(scsi_qla_host_t *ha) ...@@ -1130,12 +1146,12 @@ qla2x00_init_rings(scsi_qla_host_t *ha)
/* Initialize response queue entries */ /* Initialize response queue entries */
qla2x00_init_response_q_entries(ha); qla2x00_init_response_q_entries(ha);
ha->isp_ops.config_rings(ha); ha->isp_ops->config_rings(ha);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Update any ISP specific firmware options before initialization. */ /* Update any ISP specific firmware options before initialization. */
ha->isp_ops.update_fw_options(ha); ha->isp_ops->update_fw_options(ha);
DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no));
...@@ -1459,7 +1475,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) ...@@ -1459,7 +1475,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
ha->nvram_base = 0x80; ha->nvram_base = 0x80;
/* Get NVRAM data and calculate checksum. */ /* Get NVRAM data and calculate checksum. */
ha->isp_ops.read_nvram(ha, ptr, ha->nvram_base, ha->nvram_size); ha->isp_ops->read_nvram(ha, ptr, ha->nvram_base, ha->nvram_size);
for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++) for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++)
chksum += *ptr++; chksum += *ptr++;
...@@ -2119,7 +2135,7 @@ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) ...@@ -2119,7 +2135,7 @@ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
int rval; int rval;
uint16_t port_speed, mb[6]; uint16_t port_speed, mb[6];
if (!IS_QLA24XX(ha)) if (!IS_IIDMA_CAPABLE(ha))
return; return;
switch (be16_to_cpu(fcport->fp_speed)) { switch (be16_to_cpu(fcport->fp_speed)) {
...@@ -2267,7 +2283,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) ...@@ -2267,7 +2283,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
scsi_qla_host_t *pha = to_qla_parent(ha); scsi_qla_host_t *pha = to_qla_parent(ha);
/* If FL port exists, then SNS is present */ /* If FL port exists, then SNS is present */
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
loop_id = NPH_F_PORT; loop_id = NPH_F_PORT;
else else
loop_id = SNS_FL_PORT; loop_id = SNS_FL_PORT;
...@@ -2294,11 +2310,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) ...@@ -2294,11 +2310,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
qla2x00_fdmi_register(ha); qla2x00_fdmi_register(ha);
/* Ensure we are logged into the SNS. */ /* Ensure we are logged into the SNS. */
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
loop_id = NPH_SNS; loop_id = NPH_SNS;
else else
loop_id = SIMPLE_NAME_SERVER; loop_id = SIMPLE_NAME_SERVER;
ha->isp_ops.fabric_login(ha, loop_id, 0xff, 0xff, ha->isp_ops->fabric_login(ha, loop_id, 0xff, 0xff,
0xfc, mb, BIT_1 | BIT_0); 0xfc, mb, BIT_1 | BIT_0);
if (mb[0] != MBS_COMMAND_COMPLETE) { if (mb[0] != MBS_COMMAND_COMPLETE) {
DEBUG2(qla_printk(KERN_INFO, ha, DEBUG2(qla_printk(KERN_INFO, ha,
...@@ -2355,7 +2371,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) ...@@ -2355,7 +2371,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
(fcport->flags & FCF_TAPE_PRESENT) == 0 && (fcport->flags & FCF_TAPE_PRESENT) == 0 &&
fcport->port_type != FCT_INITIATOR && fcport->port_type != FCT_INITIATOR &&
fcport->port_type != FCT_BROADCAST) { fcport->port_type != FCT_BROADCAST) {
ha->isp_ops.fabric_logout(ha, ha->isp_ops->fabric_logout(ha,
fcport->loop_id, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.area,
...@@ -2664,7 +2680,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) ...@@ -2664,7 +2680,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
(fcport->flags & FCF_TAPE_PRESENT) == 0 && (fcport->flags & FCF_TAPE_PRESENT) == 0 &&
fcport->port_type != FCT_INITIATOR && fcport->port_type != FCT_INITIATOR &&
fcport->port_type != FCT_BROADCAST) { fcport->port_type != FCT_BROADCAST) {
ha->isp_ops.fabric_logout(ha, fcport->loop_id, ha->isp_ops->fabric_logout(ha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa); fcport->d_id.b.al_pa);
fcport->loop_id = FC_NO_LOOP_ID; fcport->loop_id = FC_NO_LOOP_ID;
...@@ -2919,7 +2935,7 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *ha, fc_port_t *fcport, ...@@ -2919,7 +2935,7 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *ha, fc_port_t *fcport,
opts |= BIT_1; opts |= BIT_1;
rval = qla2x00_get_port_database(ha, fcport, opts); rval = qla2x00_get_port_database(ha, fcport, opts);
if (rval != QLA_SUCCESS) { if (rval != QLA_SUCCESS) {
ha->isp_ops.fabric_logout(ha, fcport->loop_id, ha->isp_ops->fabric_logout(ha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa); fcport->d_id.b.al_pa);
qla2x00_mark_device_lost(ha, fcport, 1, 0); qla2x00_mark_device_lost(ha, fcport, 1, 0);
...@@ -2964,7 +2980,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, ...@@ -2964,7 +2980,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport,
fcport->d_id.b.area, fcport->d_id.b.al_pa)); fcport->d_id.b.area, fcport->d_id.b.al_pa));
/* Login fcport on switch. */ /* Login fcport on switch. */
ha->isp_ops.fabric_login(ha, fcport->loop_id, ha->isp_ops->fabric_login(ha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa, mb, BIT_0); fcport->d_id.b.al_pa, mb, BIT_0);
if (mb[0] == MBS_PORT_ID_USED) { if (mb[0] == MBS_PORT_ID_USED) {
...@@ -3032,7 +3048,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, ...@@ -3032,7 +3048,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport,
* dead. * dead.
*/ */
*next_loopid = fcport->loop_id; *next_loopid = fcport->loop_id;
ha->isp_ops.fabric_logout(ha, fcport->loop_id, ha->isp_ops->fabric_logout(ha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa); fcport->d_id.b.al_pa);
qla2x00_mark_device_lost(ha, fcport, 1, 0); qla2x00_mark_device_lost(ha, fcport, 1, 0);
...@@ -3050,7 +3066,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, ...@@ -3050,7 +3066,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport,
fcport->d_id.b.al_pa, fcport->loop_id, jiffies)); fcport->d_id.b.al_pa, fcport->loop_id, jiffies));
*next_loopid = fcport->loop_id; *next_loopid = fcport->loop_id;
ha->isp_ops.fabric_logout(ha, fcport->loop_id, ha->isp_ops->fabric_logout(ha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa); fcport->d_id.b.al_pa);
fcport->loop_id = FC_NO_LOOP_ID; fcport->loop_id = FC_NO_LOOP_ID;
...@@ -3206,7 +3222,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) ...@@ -3206,7 +3222,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
qla_printk(KERN_INFO, ha, qla_printk(KERN_INFO, ha,
"Performing ISP error recovery - ha= %p.\n", ha); "Performing ISP error recovery - ha= %p.\n", ha);
ha->isp_ops.reset_chip(ha); ha->isp_ops->reset_chip(ha);
atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
if (atomic_read(&ha->loop_state) != LOOP_DOWN) { if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
...@@ -3232,9 +3248,9 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) ...@@ -3232,9 +3248,9 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
} }
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
ha->isp_ops.get_flash_version(ha, ha->request_ring); ha->isp_ops->get_flash_version(ha, ha->request_ring);
ha->isp_ops.nvram_config(ha); ha->isp_ops->nvram_config(ha);
if (!qla2x00_restart_isp(ha)) { if (!qla2x00_restart_isp(ha)) {
clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
...@@ -3249,7 +3265,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) ...@@ -3249,7 +3265,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
ha->flags.online = 1; ha->flags.online = 1;
ha->isp_ops.enable_intrs(ha); ha->isp_ops->enable_intrs(ha);
ha->isp_abort_cnt = 0; ha->isp_abort_cnt = 0;
clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
...@@ -3274,7 +3290,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) ...@@ -3274,7 +3290,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
* The next call disables the board * The next call disables the board
* completely. * completely.
*/ */
ha->isp_ops.reset_adapter(ha); ha->isp_ops->reset_adapter(ha);
ha->flags.online = 0; ha->flags.online = 0;
clear_bit(ISP_ABORT_RETRY, clear_bit(ISP_ABORT_RETRY,
&ha->dpc_flags); &ha->dpc_flags);
...@@ -3331,7 +3347,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) ...@@ -3331,7 +3347,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
/* If firmware needs to be loaded */ /* If firmware needs to be loaded */
if (qla2x00_isp_firmware(ha)) { if (qla2x00_isp_firmware(ha)) {
ha->flags.online = 0; ha->flags.online = 0;
if (!(status = ha->isp_ops.chip_diag(ha))) { if (!(status = ha->isp_ops->chip_diag(ha))) {
if (IS_QLA2100(ha) || IS_QLA2200(ha)) { if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
status = qla2x00_setup_chip(ha); status = qla2x00_setup_chip(ha);
goto done; goto done;
...@@ -3423,7 +3439,7 @@ qla2x00_reset_adapter(scsi_qla_host_t *ha) ...@@ -3423,7 +3439,7 @@ qla2x00_reset_adapter(scsi_qla_host_t *ha)
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
ha->flags.online = 0; ha->flags.online = 0;
ha->isp_ops.disable_intrs(ha); ha->isp_ops->disable_intrs(ha);
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC); WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
...@@ -3440,7 +3456,7 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha) ...@@ -3440,7 +3456,7 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha)
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
ha->flags.online = 0; ha->flags.online = 0;
ha->isp_ops.disable_intrs(ha); ha->isp_ops->disable_intrs(ha);
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET); WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
...@@ -3498,7 +3514,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ...@@ -3498,7 +3514,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
/* Get NVRAM data and calculate checksum. */ /* Get NVRAM data and calculate checksum. */
dptr = (uint32_t *)nv; dptr = (uint32_t *)nv;
ha->isp_ops.read_nvram(ha, (uint8_t *)dptr, ha->nvram_base, ha->isp_ops->read_nvram(ha, (uint8_t *)dptr, ha->nvram_base,
ha->nvram_size); ha->nvram_size);
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++) for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)
chksum += le32_to_cpu(*dptr++); chksum += le32_to_cpu(*dptr++);
...@@ -4012,7 +4028,7 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha) ...@@ -4012,7 +4028,7 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha)
{ {
int ret, retries; int ret, retries;
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) if (!IS_FWI2_CAPABLE(ha))
return; return;
if (!ha->fw_major_version) if (!ha->fw_major_version)
return; return;
......
...@@ -104,7 +104,7 @@ static __inline__ void qla2x00_poll(scsi_qla_host_t *); ...@@ -104,7 +104,7 @@ static __inline__ void qla2x00_poll(scsi_qla_host_t *);
static inline void static inline void
qla2x00_poll(scsi_qla_host_t *ha) qla2x00_poll(scsi_qla_host_t *ha)
{ {
ha->isp_ops.intr_handler(0, ha); ha->isp_ops->intr_handler(0, ha);
} }
static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *); static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *);
...@@ -163,7 +163,7 @@ static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t); ...@@ -163,7 +163,7 @@ static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t);
static inline int static inline int
qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id) qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id)
{ {
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
return (loop_id > NPH_LAST_HANDLE); return (loop_id > NPH_LAST_HANDLE);
return ((loop_id > ha->last_loop_id && loop_id < SNS_FIRST_LOOP_ID) || return ((loop_id > ha->last_loop_id && loop_id < SNS_FIRST_LOOP_ID) ||
......
...@@ -326,7 +326,7 @@ qla2x00_start_scsi(srb_t *sp) ...@@ -326,7 +326,7 @@ qla2x00_start_scsi(srb_t *sp)
tot_dsds = nseg; tot_dsds = nseg;
/* Calculate the number of request entries needed. */ /* Calculate the number of request entries needed. */
req_cnt = ha->isp_ops.calc_req_entries(tot_dsds); req_cnt = ha->isp_ops->calc_req_entries(tot_dsds);
if (ha->req_q_cnt < (req_cnt + 2)) { if (ha->req_q_cnt < (req_cnt + 2)) {
cnt = RD_REG_WORD_RELAXED(ISP_REQ_Q_OUT(ha, reg)); cnt = RD_REG_WORD_RELAXED(ISP_REQ_Q_OUT(ha, reg));
if (ha->req_ring_index < cnt) if (ha->req_ring_index < cnt)
...@@ -364,7 +364,7 @@ qla2x00_start_scsi(srb_t *sp) ...@@ -364,7 +364,7 @@ qla2x00_start_scsi(srb_t *sp)
cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
/* Build IOCB segments */ /* Build IOCB segments */
ha->isp_ops.build_iocbs(sp, cmd_pkt, tot_dsds); ha->isp_ops->build_iocbs(sp, cmd_pkt, tot_dsds);
/* Set total data segment count. */ /* Set total data segment count. */
cmd_pkt->entry_count = (uint8_t)req_cnt; cmd_pkt->entry_count = (uint8_t)req_cnt;
...@@ -432,7 +432,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, ...@@ -432,7 +432,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
mrk->entry_type = MARKER_TYPE; mrk->entry_type = MARKER_TYPE;
mrk->modifier = type; mrk->modifier = type;
if (type != MK_SYNC_ALL) { if (type != MK_SYNC_ALL) {
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
mrk24 = (struct mrk_entry_24xx *) mrk; mrk24 = (struct mrk_entry_24xx *) mrk;
mrk24->nport_handle = cpu_to_le16(loop_id); mrk24->nport_handle = cpu_to_le16(loop_id);
mrk24->lun[1] = LSB(lun); mrk24->lun[1] = LSB(lun);
...@@ -487,7 +487,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha) ...@@ -487,7 +487,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha)
for (timer = HZ; timer; timer--) { for (timer = HZ; timer; timer--) {
if ((req_cnt + 2) >= ha->req_q_cnt) { if ((req_cnt + 2) >= ha->req_q_cnt) {
/* Calculate number of free request entries. */ /* Calculate number of free request entries. */
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
cnt = (uint16_t)RD_REG_DWORD( cnt = (uint16_t)RD_REG_DWORD(
&reg->isp24.req_q_out); &reg->isp24.req_q_out);
else else
...@@ -561,7 +561,7 @@ qla2x00_isp_cmd(scsi_qla_host_t *ha) ...@@ -561,7 +561,7 @@ qla2x00_isp_cmd(scsi_qla_host_t *ha)
ha->request_ring_ptr++; ha->request_ring_ptr++;
/* Set chip new ring index. */ /* Set chip new ring index. */
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
WRT_REG_DWORD(&reg->isp24.req_q_in, ha->req_ring_index); WRT_REG_DWORD(&reg->isp24.req_q_in, ha->req_ring_index);
RD_REG_DWORD_RELAXED(&reg->isp24.req_q_in); RD_REG_DWORD_RELAXED(&reg->isp24.req_q_in);
} else { } else {
......
...@@ -143,7 +143,7 @@ qla2300_intr_handler(int irq, void *dev_id) ...@@ -143,7 +143,7 @@ qla2300_intr_handler(int irq, void *dev_id)
WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC); WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
RD_REG_WORD(&reg->hccr); RD_REG_WORD(&reg->hccr);
ha->isp_ops.fw_dump(ha, 1); ha->isp_ops->fw_dump(ha, 1);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
break; break;
} else if ((stat & HSR_RISC_INT) == 0) } else if ((stat & HSR_RISC_INT) == 0)
...@@ -247,7 +247,7 @@ void ...@@ -247,7 +247,7 @@ void
qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
{ {
#define LS_UNKNOWN 2 #define LS_UNKNOWN 2
static char *link_speeds[5] = { "1", "2", "?", "4", "10" }; static char *link_speeds[5] = { "1", "2", "?", "4", "8" };
char *link_speed; char *link_speed;
uint16_t handle_cnt; uint16_t handle_cnt;
uint16_t cnt; uint16_t cnt;
...@@ -334,9 +334,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ...@@ -334,9 +334,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
"ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n", "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",
mb[1], mb[2], mb[3]); mb[1], mb[2], mb[3]);
ha->isp_ops.fw_dump(ha, 1); ha->isp_ops->fw_dump(ha, 1);
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
if (mb[1] == 0 && mb[2] == 0) { if (mb[1] == 0 && mb[2] == 0) {
qla_printk(KERN_ERR, ha, qla_printk(KERN_ERR, ha,
"Unrecoverable Hardware Error: adapter " "Unrecoverable Hardware Error: adapter "
...@@ -601,7 +601,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ...@@ -601,7 +601,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
"scsi(%ld): [R|Z]IO update completion.\n", "scsi(%ld): [R|Z]IO update completion.\n",
ha->host_no)); ha->host_no));
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
qla24xx_process_response_queue(ha); qla24xx_process_response_queue(ha);
else else
qla2x00_process_response_queue(ha); qla2x00_process_response_queue(ha);
...@@ -823,7 +823,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) ...@@ -823,7 +823,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
sts = (sts_entry_t *) pkt; sts = (sts_entry_t *) pkt;
sts24 = (struct sts_entry_24xx *) pkt; sts24 = (struct sts_entry_24xx *) pkt;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
comp_status = le16_to_cpu(sts24->comp_status); comp_status = le16_to_cpu(sts24->comp_status);
scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
} else { } else {
...@@ -872,7 +872,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) ...@@ -872,7 +872,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
fcport = sp->fcport; fcport = sp->fcport;
sense_len = rsp_info_len = resid_len = fw_resid_len = 0; sense_len = rsp_info_len = resid_len = fw_resid_len = 0;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
sense_len = le32_to_cpu(sts24->sense_len); sense_len = le32_to_cpu(sts24->sense_len);
rsp_info_len = le32_to_cpu(sts24->rsp_data_len); rsp_info_len = le32_to_cpu(sts24->rsp_data_len);
resid_len = le32_to_cpu(sts24->rsp_residual_count); resid_len = le32_to_cpu(sts24->rsp_residual_count);
...@@ -891,7 +891,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) ...@@ -891,7 +891,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
/* Check for any FCP transport errors. */ /* Check for any FCP transport errors. */
if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) {
/* Sense data lies beyond any FCP RESPONSE data. */ /* Sense data lies beyond any FCP RESPONSE data. */
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
sense_data += rsp_info_len; sense_data += rsp_info_len;
if (rsp_info_len > 3 && rsp_info[3]) { if (rsp_info_len > 3 && rsp_info[3]) {
DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol "
...@@ -990,7 +990,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) ...@@ -990,7 +990,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
case CS_DATA_UNDERRUN: case CS_DATA_UNDERRUN:
resid = resid_len; resid = resid_len;
/* Use F/W calculated residual length. */ /* Use F/W calculated residual length. */
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
resid = fw_resid_len; resid = fw_resid_len;
if (scsi_status & SS_RESIDUAL_UNDER) { if (scsi_status & SS_RESIDUAL_UNDER) {
...@@ -1062,6 +1062,25 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) ...@@ -1062,6 +1062,25 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
cp->device->id, cp->device->lun, cp, cp->device->id, cp->device->lun, cp,
cp->serial_number)); cp->serial_number));
/*
* In case of a Underrun condition, set both the lscsi
* status and the completion status to appropriate
* values.
*/
if (resid &&
((unsigned)(cp->request_bufflen - resid) <
cp->underflow)) {
DEBUG2(qla_printk(KERN_INFO, ha,
"scsi(%ld:%d:%d:%d): Mid-layer underflow "
"detected (%x of %x bytes)...returning "
"error status.\n", ha->host_no,
cp->device->channel, cp->device->id,
cp->device->lun, resid,
cp->request_bufflen));
cp->result = DID_ERROR << 16 | lscsi_status;
}
if (sense_len) if (sense_len)
DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, DEBUG5(qla2x00_dump_buffer(cp->sense_buffer,
CMD_ACTUAL_SNSLEN(cp))); CMD_ACTUAL_SNSLEN(cp)));
...@@ -1166,7 +1185,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) ...@@ -1166,7 +1185,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
case CS_TIMEOUT: case CS_TIMEOUT:
cp->result = DID_BUS_BUSY << 16; cp->result = DID_BUS_BUSY << 16;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
DEBUG2(printk(KERN_INFO DEBUG2(printk(KERN_INFO
"scsi(%ld:%d:%d:%d): TIMEOUT status detected " "scsi(%ld:%d:%d:%d): TIMEOUT status detected "
"0x%x-0x%x\n", ha->host_no, cp->device->channel, "0x%x-0x%x\n", ha->host_no, cp->device->channel,
...@@ -1235,7 +1254,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt) ...@@ -1235,7 +1254,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt)
} }
/* Move sense data. */ /* Move sense data. */
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
host_to_fcp_swap(pkt->data, sizeof(pkt->data)); host_to_fcp_swap(pkt->data, sizeof(pkt->data));
memcpy(sp->request_sense_ptr, pkt->data, sense_sz); memcpy(sp->request_sense_ptr, pkt->data, sense_sz);
DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz)); DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz));
...@@ -1483,7 +1502,7 @@ qla24xx_intr_handler(int irq, void *dev_id) ...@@ -1483,7 +1502,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
"Dumping firmware!\n", hccr); "Dumping firmware!\n", hccr);
ha->isp_ops.fw_dump(ha, 1); ha->isp_ops->fw_dump(ha, 1);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
break; break;
} else if ((stat & HSRX_RISC_INT) == 0) } else if ((stat & HSRX_RISC_INT) == 0)
...@@ -1617,7 +1636,7 @@ qla24xx_msix_default(int irq, void *dev_id) ...@@ -1617,7 +1636,7 @@ qla24xx_msix_default(int irq, void *dev_id)
qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
"Dumping firmware!\n", hccr); "Dumping firmware!\n", hccr);
ha->isp_ops.fw_dump(ha, 1); ha->isp_ops->fw_dump(ha, 1);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
break; break;
} else if ((stat & HSRX_RISC_INT) == 0) } else if ((stat & HSRX_RISC_INT) == 0)
...@@ -1739,11 +1758,11 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) ...@@ -1739,11 +1758,11 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
int ret; int ret;
/* If possible, enable MSI-X. */ /* If possible, enable MSI-X. */
if (!IS_QLA2432(ha)) if (!IS_QLA2432(ha) && !IS_QLA2532(ha))
goto skip_msix; goto skip_msix;
if (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX || if (IS_QLA2432(ha) && (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX ||
!QLA_MSIX_FW_MODE_1(ha->fw_attributes)) { !QLA_MSIX_FW_MODE_1(ha->fw_attributes))) {
DEBUG2(qla_printk(KERN_WARNING, ha, DEBUG2(qla_printk(KERN_WARNING, ha,
"MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n", "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n",
ha->chip_revision, ha->fw_attributes)); ha->chip_revision, ha->fw_attributes));
...@@ -1762,7 +1781,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) ...@@ -1762,7 +1781,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
"MSI-X: Falling back-to INTa mode -- %d.\n", ret); "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
skip_msix: skip_msix:
if (!IS_QLA24XX(ha)) if (!IS_QLA24XX(ha) && !IS_QLA2532(ha))
goto skip_msi; goto skip_msi;
ret = pci_enable_msi(ha->pdev); ret = pci_enable_msi(ha->pdev);
...@@ -1772,7 +1791,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) ...@@ -1772,7 +1791,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
} }
skip_msi: skip_msi:
ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler, ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha);
if (!ret) { if (!ret) {
ha->flags.inta_enabled = 1; ha->flags.inta_enabled = 1;
......
...@@ -90,7 +90,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) ...@@ -90,7 +90,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
/* Load mailbox registers. */ /* Load mailbox registers. */
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
optr = (uint16_t __iomem *)&reg->isp24.mailbox0; optr = (uint16_t __iomem *)&reg->isp24.mailbox0;
else else
optr = (uint16_t __iomem *)MAILBOX_REG(ha, &reg->isp, 0); optr = (uint16_t __iomem *)MAILBOX_REG(ha, &reg->isp, 0);
...@@ -154,7 +154,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) ...@@ -154,7 +154,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT); WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
else else
WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT); WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
...@@ -175,7 +175,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) ...@@ -175,7 +175,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__, DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__,
ha->host_no, command)); ha->host_no, command));
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT); WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
else else
WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT); WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
...@@ -228,7 +228,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) ...@@ -228,7 +228,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
uint16_t mb0; uint16_t mb0;
uint32_t ictrl; uint32_t ictrl;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
mb0 = RD_REG_WORD(&reg->isp24.mailbox0); mb0 = RD_REG_WORD(&reg->isp24.mailbox0);
ictrl = RD_REG_DWORD(&reg->isp24.ictrl); ictrl = RD_REG_DWORD(&reg->isp24.ictrl);
} else { } else {
...@@ -322,7 +322,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr, ...@@ -322,7 +322,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha)) {
mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
mcp->mb[8] = MSW(risc_addr); mcp->mb[8] = MSW(risc_addr);
mcp->out_mb = MBX_8|MBX_0; mcp->out_mb = MBX_8|MBX_0;
...@@ -336,7 +336,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr, ...@@ -336,7 +336,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
mcp->mb[6] = MSW(MSD(req_dma)); mcp->mb[6] = MSW(MSD(req_dma));
mcp->mb[7] = LSW(MSD(req_dma)); mcp->mb[7] = LSW(MSD(req_dma));
mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
mcp->mb[4] = MSW(risc_code_size); mcp->mb[4] = MSW(risc_code_size);
mcp->mb[5] = LSW(risc_code_size); mcp->mb[5] = LSW(risc_code_size);
mcp->out_mb |= MBX_5|MBX_4; mcp->out_mb |= MBX_5|MBX_4;
...@@ -387,7 +387,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) ...@@ -387,7 +387,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr)
mcp->mb[0] = MBC_EXECUTE_FIRMWARE; mcp->mb[0] = MBC_EXECUTE_FIRMWARE;
mcp->out_mb = MBX_0; mcp->out_mb = MBX_0;
mcp->in_mb = MBX_0; mcp->in_mb = MBX_0;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
mcp->mb[1] = MSW(risc_addr); mcp->mb[1] = MSW(risc_addr);
mcp->mb[2] = LSW(risc_addr); mcp->mb[2] = LSW(risc_addr);
mcp->mb[3] = 0; mcp->mb[3] = 0;
...@@ -410,7 +410,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) ...@@ -410,7 +410,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr)
DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__, DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__,
ha->host_no, rval, mcp->mb[0])); ha->host_no, rval, mcp->mb[0]));
} else { } else {
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
DEBUG11(printk("%s(%ld): done exchanges=%x.\n", DEBUG11(printk("%s(%ld): done exchanges=%x.\n",
__func__, ha->host_no, mcp->mb[1])); __func__, ha->host_no, mcp->mb[1]));
} else { } else {
...@@ -551,7 +551,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts) ...@@ -551,7 +551,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts)
mcp->mb[3] = fwopts[3]; mcp->mb[3] = fwopts[3];
mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0; mcp->in_mb = MBX_0;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
mcp->in_mb |= MBX_1; mcp->in_mb |= MBX_1;
} else { } else {
mcp->mb[10] = fwopts[10]; mcp->mb[10] = fwopts[10];
...@@ -664,7 +664,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr) ...@@ -664,7 +664,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
mcp->mb[0] = MBC_VERIFY_CHECKSUM; mcp->mb[0] = MBC_VERIFY_CHECKSUM;
mcp->out_mb = MBX_0; mcp->out_mb = MBX_0;
mcp->in_mb = MBX_0; mcp->in_mb = MBX_0;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
mcp->mb[1] = MSW(risc_addr); mcp->mb[1] = MSW(risc_addr);
mcp->mb[2] = LSW(risc_addr); mcp->mb[2] = LSW(risc_addr);
mcp->out_mb |= MBX_2|MBX_1; mcp->out_mb |= MBX_2|MBX_1;
...@@ -681,8 +681,8 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr) ...@@ -681,8 +681,8 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
if (rval != QLA_SUCCESS) { if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__, DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__,
ha->host_no, rval, (IS_QLA24XX(ha) || IS_QLA54XX(ha) ? ha->host_no, rval, IS_FWI2_CAPABLE(ha) ?
(mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]))); (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]));
} else { } else {
DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
} }
...@@ -739,7 +739,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr, ...@@ -739,7 +739,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr,
/* Mask reserved bits. */ /* Mask reserved bits. */
sts_entry->entry_status &= sts_entry->entry_status &=
IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RF_MASK_24XX :RF_MASK; IS_FWI2_CAPABLE(ha) ? RF_MASK_24XX :RF_MASK;
} }
return rval; return rval;
...@@ -1085,7 +1085,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) ...@@ -1085,7 +1085,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt)
memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE)); memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
mcp->mb[0] = MBC_GET_PORT_DATABASE; mcp->mb[0] = MBC_GET_PORT_DATABASE;
if (opt != 0 && !IS_QLA24XX(ha) && !IS_QLA54XX(ha)) if (opt != 0 && !IS_FWI2_CAPABLE(ha))
mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE; mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE;
mcp->mb[2] = MSW(pd_dma); mcp->mb[2] = MSW(pd_dma);
mcp->mb[3] = LSW(pd_dma); mcp->mb[3] = LSW(pd_dma);
...@@ -1094,7 +1094,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) ...@@ -1094,7 +1094,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt)
mcp->mb[9] = ha->vp_idx; mcp->mb[9] = ha->vp_idx;
mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
mcp->in_mb = MBX_0; mcp->in_mb = MBX_0;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
mcp->mb[1] = fcport->loop_id; mcp->mb[1] = fcport->loop_id;
mcp->mb[10] = opt; mcp->mb[10] = opt;
mcp->out_mb |= MBX_10|MBX_1; mcp->out_mb |= MBX_10|MBX_1;
...@@ -1107,15 +1107,15 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) ...@@ -1107,15 +1107,15 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt)
mcp->mb[1] = fcport->loop_id << 8 | opt; mcp->mb[1] = fcport->loop_id << 8 | opt;
mcp->out_mb |= MBX_1; mcp->out_mb |= MBX_1;
} }
mcp->buf_size = (IS_QLA24XX(ha) || IS_QLA54XX(ha) ? mcp->buf_size = IS_FWI2_CAPABLE(ha) ?
PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE); PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE;
mcp->flags = MBX_DMA_IN; mcp->flags = MBX_DMA_IN;
mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2);
rval = qla2x00_mailbox_command(ha, mcp); rval = qla2x00_mailbox_command(ha, mcp);
if (rval != QLA_SUCCESS) if (rval != QLA_SUCCESS)
goto gpd_error_out; goto gpd_error_out;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
pd24 = (struct port_database_24xx *) pd; pd24 = (struct port_database_24xx *) pd;
/* Check for logged in state. */ /* Check for logged in state. */
...@@ -1333,7 +1333,7 @@ qla2x00_lip_reset(scsi_qla_host_t *ha) ...@@ -1333,7 +1333,7 @@ qla2x00_lip_reset(scsi_qla_host_t *ha)
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
mcp->mb[0] = MBC_LIP_FULL_LOGIN; mcp->mb[0] = MBC_LIP_FULL_LOGIN;
mcp->mb[1] = BIT_6; mcp->mb[1] = BIT_6;
mcp->mb[2] = 0; mcp->mb[2] = 0;
...@@ -1637,7 +1637,7 @@ qla2x00_login_local_device(scsi_qla_host_t *ha, fc_port_t *fcport, ...@@ -1637,7 +1637,7 @@ qla2x00_login_local_device(scsi_qla_host_t *ha, fc_port_t *fcport,
mbx_cmd_t mc; mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc; mbx_cmd_t *mcp = &mc;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) if (IS_FWI2_CAPABLE(ha))
return qla24xx_login_fabric(ha, fcport->loop_id, return qla24xx_login_fabric(ha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa, mb_ret, opt); fcport->d_id.b.al_pa, mb_ret, opt);
...@@ -1821,7 +1821,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha) ...@@ -1821,7 +1821,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha)
ha->host_no)); ha->host_no));
mcp->mb[0] = MBC_LIP_FULL_LOGIN; mcp->mb[0] = MBC_LIP_FULL_LOGIN;
mcp->mb[1] = IS_QLA24XX(ha) || IS_QLA54XX(ha) ? BIT_3: 0; mcp->mb[1] = IS_FWI2_CAPABLE(ha) ? BIT_3: 0;
mcp->mb[2] = 0; mcp->mb[2] = 0;
mcp->mb[3] = 0; mcp->mb[3] = 0;
mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
...@@ -1871,7 +1871,7 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma, ...@@ -1871,7 +1871,7 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma,
mcp->mb[0] = MBC_GET_ID_LIST; mcp->mb[0] = MBC_GET_ID_LIST;
mcp->out_mb = MBX_0; mcp->out_mb = MBX_0;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
mcp->mb[2] = MSW(id_list_dma); mcp->mb[2] = MSW(id_list_dma);
mcp->mb[3] = LSW(id_list_dma); mcp->mb[3] = LSW(id_list_dma);
mcp->mb[6] = MSW(MSD(id_list_dma)); mcp->mb[6] = MSW(MSD(id_list_dma));
...@@ -2063,7 +2063,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id, ...@@ -2063,7 +2063,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
mcp->mb[7] = LSW(MSD(stat_buf_dma)); mcp->mb[7] = LSW(MSD(stat_buf_dma));
mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
mcp->in_mb = MBX_0; mcp->in_mb = MBX_0;
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { if (IS_FWI2_CAPABLE(ha)) {
mcp->mb[1] = loop_id; mcp->mb[1] = loop_id;
mcp->mb[4] = 0; mcp->mb[4] = 0;
mcp->mb[10] = 0; mcp->mb[10] = 0;
...@@ -2334,7 +2334,7 @@ qla2x00_system_error(scsi_qla_host_t *ha) ...@@ -2334,7 +2334,7 @@ qla2x00_system_error(scsi_qla_host_t *ha)
mbx_cmd_t mc; mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc; mbx_cmd_t *mcp = &mc;
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) if (!IS_FWI2_CAPABLE(ha))
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
...@@ -2444,7 +2444,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *ha) ...@@ -2444,7 +2444,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *ha)
mbx_cmd_t mc; mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc; mbx_cmd_t *mcp = &mc;
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) if (!IS_FWI2_CAPABLE(ha))
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
...@@ -2474,7 +2474,7 @@ qla2x00_trace_control(scsi_qla_host_t *ha, uint16_t ctrl, dma_addr_t eft_dma, ...@@ -2474,7 +2474,7 @@ qla2x00_trace_control(scsi_qla_host_t *ha, uint16_t ctrl, dma_addr_t eft_dma,
mbx_cmd_t mc; mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc; mbx_cmd_t *mcp = &mc;
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) if (!IS_FWI2_CAPABLE(ha))
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
...@@ -2514,7 +2514,7 @@ qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr, ...@@ -2514,7 +2514,7 @@ qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr,
mbx_cmd_t mc; mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc; mbx_cmd_t *mcp = &mc;
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) if (!IS_FWI2_CAPABLE(ha))
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
...@@ -2552,7 +2552,7 @@ qla2x00_get_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, ...@@ -2552,7 +2552,7 @@ qla2x00_get_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id,
mbx_cmd_t mc; mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc; mbx_cmd_t *mcp = &mc;
if (!IS_QLA24XX(ha)) if (!IS_IIDMA_CAPABLE(ha))
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
...@@ -2595,7 +2595,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, ...@@ -2595,7 +2595,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id,
mbx_cmd_t mc; mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc; mbx_cmd_t *mcp = &mc;
if (!IS_QLA24XX(ha)) if (!IS_IIDMA_CAPABLE(ha))
return QLA_FUNCTION_FAILED; return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
......
此差异已折叠。
...@@ -766,6 +766,29 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, ...@@ -766,6 +766,29 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
return ret; return ret;
} }
uint8_t *
qla25xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
uint32_t bytes)
{
uint32_t i;
uint32_t *dwptr;
/* Dword reads to flash. */
dwptr = (uint32_t *)buf;
for (i = 0; i < bytes >> 2; i++, naddr++)
dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
flash_data_to_access_addr(FA_VPD_NVRAM_ADDR | naddr)));
return buf;
}
int
qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
uint32_t bytes)
{
return qla24xx_write_flash_data(ha, (uint32_t *)buf,
FA_VPD_NVRAM_ADDR | naddr, bytes >> 2);
}
static inline void static inline void
qla2x00_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags) qla2x00_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags)
...@@ -919,7 +942,7 @@ qla2x00_beacon_off(struct scsi_qla_host *ha) ...@@ -919,7 +942,7 @@ qla2x00_beacon_off(struct scsi_qla_host *ha)
else else
ha->beacon_color_state = QLA_LED_GRN_ON; ha->beacon_color_state = QLA_LED_GRN_ON;
ha->isp_ops.beacon_blink(ha); /* This turns green LED off */ ha->isp_ops->beacon_blink(ha); /* This turns green LED off */
ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING; ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
ha->fw_options[1] &= ~FO1_DISABLE_GPIO6_7; ha->fw_options[1] &= ~FO1_DISABLE_GPIO6_7;
...@@ -1031,7 +1054,7 @@ qla24xx_beacon_off(struct scsi_qla_host *ha) ...@@ -1031,7 +1054,7 @@ qla24xx_beacon_off(struct scsi_qla_host *ha)
ha->beacon_blink_led = 0; ha->beacon_blink_led = 0;
ha->beacon_color_state = QLA_LED_ALL_ON; ha->beacon_color_state = QLA_LED_ALL_ON;
ha->isp_ops.beacon_blink(ha); /* Will flip to all off. */ ha->isp_ops->beacon_blink(ha); /* Will flip to all off. */
/* Give control back to firmware. */ /* Give control back to firmware. */
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->hardware_lock, flags);
...@@ -1419,7 +1442,7 @@ qla2x00_suspend_hba(struct scsi_qla_host *ha) ...@@ -1419,7 +1442,7 @@ qla2x00_suspend_hba(struct scsi_qla_host *ha)
/* Suspend HBA. */ /* Suspend HBA. */
scsi_block_requests(ha->host); scsi_block_requests(ha->host);
ha->isp_ops.disable_intrs(ha); ha->isp_ops->disable_intrs(ha);
set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
/* Pause RISC. */ /* Pause RISC. */
...@@ -1705,7 +1728,7 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, ...@@ -1705,7 +1728,7 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
{ {
/* Suspend HBA. */ /* Suspend HBA. */
scsi_block_requests(ha->host); scsi_block_requests(ha->host);
ha->isp_ops.disable_intrs(ha); ha->isp_ops->disable_intrs(ha);
set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
/* Go with read. */ /* Go with read. */
...@@ -1713,7 +1736,7 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, ...@@ -1713,7 +1736,7 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
/* Resume HBA. */ /* Resume HBA. */
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
ha->isp_ops.enable_intrs(ha); ha->isp_ops->enable_intrs(ha);
scsi_unblock_requests(ha->host); scsi_unblock_requests(ha->host);
return buf; return buf;
...@@ -1727,7 +1750,7 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, ...@@ -1727,7 +1750,7 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
/* Suspend HBA. */ /* Suspend HBA. */
scsi_block_requests(ha->host); scsi_block_requests(ha->host);
ha->isp_ops.disable_intrs(ha); ha->isp_ops->disable_intrs(ha);
set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
/* Go with write. */ /* Go with write. */
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册