forked from TencentOS/TencentOS-kernel
Compare commits
35 Commits
master
...
tk3/fix_ud
| Author | SHA1 | Date |
|---|---|---|
|
|
6a5c938a8c | |
|
|
ad81a1a4f9 | |
|
|
11c214a0ea | |
|
|
86174fab46 | |
|
|
2eda7fb569 | |
|
|
7dd04507a4 | |
|
|
90bf81d5a4 | |
|
|
4a21bdff34 | |
|
|
888ebc6ce8 | |
|
|
b0ce81de19 | |
|
|
16294cf152 | |
|
|
949898196f | |
|
|
d9a9de4ecb | |
|
|
63041cefa6 | |
|
|
2260961e4e | |
|
|
f25df32da5 | |
|
|
b4c389e338 | |
|
|
98d8065ab5 | |
|
|
0f77c3ff8f | |
|
|
f1355f197a | |
|
|
4766c86fd5 | |
|
|
2f09e7ee6d | |
|
|
b4977709b7 | |
|
|
23e7bcb226 | |
|
|
a7777b0c29 | |
|
|
21008e5ae6 | |
|
|
aedf71cbd7 | |
|
|
83cae9c63f | |
|
|
6a3d84a0e8 | |
|
|
9db1459215 | |
|
|
eff5c3174b | |
|
|
9d1c23eb89 | |
|
|
ccdeb257e0 | |
|
|
985a0aad22 | |
|
|
207a58f198 |
|
|
@ -903,7 +903,7 @@ static int ubd_disk_register(int major, u64 size, int unit,
|
|||
|
||||
disk->private_data = &ubd_devs[unit];
|
||||
disk->queue = ubd_devs[unit].queue;
|
||||
device_add_disk(parent, disk);
|
||||
device_add_disk(parent, disk, NULL);
|
||||
|
||||
*disk_out = disk;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -835,6 +835,9 @@ static void blk_rq_timed_out_timer(unsigned long data)
|
|||
{
|
||||
struct request_queue *q = (struct request_queue *)data;
|
||||
|
||||
if (blk_queue_no_timeout(q))
|
||||
return;
|
||||
|
||||
kblockd_schedule_work(&q->timeout_work);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2439,6 +2439,9 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
|
|||
|
||||
q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT;
|
||||
|
||||
if (set->flags & BLK_MQ_F_NO_TIMEOUT)
|
||||
queue_flag_set_unlocked(QUEUE_FLAG_NO_TIMEOUT, q);
|
||||
|
||||
if (!(set->flags & BLK_MQ_F_SG_MERGE))
|
||||
q->queue_flags |= 1 << QUEUE_FLAG_NO_SG_MERGE;
|
||||
|
||||
|
|
|
|||
|
|
@ -162,6 +162,14 @@ static ssize_t queue_io_min_show(struct request_queue *q, char *page)
|
|||
return queue_var_show(queue_io_min(q), page);
|
||||
}
|
||||
|
||||
static ssize_t queue_timeout_timer_pending_show(struct request_queue *q, char *page)
|
||||
{
|
||||
unsigned long pending;
|
||||
|
||||
pending = timer_pending(&q->timeout);
|
||||
return queue_var_show(pending, page);
|
||||
}
|
||||
|
||||
static ssize_t queue_io_opt_show(struct request_queue *q, char *page)
|
||||
{
|
||||
return queue_var_show(queue_io_opt(q), page);
|
||||
|
|
@ -590,6 +598,11 @@ static struct queue_sysfs_entry queue_io_min_entry = {
|
|||
.show = queue_io_min_show,
|
||||
};
|
||||
|
||||
static struct queue_sysfs_entry queue_timeout_timer_pending = {
|
||||
.attr = {.name = "timeout_timer_pending", .mode = S_IRUGO },
|
||||
.show = queue_timeout_timer_pending_show,
|
||||
};
|
||||
|
||||
static struct queue_sysfs_entry queue_io_opt_entry = {
|
||||
.attr = {.name = "optimal_io_size", .mode = S_IRUGO },
|
||||
.show = queue_io_opt_show,
|
||||
|
|
@ -714,6 +727,7 @@ static struct attribute *default_attrs[] = {
|
|||
&queue_physical_block_size_entry.attr,
|
||||
&queue_chunk_sectors_entry.attr,
|
||||
&queue_io_min_entry.attr,
|
||||
&queue_timeout_timer_pending.attr,
|
||||
&queue_io_opt_entry.attr,
|
||||
&queue_discard_granularity_entry.attr,
|
||||
&queue_discard_max_entry.attr,
|
||||
|
|
|
|||
|
|
@ -199,6 +199,9 @@ void blk_add_timer(struct request *req)
|
|||
if (!q->mq_ops && !q->rq_timed_out_fn)
|
||||
return;
|
||||
|
||||
if (blk_queue_no_timeout(q))
|
||||
return;
|
||||
|
||||
BUG_ON(!list_empty(&req->timeout_list));
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -564,7 +564,8 @@ static int exact_lock(dev_t devt, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void register_disk(struct device *parent, struct gendisk *disk)
|
||||
static void register_disk(struct device *parent, struct gendisk *disk,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
struct device *ddev = disk_to_dev(disk);
|
||||
struct block_device *bdev;
|
||||
|
|
@ -579,6 +580,10 @@ static void register_disk(struct device *parent, struct gendisk *disk)
|
|||
/* delay uevents, until we scanned partition table */
|
||||
dev_set_uevent_suppress(ddev, 1);
|
||||
|
||||
if (groups) {
|
||||
WARN_ON(ddev->groups);
|
||||
ddev->groups = groups;
|
||||
}
|
||||
if (device_add(ddev))
|
||||
return;
|
||||
if (!sysfs_deprecated) {
|
||||
|
|
@ -640,7 +645,8 @@ exit:
|
|||
*
|
||||
* FIXME: error handling
|
||||
*/
|
||||
void device_add_disk(struct device *parent, struct gendisk *disk)
|
||||
void device_add_disk(struct device *parent, struct gendisk *disk,
|
||||
const struct attribute_group **groups)
|
||||
{
|
||||
struct backing_dev_info *bdi;
|
||||
dev_t devt;
|
||||
|
|
@ -676,7 +682,7 @@ void device_add_disk(struct device *parent, struct gendisk *disk)
|
|||
|
||||
blk_register_region(disk_devt(disk), disk->minors, NULL,
|
||||
exact_match, exact_lock, disk);
|
||||
register_disk(parent, disk);
|
||||
register_disk(parent, disk, groups);
|
||||
blk_register_queue(disk);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -202,7 +202,6 @@ int aoeblk_init(void);
|
|||
void aoeblk_exit(void);
|
||||
void aoeblk_gdalloc(void *);
|
||||
void aoedisk_rm_debugfs(struct aoedev *d);
|
||||
void aoedisk_rm_sysfs(struct aoedev *d);
|
||||
|
||||
int aoechr_init(void);
|
||||
void aoechr_exit(void);
|
||||
|
|
|
|||
|
|
@ -177,10 +177,15 @@ static struct attribute *aoe_attrs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group attr_group = {
|
||||
static const struct attribute_group aoe_attr_group = {
|
||||
.attrs = aoe_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *aoe_attr_groups[] = {
|
||||
&aoe_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct file_operations aoe_debugfs_fops = {
|
||||
.open = aoe_debugfs_open,
|
||||
.read = seq_read,
|
||||
|
|
@ -219,17 +224,6 @@ aoedisk_rm_debugfs(struct aoedev *d)
|
|||
d->debugfs = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
aoedisk_add_sysfs(struct aoedev *d)
|
||||
{
|
||||
return sysfs_create_group(&disk_to_dev(d->gd)->kobj, &attr_group);
|
||||
}
|
||||
void
|
||||
aoedisk_rm_sysfs(struct aoedev *d)
|
||||
{
|
||||
sysfs_remove_group(&disk_to_dev(d->gd)->kobj, &attr_group);
|
||||
}
|
||||
|
||||
static int
|
||||
aoeblk_open(struct block_device *bdev, fmode_t mode)
|
||||
{
|
||||
|
|
@ -418,8 +412,7 @@ aoeblk_gdalloc(void *vp)
|
|||
|
||||
spin_unlock_irqrestore(&d->lock, flags);
|
||||
|
||||
add_disk(gd);
|
||||
aoedisk_add_sysfs(d);
|
||||
device_add_disk(NULL, gd, aoe_attr_groups);
|
||||
aoedisk_add_debugfs(d);
|
||||
|
||||
spin_lock_irqsave(&d->lock, flags);
|
||||
|
|
|
|||
|
|
@ -276,7 +276,6 @@ freedev(struct aoedev *d)
|
|||
del_timer_sync(&d->timer);
|
||||
if (d->gd) {
|
||||
aoedisk_rm_debugfs(d);
|
||||
aoedisk_rm_sysfs(d);
|
||||
del_gendisk(d->gd);
|
||||
put_disk(d->gd);
|
||||
blk_cleanup_queue(d->blkq);
|
||||
|
|
|
|||
|
|
@ -4675,7 +4675,7 @@ static int __init do_floppy_init(void)
|
|||
/* to be cleaned up... */
|
||||
disks[drive]->private_data = (void *)(long)drive;
|
||||
disks[drive]->flags |= GENHD_FL_REMOVABLE;
|
||||
device_add_disk(&floppy_device[drive].dev, disks[drive]);
|
||||
device_add_disk(&floppy_device[drive].dev, disks[drive], NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -3889,7 +3889,7 @@ skip_create_disk:
|
|||
set_capacity(dd->disk, capacity);
|
||||
|
||||
/* Enable the block device and add it to /dev */
|
||||
device_add_disk(&dd->pdev->dev, dd->disk);
|
||||
device_add_disk(&dd->pdev->dev, dd->disk, NULL);
|
||||
|
||||
dd->bdev = bdget_disk(dd->disk, 0);
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -502,7 +502,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
|
|||
gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
|
||||
get_capacity(gendisk) >> 11);
|
||||
|
||||
device_add_disk(&dev->sbd.core, gendisk);
|
||||
device_add_disk(&dev->sbd.core, gendisk, NULL);
|
||||
return 0;
|
||||
|
||||
fail_cleanup_queue:
|
||||
|
|
|
|||
|
|
@ -781,7 +781,7 @@ static int ps3vram_probe(struct ps3_system_bus_device *dev)
|
|||
dev_info(&dev->core, "%s: Using %lu MiB of GPU memory\n",
|
||||
gendisk->disk_name, get_capacity(gendisk) >> 11);
|
||||
|
||||
device_add_disk(&dev->core, gendisk);
|
||||
device_add_disk(&dev->core, gendisk, NULL);
|
||||
return 0;
|
||||
|
||||
fail_cleanup_queue:
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ int rsxx_attach_dev(struct rsxx_cardinfo *card)
|
|||
set_capacity(card->gendisk, card->size8 >> 9);
|
||||
else
|
||||
set_capacity(card->gendisk, 0);
|
||||
device_add_disk(CARD_TO_DEV(card), card->gendisk);
|
||||
device_add_disk(CARD_TO_DEV(card), card->gendisk, NULL);
|
||||
card->bdev_attached = 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3102,7 +3102,7 @@ static int skd_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
|||
static int skd_bdev_attach(struct device *parent, struct skd_device *skdev)
|
||||
{
|
||||
dev_dbg(&skdev->pdev->dev, "add_disk\n");
|
||||
device_add_disk(parent, skdev->disk);
|
||||
device_add_disk(parent, skdev->disk, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -855,7 +855,7 @@ static int probe_disk(struct vdc_port *port)
|
|||
port->vdisk_size, (port->vdisk_size >> (20 - 9)),
|
||||
port->vio.ver.major, port->vio.ver.minor);
|
||||
|
||||
device_add_disk(&port->vio.vdev->dev, g);
|
||||
device_add_disk(&port->vio.vdev->dev, g, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -351,8 +351,8 @@ static int minor_to_index(int minor)
|
|||
return minor >> PART_BITS;
|
||||
}
|
||||
|
||||
static ssize_t virtblk_serial_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t serial_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
int err;
|
||||
|
|
@ -371,7 +371,7 @@ static ssize_t virtblk_serial_show(struct device *dev,
|
|||
return err;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(serial, S_IRUGO, virtblk_serial_show, NULL);
|
||||
static DEVICE_ATTR_RO(serial);
|
||||
|
||||
static void virtblk_config_changed_work(struct work_struct *work)
|
||||
{
|
||||
|
|
@ -536,8 +536,8 @@ static const char *const virtblk_cache_types[] = {
|
|||
};
|
||||
|
||||
static ssize_t
|
||||
virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
cache_type_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
struct virtio_blk *vblk = disk->private_data;
|
||||
|
|
@ -555,8 +555,7 @@ virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
|
|||
}
|
||||
|
||||
static ssize_t
|
||||
virtblk_cache_type_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
cache_type_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
struct virtio_blk *vblk = disk->private_data;
|
||||
|
|
@ -566,12 +565,38 @@ virtblk_cache_type_show(struct device *dev, struct device_attribute *attr,
|
|||
return snprintf(buf, 40, "%s\n", virtblk_cache_types[writeback]);
|
||||
}
|
||||
|
||||
static const struct device_attribute dev_attr_cache_type_ro =
|
||||
__ATTR(cache_type, S_IRUGO,
|
||||
virtblk_cache_type_show, NULL);
|
||||
static const struct device_attribute dev_attr_cache_type_rw =
|
||||
__ATTR(cache_type, S_IRUGO|S_IWUSR,
|
||||
virtblk_cache_type_show, virtblk_cache_type_store);
|
||||
static DEVICE_ATTR_RW(cache_type);
|
||||
|
||||
static struct attribute *virtblk_attrs[] = {
|
||||
&dev_attr_serial.attr,
|
||||
&dev_attr_cache_type.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static umode_t virtblk_attrs_are_visible(struct kobject *kobj,
|
||||
struct attribute *a, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
struct virtio_blk *vblk = disk->private_data;
|
||||
struct virtio_device *vdev = vblk->vdev;
|
||||
|
||||
if (a == &dev_attr_cache_type.attr &&
|
||||
!virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE))
|
||||
return S_IRUGO;
|
||||
|
||||
return a->mode;
|
||||
}
|
||||
|
||||
static const struct attribute_group virtblk_attr_group = {
|
||||
.attrs = virtblk_attrs,
|
||||
.is_visible = virtblk_attrs_are_visible,
|
||||
};
|
||||
|
||||
static const struct attribute_group *virtblk_attr_groups[] = {
|
||||
&virtblk_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int virtblk_init_request(struct blk_mq_tag_set *set, struct request *rq,
|
||||
unsigned int hctx_idx, unsigned int numa_node)
|
||||
|
|
@ -694,7 +719,7 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|||
vblk->tag_set.ops = &virtio_mq_ops;
|
||||
vblk->tag_set.queue_depth = virtblk_queue_depth;
|
||||
vblk->tag_set.numa_node = NUMA_NO_NODE;
|
||||
vblk->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
|
||||
vblk->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_NO_TIMEOUT;
|
||||
vblk->tag_set.cmd_size =
|
||||
sizeof(struct virtblk_req) +
|
||||
sizeof(struct scatterlist) * sg_elems;
|
||||
|
|
@ -793,24 +818,9 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|||
|
||||
virtio_device_ready(vdev);
|
||||
|
||||
device_add_disk(&vdev->dev, vblk->disk);
|
||||
err = device_create_file(disk_to_dev(vblk->disk), &dev_attr_serial);
|
||||
if (err)
|
||||
goto out_del_disk;
|
||||
|
||||
if (virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE))
|
||||
err = device_create_file(disk_to_dev(vblk->disk),
|
||||
&dev_attr_cache_type_rw);
|
||||
else
|
||||
err = device_create_file(disk_to_dev(vblk->disk),
|
||||
&dev_attr_cache_type_ro);
|
||||
if (err)
|
||||
goto out_del_disk;
|
||||
device_add_disk(&vdev->dev, vblk->disk, virtblk_attr_groups);
|
||||
return 0;
|
||||
|
||||
out_del_disk:
|
||||
del_gendisk(vblk->disk);
|
||||
blk_cleanup_queue(vblk->disk->queue);
|
||||
out_free_tags:
|
||||
blk_mq_free_tag_set(&vblk->tag_set);
|
||||
out_put_disk:
|
||||
|
|
|
|||
|
|
@ -2399,7 +2399,7 @@ static void blkfront_connect(struct blkfront_info *info)
|
|||
for (i = 0; i < info->nr_rings; i++)
|
||||
kick_pending_request_queues(&info->rinfo[i]);
|
||||
|
||||
device_add_disk(&info->xbdev->dev, info->gd);
|
||||
device_add_disk(&info->xbdev->dev, info->gd, NULL);
|
||||
|
||||
info->is_ready = 1;
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1576,7 +1576,7 @@ static int zram_add(void)
|
|||
blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX);
|
||||
|
||||
disk_to_dev(zram->disk)->groups = zram_disk_attr_groups;
|
||||
add_disk(zram->disk);
|
||||
device_add_disk(NULL, zram->disk, zram_disk_attr_groups);
|
||||
|
||||
strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
|
||||
|
||||
|
|
|
|||
|
|
@ -1802,7 +1802,7 @@ static int ide_cd_probe(ide_drive_t *drive)
|
|||
ide_cd_read_toc(drive, &sense);
|
||||
g->fops = &idecd_ops;
|
||||
g->flags |= GENHD_FL_REMOVABLE | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
|
||||
device_add_disk(&drive->gendev, g);
|
||||
device_add_disk(&drive->gendev, g, NULL);
|
||||
return 0;
|
||||
|
||||
out_free_disk:
|
||||
|
|
|
|||
|
|
@ -416,7 +416,7 @@ static int ide_gd_probe(ide_drive_t *drive)
|
|||
if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
|
||||
g->flags = GENHD_FL_REMOVABLE;
|
||||
g->fops = &ide_gd_ops;
|
||||
device_add_disk(&drive->gendev, g);
|
||||
device_add_disk(&drive->gendev, g, NULL);
|
||||
return 0;
|
||||
|
||||
out_free_disk:
|
||||
|
|
|
|||
|
|
@ -281,9 +281,9 @@ static void clear_translation_pre_enabled(struct amd_iommu *iommu)
|
|||
|
||||
static void init_translation_status(struct amd_iommu *iommu)
|
||||
{
|
||||
u32 ctrl;
|
||||
u64 ctrl;
|
||||
|
||||
ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
if (ctrl & (1<<CONTROL_IOMMU_EN))
|
||||
iommu->flags |= AMD_IOMMU_FLAG_TRANS_PRE_ENABLED;
|
||||
}
|
||||
|
|
@ -387,30 +387,30 @@ static void iommu_set_device_table(struct amd_iommu *iommu)
|
|||
/* Generic functions to enable/disable certain features of the IOMMU. */
|
||||
static void iommu_feature_enable(struct amd_iommu *iommu, u8 bit)
|
||||
{
|
||||
u32 ctrl;
|
||||
u64 ctrl;
|
||||
|
||||
ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
ctrl |= (1 << bit);
|
||||
writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
ctrl |= (1ULL << bit);
|
||||
writeq(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
}
|
||||
|
||||
static void iommu_feature_disable(struct amd_iommu *iommu, u8 bit)
|
||||
{
|
||||
u32 ctrl;
|
||||
u64 ctrl;
|
||||
|
||||
ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
ctrl &= ~(1 << bit);
|
||||
writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
ctrl &= ~(1ULL << bit);
|
||||
writeq(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
}
|
||||
|
||||
static void iommu_set_inv_tlb_timeout(struct amd_iommu *iommu, int timeout)
|
||||
{
|
||||
u32 ctrl;
|
||||
u64 ctrl;
|
||||
|
||||
ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
ctrl &= ~CTRL_INV_TO_MASK;
|
||||
ctrl |= (timeout << CONTROL_INV_TIMEOUT) & CTRL_INV_TO_MASK;
|
||||
writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
writeq(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
|
||||
}
|
||||
|
||||
/* Function to enable the hardware */
|
||||
|
|
|
|||
|
|
@ -2151,7 +2151,7 @@ static int msb_init_disk(struct memstick_dev *card)
|
|||
set_disk_ro(msb->disk, 1);
|
||||
|
||||
msb_start(card);
|
||||
device_add_disk(&card->dev, msb->disk);
|
||||
device_add_disk(&card->dev, msb->disk, NULL);
|
||||
dbg("Disk added");
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -1242,7 +1242,7 @@ static int mspro_block_init_disk(struct memstick_dev *card)
|
|||
set_capacity(msb->disk, capacity);
|
||||
dev_dbg(&card->dev, "capacity set %ld\n", capacity);
|
||||
|
||||
device_add_disk(&card->dev, msb->disk);
|
||||
device_add_disk(&card->dev, msb->disk, NULL);
|
||||
msb->active = 1;
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -2308,7 +2308,7 @@ static int mmc_add_disk(struct mmc_blk_data *md)
|
|||
int ret;
|
||||
struct mmc_card *card = md->queue.card;
|
||||
|
||||
device_add_disk(md->parent, md->disk);
|
||||
device_add_disk(md->parent, md->disk, NULL);
|
||||
md->force_ro.show = force_ro_show;
|
||||
md->force_ro.store = force_ro_store;
|
||||
sysfs_attr_init(&md->force_ro.attr);
|
||||
|
|
|
|||
|
|
@ -439,7 +439,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
|
|||
if (new->readonly)
|
||||
set_disk_ro(gd, 1);
|
||||
|
||||
device_add_disk(&new->mtd->dev, gd);
|
||||
device_add_disk(&new->mtd->dev, gd, NULL);
|
||||
|
||||
if (new->disk_attributes) {
|
||||
ret = sysfs_create_group(&disk_to_dev(gd)->kobj,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,13 +1,49 @@
|
|||
#!/usr/bin/make
|
||||
# Makefile for building Linux Broadcom Gigabit ethernet driver as a module.
|
||||
# $id$
|
||||
KVER=
|
||||
ifeq ($(KVER),)
|
||||
KVER=$(shell uname -r)
|
||||
endif
|
||||
|
||||
KERNELDIR=$(shell pwd)
|
||||
KVER_MAJ=$(shell echo $(KVER) | cut -d "." -f1)
|
||||
|
||||
ifneq ($(shell ls /$(KERNELDIR)/source > /dev/null 2>&1 && echo source),)
|
||||
LINUXSRC=/$(KERNELDIR)/source
|
||||
__ARCH=$(shell uname -m)
|
||||
|
||||
# PREFIX may be set by the RPM build to set the effective root.
|
||||
PREFIX=
|
||||
ifeq ($(shell ls /lib/modules/$(KVER)/build > /dev/null 2>&1 && echo build),)
|
||||
# SuSE source RPMs
|
||||
_KVER=$(shell echo $(KVER) | cut -d "-" -f1,2)
|
||||
_KFLA=$(shell echo $(KVER) | cut -d "-" -f3)
|
||||
_ARCH=$(shell file -b /lib/modules/$(shell uname -r)/build | cut -d "/" -f5)
|
||||
ifeq ($(_ARCH),)
|
||||
_ARCH=$(__ARCH)
|
||||
endif
|
||||
ifeq ($(shell ls /usr/src/linux-$(_KVER)-obj > /dev/null 2>&1 && echo linux),)
|
||||
ifeq ($(shell ls /usr/src/kernels/$(KVER)-$(__ARCH) > /dev/null 2>&1 && echo linux),)
|
||||
LINUX=
|
||||
else
|
||||
LINUX=/usr/src/kernels/$(KVER)-$(__ARCH)
|
||||
LINUXSRC=$(LINUX)
|
||||
endif
|
||||
else
|
||||
LINUX=/usr/src/linux-$(_KVER)-obj/$(_ARCH)/$(_KFLA)
|
||||
LINUXSRC=/usr/src/linux-$(_KVER)
|
||||
endif
|
||||
else
|
||||
LINUXSRC=$(KERNELDIR)
|
||||
LINUX=/lib/modules/$(KVER)/build
|
||||
ifeq ($(shell ls /lib/modules/$(KVER)/source > /dev/null 2>&1 && echo source),)
|
||||
LINUXSRC=$(LINUX)
|
||||
else
|
||||
LINUXSRC=/lib/modules/$(KVER)/source
|
||||
endif
|
||||
endif
|
||||
|
||||
KDIR ?= $(srctree)
|
||||
ifneq ($(KDIR),)
|
||||
LINUX=$(KDIR)
|
||||
LINUXSRC=$(LINUX)
|
||||
endif
|
||||
|
||||
ifeq ($(shell ls $(LINUXSRC)/include/uapi/linux > /dev/null 2>&1 && echo uapi),)
|
||||
|
|
@ -16,6 +52,26 @@ else
|
|||
UAPI=uapi
|
||||
endif
|
||||
|
||||
ifeq ($(BCMMODDIR),)
|
||||
ifeq ($(shell ls /lib/modules/$(KVER)/updates > /dev/null 2>&1 && echo 1),1)
|
||||
BCMMODDIR=/lib/modules/$(KVER)/updates
|
||||
else
|
||||
ifeq ($(shell grep -q "search.*[[:space:]]updates" /etc/depmod.conf > /dev/null 2>&1 && echo 1),1)
|
||||
BCMMODDIR=/lib/modules/$(KVER)/updates
|
||||
else
|
||||
ifeq ($(shell grep -q "search.*[[:space:]]updates" /etc/depmod.d/* > /dev/null 2>&1 && echo 1),1)
|
||||
BCMMODDIR=/lib/modules/$(KVER)/updates
|
||||
else
|
||||
ifeq ($(shell expr $(KVER_MAJ) \>= 3), 1)
|
||||
BCMMODDIR=/lib/modules/$(KVER)/updates
|
||||
else
|
||||
BCMMODDIR=/lib/modules/$(KVER)/kernel/drivers/net
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "pci_enable_msix_range" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG = -DHAVE_MSIX_RANGE
|
||||
else
|
||||
|
|
@ -28,10 +84,6 @@ ifneq ($(shell grep -o "msix_cap" $(LINUXSRC)/include/linux/pci.h),)
|
|||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "module_pci_driver" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_MODULE_PCI_DRIVER
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "GENL_ID_GENERATE" $(LINUXSRC)/include/uapi/linux/genetlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_GENL_ID_GENERATE
|
||||
endif
|
||||
|
|
@ -123,6 +175,38 @@ ifneq ($(shell grep -o "dma_set_coherent_mask" $(LINUXSRC)/include/linux/dma-map
|
|||
DISTRO_CFLAG += -DHAVE_SET_COHERENT_MASK
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep "dma_buf_export" $(LINUXSRC)/include/linux/dma-buf.h | grep "exp_info"),)
|
||||
DISTRO_CFLAG += -DHAVE_DMA_EXPORT
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -w "dma_buf_export" $(LINUXSRC)/include/linux/dma-buf.h | grep "define"),)
|
||||
ifneq ($(shell grep "dma_buf_export" $(LINUXSRC)/include/linux/dma-buf.h | grep "resv"),)
|
||||
DISTRO_CFLAG += -DHAVE_DMA_EXPORT_FLAG_RESV
|
||||
else
|
||||
DISTRO_CFLAG += -DHAVE_DMA_EXPORT_FLAG
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -w "(*kmap_atomic)" $(LINUXSRC)/include/linux/dma-buf.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DMABUF_KMAP_ATOMIC
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -w "(*kmap)" $(LINUXSRC)/include/linux/dma-buf.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DMABUF_KMAP
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -w "(*map_atomic)" $(LINUXSRC)/include/linux/dma-buf.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DMABUF_MAP_ATOMIC
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -w "(*map)" $(LINUXSRC)/include/linux/dma-buf.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DMABUF_MAP
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -w "attach" $(LINUXSRC)/include/linux/dma-buf.h | grep "struct device"),)
|
||||
DISTRO_CFLAG += -DHAVE_DMABUF_ATTACH_DEV
|
||||
endif
|
||||
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/linux/dma-attrs.h > /dev/null 2>&1 && echo dma_attrs),)
|
||||
DISTRO_CFLAG += -DHAVE_DMA_ATTRS_H
|
||||
endif
|
||||
|
|
@ -139,15 +223,18 @@ ifneq ($(shell grep -o "dma_zalloc_coherent" $(LINUXSRC)/include/linux/dma-mappi
|
|||
DISTRO_CFLAG += -DHAVE_DMA_ZALLOC_COHERENT
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_add_vxlan_port" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_ADD_VXLAN
|
||||
ifneq ($(shell grep -so "vxlan_get_rx_port" $(LINUXSRC)/include/net/vxlan.h),)
|
||||
DISTRO_CFLAG += -DHAVE_VXLAN_GET_RX_PORT
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_udp_tunnel_add" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_UDP_TUNNEL
|
||||
ifneq ($(shell grep -A 24 "net_device_ops_extended" $(LINUXSRC)/include/linux/netdevice.h | grep -o "ndo_udp_tunnel_add"),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_UDP_TUNNEL_RH
|
||||
endif
|
||||
else
|
||||
ifneq ($(shell grep -o "ndo_add_vxlan_port" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_ADD_VXLAN
|
||||
ifneq ($(shell grep -so "vxlan_get_rx_port" $(LINUXSRC)/include/net/vxlan.h),)
|
||||
DISTRO_CFLAG += -DHAVE_VXLAN_GET_RX_PORT
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "struct dev_addr_list" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
|
|
@ -197,6 +284,9 @@ ifneq ($(shell ls $(LINUXSRC)/include/net/flow_offload.h > /dev/null 2>&1 && ech
|
|||
ifneq ($(shell grep -o "FLOW_ACTION_POLICE" $(LINUXSRC)/include/net/flow_offload.h),)
|
||||
DISTRO_CFLAG += -DHAVE_FLOW_ACTION_POLICE
|
||||
endif
|
||||
ifneq ($(shell grep -o "flow_action_basic_hw_stats_check" $(LINUXSRC)/include/net/flow_offload.h),)
|
||||
DISTRO_CFLAG += -DHAVE_FLOW_ACTION_BASIC_HW_STATS_CHECK
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/net/udp_tunnel.h > /dev/null 2>&1 && echo udp_tunnel),)
|
||||
|
|
@ -258,6 +348,10 @@ ifneq ($(shell grep -so "ETHTOOL_LINK_MODE_25000baseCR_Full_BIT" $(LINUXSRC)/inc
|
|||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "ETHTOOL_LINK_MODE_50000baseCR_Full_BIT" $(LINUXSRC)/include/$(UAPI)/linux/ethtool.h),)
|
||||
DISTRO_CFLAG += -DHAVE_ETHTOOL_GLINKSETTINGS_PAM4
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "ethtool_tcpip6_spec" $(LINUXSRC)/include/$(UAPI)/linux/ethtool.h),)
|
||||
DISTRO_CFLAG += -DHAVE_ETHTOOL_IP6_SPEC
|
||||
endif
|
||||
|
|
@ -380,11 +474,8 @@ ifneq ($(shell grep -o "ndo_set_vf_vlan_rh73" $(LINUXSRC)/include/linux/netdevic
|
|||
endif
|
||||
|
||||
ifneq ($(shell grep -o "ndo_set_vf_trust" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
ifeq ($(shell grep -o "net_device_ops_ext" $(LINUXSRC)/include/linux/netdevice.h),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SET_VF_TRUST
|
||||
endif
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SET_VF_TRUST
|
||||
ifneq ($(shell grep -A 3 "net_device_ops_extended" $(LINUXSRC)/include/linux/netdevice.h | grep -o "ndo_set_vf_trust"),)
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SET_VF_TRUST
|
||||
DISTRO_CFLAG += -DHAVE_NDO_SET_VF_TRUST_RH
|
||||
endif
|
||||
endif
|
||||
|
|
@ -553,6 +644,10 @@ ifneq ($(shell grep -so "struct xdp_rxq_info" $(LINUXSRC)/include/net/xdp.h),)
|
|||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "xdp_data_hard_end" $(LINUXSRC)/include/net/xdp.h),)
|
||||
DISTRO_CFLAG += -DHAVE_XDP_FRAME_SZ
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "page_pool_release_page" $(LINUXSRC)/include/net/page_pool.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PAGE_POOL_RELEASE_PAGE
|
||||
endif
|
||||
|
|
@ -649,6 +744,14 @@ ifneq ($(shell grep -o "pci_physfn" $(LINUXSRC)/include/linux/pci.h),)
|
|||
DISTRO_CFLAG += -DHAVE_PCI_PHYSFN
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "pcie_flr" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PCIE_FLR
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "pci_get_dsn" $(LINUXSRC)/include/linux/pci.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PCI_GET_DSN
|
||||
endif
|
||||
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/$(UAPI)/linux/net_tstamp.h > /dev/null 2>&1 && echo net_tstamp),)
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/linux/timecounter.h > /dev/null 2>&1 && echo timecounter),)
|
||||
ifneq ($(shell ls $(LINUXSRC)/include/linux/timekeeping.h > /dev/null 2>&1 && echo timekeeping),)
|
||||
|
|
@ -659,6 +762,10 @@ ifneq ($(shell ls $(LINUXSRC)/include/$(UAPI)/linux/net_tstamp.h > /dev/null 2>&
|
|||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "gettimex64" $(LINUXSRC)/include/linux/ptp_clock_kernel.h),)
|
||||
DISTRO_CFLAG += -DHAVE_PTP_GETTIMEX64
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o "time64_to_tm" $(LINUXSRC)/include/linux/time.h),)
|
||||
DISTRO_CFLAG += -DHAVE_TIME64
|
||||
endif
|
||||
|
|
@ -704,6 +811,9 @@ endif
|
|||
|
||||
ifneq ($(shell grep -so "info_get" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_INFO
|
||||
ifneq ($(shell grep -so "devlink_info_board_serial_number_put" $(LINUXSRC)/include/net/devlink.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_INFO_BSN_PUT
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "flash_update" $(LINUXSRC)/include/net/devlink.h),)
|
||||
|
|
@ -730,6 +840,10 @@ ifneq ($(shell grep -so "devlink_health_reporter_recovery_done" $(LINUXSRC)/incl
|
|||
DISTRO_CFLAG += -DHAVE_DEVLINK_HEALTH_REPORTER_RECOVERY_DONE
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -s -A 2 "devlink_health_reporter_create" $(LINUXSRC)/include/net/devlink.h | grep auto_recover),)
|
||||
DISTRO_CFLAG += -DHAVE_DEVLINK_HEALTH_AUTO_RECOVER
|
||||
endif
|
||||
|
||||
# Check if the file exists or not
|
||||
ifneq ($(shell grep -s "switchdev_ops" $(LINUXSRC)/include/net/switchdev.h),)
|
||||
DISTRO_CFLAG += -DHAVE_SWITCHDEV
|
||||
|
|
@ -743,6 +857,10 @@ ifneq ($(shell grep -so "(*ieee_delapp)" $(LINUXSRC)/include/net/dcbnl.h),)
|
|||
DISTRO_CFLAG += -DHAVE_IEEE_DELAPP
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -so "dcb_ieee_getapp_prio_dscp_mask_map" $(LINUXSRC)/include/net/dcbnl.h),)
|
||||
DISTRO_CFLAG += -DHAVE_DSCP_MASK_MAP
|
||||
endif
|
||||
|
||||
ifneq ($(shell grep -o cpumask_local_spread $(LINUXSRC)/include/linux/cpumask.h),)
|
||||
DISTRO_CFLAG += -DHAVE_CPUMASK_LOCAL_SPREAD
|
||||
endif
|
||||
|
|
@ -767,11 +885,59 @@ ifneq ($(shell grep -o hwmon_device_register_with_groups $(LINUXSRC)/include/lin
|
|||
DISTRO_CFLAG += -DHAVE_NEW_HWMON_API
|
||||
endif
|
||||
|
||||
EXTRA_CFLAGS += ${DISTRO_CFLAG} -g -DCHIMP_FW -D__LINUX -DCONFIG_BNXT_SRIOV -DCONFIG_BNXT_DCB -DCONFIG_BNXT_FLASHDEV -DHSI_DBG_DISABLE -DCONFIG_BNXT_LFC
|
||||
ifneq ($(shell grep -o ETH_RESET_CRASHDUMP $(LINUXSRC)/include/uapi/linux/ethtool.h),)
|
||||
DISTRO_CFLAG += -DHAVE_ETHTOOL_RESET_CRASHDUMP
|
||||
endif
|
||||
|
||||
override EXTRA_CFLAGS += ${DISTRO_CFLAG} -g -DCHIMP_FW -D__LINUX -DCONFIG_BNXT_SRIOV -DCONFIG_BNXT_DCB -DCONFIG_BNXT_FLASHDEV -DHSI_DBG_DISABLE -DCONFIG_BNXT_LFC
|
||||
|
||||
cflags-y += $(EXTRA_CFLAGS)
|
||||
|
||||
BNXT_DBGFS_OBJ = bnxt_debugfs_cpt.o
|
||||
BCM_DRV = bnxt_en.ko
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
obj-$(CONFIG_BNXT) += bnxt_en.o
|
||||
bnxt_en-y := bnxt.o bnxt_ethtool.o bnxt_sriov.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_ptp.o bnxt_vfr.o bnxt_tc.o bnxt_devlink.o bnxt_lfc.o bnxt_netlink.o bnxt_dim.o $(BNXT_DBGFS_OBJ) #decode_hsi.o
|
||||
ifeq ($(shell expr $(KVER_MAJ) \>= 5), 1)
|
||||
BNXT_DBGFS_OBJ = bnxt_debugfs.o
|
||||
else
|
||||
BNXT_DBGFS_OBJ = bnxt_debugfs_cpt.o
|
||||
endif
|
||||
|
||||
obj-m += bnxt_en.o
|
||||
bnxt_en-y := bnxt.o bnxt_hwrm.o bnxt_ethtool.o bnxt_sriov.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_ptp.o bnxt_vfr.o bnxt_tc.o bnxt_devlink.o bnxt_lfc.o bnxt_netlink.o bnxt_dim.o bnxt_eem.o $(BNXT_DBGFS_OBJ) #decode_hsi.o
|
||||
|
||||
else
|
||||
|
||||
default:
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
make -C $(LINUX) M=$(shell pwd) modules
|
||||
else ifneq ($(CROSS_COMPILE),)
|
||||
make -C $(LINUXSRC) M=$(shell pwd) modules CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH)
|
||||
endif
|
||||
|
||||
yocto_all:
|
||||
$(MAKE) -C $(LINUXSRC) M=$(shell pwd)
|
||||
|
||||
modules_install:
|
||||
$(MAKE) -C $(LINUXSRC) M=$(shell pwd) modules_install
|
||||
|
||||
endif
|
||||
|
||||
install: default
|
||||
@if [ "$(KDIR)" != "" ]; then \
|
||||
echo "Cannot use install with KDIR option"; exit 2;\
|
||||
fi
|
||||
mkdir -p $(PREFIX)$(BCMMODDIR);
|
||||
install -m 444 $(BCM_DRV) $(PREFIX)$(BCMMODDIR);
|
||||
@if [ "$(PREFIX)" = "" ]; then /sbin/depmod -a ;\
|
||||
else echo " *** Run '/sbin/depmod -a' to update the module database.";\
|
||||
fi
|
||||
|
||||
.PHONEY: all clean install
|
||||
|
||||
clean:
|
||||
-rm -f bnxt.o bnxt.mod.c bnxt.mod.o .bnxt.*.cmd *.cmd *.markers *.order *.symvers decode_hsi.o .decode_*
|
||||
-rm -rf .tmp_versions
|
||||
-rm -rf bnxt_en.o bnxt_en.ko bnxt_en.mod.o bnxt_en.mod.c .bnxt_en.* bnxt_sriov.o .bnxt_sriov.* bnxt_ethtool.o .bnxt_ethtool.* bnxt_dcb.o .bnxt_dcb.* bnxt_ulp.o .bnxt_ulp.* bnxt_ptp.o .bnxt_ptp.* bnxt_xdp.o .bnxt_xdp.* bnxt_lfc.o .bnxt_lfc.* bnxt_hwrm.o .bnxt_hwrm.*
|
||||
-rm -rf bnxt_vfr.o .bnxt_vfr.* bnxt_tc.o .bnxt_tc.* bnxt_devlink.o .bnxt_devlink.* bnxt_netlink.o .bnxt_netlink.*
|
||||
-rm -rf bnxt_dim.o .bnxt_dim.* bnxt_debugfs*.o .bnxt_debugfs* bnxt_eem.o .bnxt_eem*
|
||||
-rm -f Module.markers Module.symvers modules.order
|
||||
|
|
|
|||
|
|
@ -133,8 +133,8 @@ module option, the vxlan.ko module must be loaded before the bnxt_en.ko module.
|
|||
Using newer kernels, the hwmon.ko module may need to be loaded first if
|
||||
CONFIG_HWMON_MODULE kernel option is set as a module option.
|
||||
|
||||
Using newer kernels, devlink.ko module may need to be loaded first if
|
||||
CONFIG_NET_DEVLINK kernel option is set as a module option.
|
||||
Using kernel versions 4.6 or higher, devlink.ko module may need to be loaded
|
||||
first if CONFIG_NET_DEVLINK kernel option is set as a module option.
|
||||
|
||||
BNXT_EN Driver Settings
|
||||
=======================
|
||||
|
|
@ -266,35 +266,67 @@ for rx and tx but must both be non-zero.
|
|||
|
||||
ethtool -x eth0
|
||||
|
||||
Note that the RSS indirection table size may vary depending on the device
|
||||
and the number of RX channels.
|
||||
|
||||
13. Set 40-byte RSS hash key:
|
||||
|
||||
ethtool -X eth0 hkey 00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f:20:21:22:23:24:25:26:27
|
||||
|
||||
14. Run self test:
|
||||
14. Set RSS indirection table:
|
||||
|
||||
ethtool -X eth0 [start N] [ equal N | weight W0 W1 ... | default ]
|
||||
|
||||
Example: Set RSS indirection table to have equal distribution for the first
|
||||
four channels:
|
||||
|
||||
ethtool -X eth0 equal 4
|
||||
|
||||
Example: Set RSS indirection table to have equal distribution for six
|
||||
channels starting from channel 2:
|
||||
|
||||
ethtool -X eth0 start 2 equal 6
|
||||
|
||||
Note that the start parameter is 0-based.
|
||||
|
||||
Example: Set RSS indirection table to have weight distributions of 1:2:3:4
|
||||
for four channels starting from channel 4:
|
||||
|
||||
ethtool -X eth0 start 4 weight 1 2 3 4
|
||||
|
||||
Note that the number of channels being configured must be valid and must not
|
||||
exceed the number of RX or combined channels. The configured settings will be
|
||||
preserved whenever possible even when the number of RX or combined channels is
|
||||
changed. In some cases when the settings cannot be preserved, the indirection
|
||||
table will revert back to default even distribution for all channels.
|
||||
|
||||
15. Run self test:
|
||||
|
||||
ethtool -t eth0
|
||||
|
||||
Note that only single function PFs can execute self tests. If a PF has
|
||||
active VFs, only online tests can be executed.
|
||||
|
||||
15. Collect Firmware Coredump:
|
||||
16. Collect Firmware Coredump:
|
||||
|
||||
ethtool -w eth0 data FILENAME
|
||||
|
||||
16. Set coredump flags:
|
||||
17. Set coredump flags:
|
||||
|
||||
ethtool -W eth0 N
|
||||
|
||||
Note that N is '0' for collecting live dump and '1' for collecting saved
|
||||
crash dump.
|
||||
crash dump. 'crash dump' is supported only on adapters that support
|
||||
TEE_BNXT_FW option.
|
||||
|
||||
17. Reset the device:
|
||||
18. Reset the device:
|
||||
|
||||
ethtool --reset eth0 [flags N] [type]
|
||||
|
||||
Note that driver supports 'ap' and 'all' type of resets.
|
||||
Note that driver supports 'ap' and 'all' type of resets. Also, '--reset'
|
||||
option is available from ethtool version 4.15 or newer.
|
||||
|
||||
18. Add receive network flow classification filters.
|
||||
19. Add receive network flow classification filters.
|
||||
|
||||
ethtool -N eth0 flow-type ether|tcp4|udp4|tcp6|udp6 FLOW_SPEC
|
||||
|
||||
|
|
@ -316,6 +348,9 @@ Example: UDP/IPv4 4-tuple filter to rx queue 2
|
|||
ethtool -N eth0 flow-type udp4 dst-ip 192.168.0.1 src-ip 192.168.0.2 \
|
||||
dst-port 2049 action 2
|
||||
|
||||
The action parameter must be greater than or equal to 0 to specify the
|
||||
RX queue/ring number. Negative action parameters are not supported.
|
||||
|
||||
The flow-type is counted as the first tuple and must always be specified.
|
||||
At least one additional tuple must be specified for TCP/UDP filters. A
|
||||
tuple must either be completely specified or not specified at all. A
|
||||
|
|
@ -329,7 +364,10 @@ another 4-tuple filter, for example. In general, the more specific
|
|||
|
||||
If the filter is created succesfully, the ID of the filter will be returned
|
||||
by ethtool. ethtool -n will also display the current list of filters with
|
||||
their IDs. A specific filter can be deleted by specifying the ID.
|
||||
their IDs. A specific filter can be deleted by specifying the ID. The
|
||||
"loc" parameter that allows the user to specify the location of the filter
|
||||
is not supported. It must be the default 0xffffffff which means that the
|
||||
driver will choose the location/ID.
|
||||
|
||||
Example: Delete filter ID 3
|
||||
|
||||
|
|
@ -340,7 +378,7 @@ filters, any duplicate 5-tuple filters added by ethtool will be rejected.
|
|||
It is generally not recommended to enable accelerated RFS and create
|
||||
static 5-tuple filters on the same function.
|
||||
|
||||
19. See ethtool man page for more options.
|
||||
20. See ethtool man page for more options.
|
||||
|
||||
|
||||
Autoneg
|
||||
|
|
@ -1100,6 +1138,19 @@ packets bigger than 1518 bytes when using earlier versions of the firmware.
|
|||
Newer version of the firmware has reprogrammed the counter to count
|
||||
packets bigger than 9600 bytes.
|
||||
|
||||
If the "rx_discards" and "rx_buf_errors" counters are high compared to the
|
||||
total recieve packets for that ring, it generally means that the host CPU
|
||||
is not processing the incoming packets fast enough and causing packet drops.
|
||||
The number of receive packets dropped is indicated by these counters.
|
||||
Increasing the receive ring size may reduce the number of dropped packets (See
|
||||
BNXT_EN Driver Settings section above, examples 5 and 6).
|
||||
|
||||
The "rx_l4_csum_errors" counter will increment for every TCP/UDP checksum
|
||||
error detected by hardware on each ring if RX checksum offload is enabled.
|
||||
Such packets will be rejected by the stack and similar stack error
|
||||
counters for TCP/UDP will also increment. Note that IPv4 checksum is
|
||||
always verified by the stack and not offloaded.
|
||||
|
||||
|
||||
Unloading and Removing Driver
|
||||
=============================
|
||||
|
|
@ -1162,13 +1213,20 @@ below steps
|
|||
Devlink
|
||||
=======
|
||||
|
||||
In newer kernels, some operations on bnxt_en driver can be done using devlink.
|
||||
In kernel versions 4.6 or higher, some operations on bnxt_en driver can be done
|
||||
using devlink.
|
||||
|
||||
Devlink tool is part of iproute2 routing commands and utilities. Latest devlink
|
||||
can be downloaded from http://www.kernel.org/pub/linux/utils/net/iproute2/,
|
||||
if it is not already installed. Following are some examples on how to use
|
||||
devlink. See the devlink man page for more information.
|
||||
if it is not already installed.
|
||||
|
||||
devlink examples:
|
||||
As devlink tool is evolving, use latest kernel and iproute2 tool available for
|
||||
all features via devlink.
|
||||
|
||||
Following are some examples on how to use devlink. See the devlink man page
|
||||
for more information.
|
||||
|
||||
Some devlink examples:
|
||||
|
||||
1. Command to display board information and firmware versions:
|
||||
|
||||
|
|
@ -1184,15 +1242,19 @@ pci/0000:3b:00.0:
|
|||
serial_number B0-26-28-FF-FE-C8-85-20
|
||||
versions:
|
||||
fixed:
|
||||
board.id BCM957508-P2100G
|
||||
asic.id 1750
|
||||
asic.rev 1
|
||||
running:
|
||||
fw 216.0.167.0
|
||||
fw.psid 0.0.6
|
||||
fw.app 216.0.167.0
|
||||
fw.mgmt 864.0.32.0
|
||||
fw.mgmt 216.0.167.0
|
||||
fw.mgmt.api 1.10.1
|
||||
fw.ncsi 864.0.32.0
|
||||
fw.roce 216.0.157.0
|
||||
|
||||
Note that 'info' is supported in 5.1 or higher kernel versions.
|
||||
|
||||
2. Updating firmware:
|
||||
|
||||
devlink dev flash DEV file PATH
|
||||
|
|
@ -1202,6 +1264,8 @@ Example:
|
|||
|
||||
Note: File path is relative to /lib/firmware directory.
|
||||
|
||||
Note that 'flash' is supported in 5.1 or higher kernel versions.
|
||||
|
||||
3. Dump device level driver parameter information:
|
||||
|
||||
devlink dev param show
|
||||
|
|
@ -1220,6 +1284,8 @@ pci/0000:3b:00.0:
|
|||
values:
|
||||
cmode permanent value true
|
||||
|
||||
Note that 'param' is supported in 4.19 or higher kernel versions.
|
||||
|
||||
5. Set the device level driver parameter information:
|
||||
|
||||
devlink dev param set DEV name PARAMETER value VALUE cmode \
|
||||
|
|
@ -1234,13 +1300,13 @@ Example:
|
|||
devlink health show [ DEV reporter REPORTER ]
|
||||
|
||||
Example:
|
||||
devlink health show pci/0000:3b:00.0 reporter fw
|
||||
devlink health show pci/0000:3b:00.0 reporter fw_fatal
|
||||
|
||||
will show:
|
||||
|
||||
pci/0000:3b:00.0:
|
||||
name fw
|
||||
state healthy error 0 recover 0
|
||||
name fw_fatal
|
||||
state healthy error 2 recover 2 grace_period 0 auto_recover true
|
||||
|
||||
Example2:
|
||||
devlink health show pci/0000:af:00.0 reporter fw_reset
|
||||
|
|
@ -1254,6 +1320,9 @@ pci/0000:af:00.0:
|
|||
Note that health reporters are created only when corresponding features
|
||||
are enabled in NVM configuration.
|
||||
|
||||
Note that "fw" health reporter information does not support any type of
|
||||
reset, so the counters displayed by show command will be 0's.
|
||||
|
||||
7. Run diagnostics via health reporter:
|
||||
|
||||
devlink health diagnose DEV reporter REPORTER
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -132,6 +132,10 @@ struct tx_cmp {
|
|||
__le32 tx_cmp_flags_type;
|
||||
#define CMP_TYPE (0x3f << 0)
|
||||
#define CMP_TYPE_TX_L2_CMP 0
|
||||
#define CMP_TYPE_TX_L2_COAL_CMP 2
|
||||
#define CMP_TYPE_TX_L2_PTP_CMP 3
|
||||
#define CMP_TYPE_RX_L2_TPA_START_V2_CMP 13
|
||||
#define CMP_TYPE_RX_L2_V2_CMP 15
|
||||
#define CMP_TYPE_RX_L2_CMP 17
|
||||
#define CMP_TYPE_RX_AGG_CMP 18
|
||||
#define CMP_TYPE_RX_L2_TPA_START_CMP 19
|
||||
|
|
@ -195,6 +199,12 @@ struct rx_cmp {
|
|||
#define RX_CMP_RSS_HASH_TYPE_SHIFT 9
|
||||
#define RX_CMP_PAYLOAD_OFFSET (0xff << 16)
|
||||
#define RX_CMP_PAYLOAD_OFFSET_SHIFT 16
|
||||
#define RX_CMP_METADATA1 (0xf << 28)
|
||||
#define RX_CMP_METADATA1_SHIFT 28
|
||||
#define RX_CMP_METADATA1_TPID_SEL (0x7 << 28)
|
||||
#define RX_CMP_METADATA1_TPID_8021Q (0x1 << 28)
|
||||
#define RX_CMP_METADATA1_TPID_8021AD (0x0 << 28)
|
||||
#define RX_CMP_METADATA1_VALID (0x8 << 28)
|
||||
|
||||
__le32 rx_cmp_rss_hash;
|
||||
};
|
||||
|
|
@ -208,13 +218,23 @@ struct rx_cmp {
|
|||
(((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_RSS_HASH_TYPE) >>\
|
||||
RX_CMP_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK)
|
||||
|
||||
#define RX_CMP_VLAN_VALID(rxcmp) \
|
||||
((rxcmp)->rx_cmp_misc_v1 & cpu_to_le32(RX_CMP_METADATA1_VALID))
|
||||
|
||||
#define RX_CMP_VLAN_TPID_SEL(rxcmp) \
|
||||
(le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_METADATA1_TPID_SEL)
|
||||
|
||||
struct rx_cmp_ext {
|
||||
__le32 rx_cmp_flags2;
|
||||
#define RX_CMP_FLAGS2_IP_CS_CALC 0x1
|
||||
#define RX_CMP_FLAGS2_L4_CS_CALC (0x1 << 1)
|
||||
#define RX_CMP_FLAGS2_T_IP_CS_CALC (0x1 << 2)
|
||||
#define RX_CMP_FLAGS2_T_L4_CS_CALC (0x1 << 3)
|
||||
#define RX_CMP_FLAGS2_CS_ALL_OK_MODE (0x1 << 3)
|
||||
#define RX_CMP_FLAGS2_META_FORMAT_VLAN (0x1 << 4)
|
||||
#define RX_CMP_FLAGS2_CS_OK_MASK (0x3f << 10)
|
||||
#define RX_CMP_FLAGS2_L4_CS_OK_MASK (0x38 << 10)
|
||||
#define RX_CMP_FLAGS2_CS_OK_SFT 10
|
||||
__le32 rx_cmp_meta_data;
|
||||
#define RX_CMP_FLAGS2_METADATA_TCI_MASK 0xffff
|
||||
#define RX_CMP_FLAGS2_METADATA_VID_MASK 0xfff
|
||||
|
|
@ -253,8 +273,18 @@ struct rx_cmp_ext {
|
|||
#define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN_TOO_SMALL (0x7 << 12)
|
||||
#define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN (0x8 << 12)
|
||||
|
||||
#define RX_CMPL_V2_ERRORS_OT_PKT_ERROR_MASK (0x7 << 4)
|
||||
#define RX_CMPL_V2_ERRORS_OT_PKT_L4_CS_ERROR (0x7 << 4)
|
||||
#define RX_CMPL_V2_ERRORS_T_PKT_ERROR_MASK (0x7 << 9)
|
||||
#define RX_CMPL_V2_ERRORS_T_PKT_L4_CS_ERROR (0x7 << 9)
|
||||
#define RX_CMPL_V2_ERRORS_PKT_ERROR_MASK (0xf << 12)
|
||||
#define RX_CMPL_V2_ERRORS_PKT_L4_CS_ERROR (0xa << 12)
|
||||
|
||||
#define RX_CMPL_CFA_CODE_MASK (0xffff << 16)
|
||||
#define RX_CMPL_CFA_CODE_SFT 16
|
||||
#define RX_CMPL_METADATA0_MASK (0xffff << 16)
|
||||
#define RX_CMPL_METADATA0_VID_MASK (0x0fff << 16)
|
||||
#define RX_CMPL_METADATA0_SFT 16
|
||||
|
||||
__le32 rx_cmp_unused3;
|
||||
};
|
||||
|
|
@ -276,10 +306,37 @@ struct rx_cmp_ext {
|
|||
((le32_to_cpu((rxcmp1)->rx_cmp_flags2) & \
|
||||
RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3)
|
||||
|
||||
#define RX_CMP_V2_L4_CS_OK(rxcmp1) \
|
||||
(le32_to_cpu((rxcmp1)->rx_cmp_flags2) & RX_CMP_FLAGS2_L4_CS_OK_MASK)
|
||||
|
||||
#define RX_CMP_V2_L4_CS_OK_CNT(rxcmp1) \
|
||||
(RX_CMP_V2_L4_CS_OK(rxcmp1) >> RX_CMP_FLAGS2_CS_OK_SFT)
|
||||
|
||||
#define RX_CMP_V2_OT_L4_CS_ERR(err) \
|
||||
(((err) & RX_CMPL_V2_ERRORS_OT_PKT_ERROR_MASK) == \
|
||||
RX_CMPL_V2_ERRORS_OT_PKT_L4_CS_ERROR)
|
||||
|
||||
#define RX_CMP_V2_T_L4_CS_ERR(err) \
|
||||
(((err) & RX_CMPL_V2_ERRORS_T_PKT_ERROR_MASK) == \
|
||||
RX_CMPL_V2_ERRORS_T_PKT_L4_CS_ERROR)
|
||||
|
||||
#define RX_CMP_V2_L4_CS_ERR(err) \
|
||||
(((err) & RX_CMPL_V2_ERRORS_PKT_ERROR_MASK) == \
|
||||
RX_CMPL_V2_ERRORS_PKT_L4_CS_ERROR)
|
||||
|
||||
#define RX_CMP_V2_L4_CS_ERRS(rxcmp1) ({ \
|
||||
u32 __err = le32_to_cpu((rxcmp1)->rx_cmp_cfa_code_errors_v2); \
|
||||
(RX_CMP_V2_OT_L4_CS_ERR(__err) || RX_CMP_V2_T_L4_CS_ERR(__err) ||\
|
||||
RX_CMP_V2_L4_CS_ERR(__err)) ? 1 : 0; })
|
||||
|
||||
#define RX_CMP_CFA_CODE(rxcmpl1) \
|
||||
((le32_to_cpu((rxcmpl1)->rx_cmp_cfa_code_errors_v2) & \
|
||||
RX_CMPL_CFA_CODE_MASK) >> RX_CMPL_CFA_CODE_SFT)
|
||||
|
||||
#define RX_CMP_METADATA0_VID(rxcmp1) \
|
||||
((le32_to_cpu((rxcmp1)->rx_cmp_cfa_code_errors_v2) & \
|
||||
RX_CMPL_METADATA0_VID_MASK) >> RX_CMPL_METADATA0_SFT)
|
||||
|
||||
struct rx_agg_cmp {
|
||||
__le32 rx_agg_cmp_len_flags_type;
|
||||
#define RX_AGG_CMP_TYPE (0x3f << 0)
|
||||
|
|
@ -288,7 +345,7 @@ struct rx_agg_cmp {
|
|||
u32 rx_agg_cmp_opaque;
|
||||
__le32 rx_agg_cmp_v;
|
||||
#define RX_AGG_CMP_V (1 << 0)
|
||||
#define RX_AGG_CMP_AGG_ID (0xffff << 16)
|
||||
#define RX_AGG_CMP_AGG_ID (0x0fff << 16)
|
||||
#define RX_AGG_CMP_AGG_ID_SHIFT 16
|
||||
__le32 rx_agg_cmp_unused;
|
||||
};
|
||||
|
|
@ -324,8 +381,10 @@ struct rx_tpa_start_cmp {
|
|||
#define RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT 9
|
||||
#define RX_TPA_START_CMP_AGG_ID (0x7f << 25)
|
||||
#define RX_TPA_START_CMP_AGG_ID_SHIFT 25
|
||||
#define RX_TPA_START_CMP_AGG_ID_P5 (0xffff << 16)
|
||||
#define RX_TPA_START_CMP_AGG_ID_P5 (0x0fff << 16)
|
||||
#define RX_TPA_START_CMP_AGG_ID_SHIFT_P5 16
|
||||
#define RX_TPA_START_CMP_METADATA1 (0xf << 28)
|
||||
#define RX_TPA_START_CMP_METADATA1_SHIFT 28
|
||||
|
||||
__le32 rx_tpa_start_cmp_rss_hash;
|
||||
};
|
||||
|
|
@ -357,6 +416,10 @@ struct rx_tpa_start_cmp_ext {
|
|||
#define RX_TPA_START_CMP_FLAGS2_L4_CS_CALC (0x1 << 1)
|
||||
#define RX_TPA_START_CMP_FLAGS2_T_IP_CS_CALC (0x1 << 2)
|
||||
#define RX_TPA_START_CMP_FLAGS2_T_L4_CS_CALC (0x1 << 3)
|
||||
#define RX_TPA_START_CMP_FLAGS2_CS_ALL_OK_MODE (0x1 << 3)
|
||||
#define RX_TPA_START_CMP_FLAGS2_CS_OK_MASK (0x3f << 10)
|
||||
#define RX_TPA_START_CMP_FLAGS2_L4_CS_OK_MASK (0x38 << 10)
|
||||
#define RX_TPA_START_CMP_FLAGS2_CS_OK_SFT 10
|
||||
#define RX_TPA_START_CMP_FLAGS2_IP_TYPE (0x1 << 8)
|
||||
#define RX_TPA_START_CMP_FLAGS2_CSUM_CMPL_VALID (0x1 << 9)
|
||||
#define RX_TPA_START_CMP_FLAGS2_EXT_META_FORMAT (0x3 << 10)
|
||||
|
|
@ -374,6 +437,8 @@ struct rx_tpa_start_cmp_ext {
|
|||
#define RX_TPA_START_CMP_ERRORS_BUFFER_ERROR_FLUSH (0x5 << 1)
|
||||
#define RX_TPA_START_CMP_CFA_CODE (0xffff << 16)
|
||||
#define RX_TPA_START_CMPL_CFA_CODE_SHIFT 16
|
||||
#define RX_TPA_START_CMP_METADATA0_MASK (0xffff << 16)
|
||||
#define RX_TPA_START_CMP_METADATA0_SFT 16
|
||||
__le32 rx_tpa_start_cmp_hdr_info;
|
||||
};
|
||||
|
||||
|
|
@ -585,6 +650,9 @@ struct nqe_cn {
|
|||
#define DB_WCB_PAGE_SIZE 4096
|
||||
#define DB_WCB_BUFFER_SIZE 256
|
||||
|
||||
#define DB_PPP_SIZE 256
|
||||
#define DB_PPP_BD_OFFSET 16
|
||||
|
||||
#define INVALID_HW_RING_ID ((u16)-1)
|
||||
|
||||
/* The hardware supports certain page sizes. Use the supported page sizes
|
||||
|
|
@ -706,37 +774,7 @@ struct nqe_cn {
|
|||
#define RING_CMP(idx) ((idx) & bp->cp_ring_mask)
|
||||
#define NEXT_CMP(idx) RING_CMP(ADV_RAW_CMP(idx, 1))
|
||||
|
||||
#define BNXT_HWRM_MAX_REQ_LEN (bp->hwrm_max_req_len)
|
||||
#define BNXT_HWRM_SHORT_REQ_LEN sizeof(struct hwrm_short_input)
|
||||
#define DFLT_HWRM_CMD_TIMEOUT 500
|
||||
#define SHORT_HWRM_CMD_TIMEOUT 20
|
||||
#define HWRM_CMD_TIMEOUT (bp->hwrm_cmd_timeout)
|
||||
#define HWRM_RESET_TIMEOUT ((HWRM_CMD_TIMEOUT) * 4)
|
||||
#define HWRM_COREDUMP_TIMEOUT ((HWRM_CMD_TIMEOUT) * 12)
|
||||
#define HWRM_RESP_ERR_CODE_MASK 0xffff
|
||||
#define HWRM_RESP_LEN_OFFSET 4
|
||||
#define HWRM_RESP_LEN_MASK 0xffff0000
|
||||
#define HWRM_RESP_LEN_SFT 16
|
||||
#define HWRM_RESP_VALID_MASK 0xff000000
|
||||
#define BNXT_HWRM_REQ_MAX_SIZE 128
|
||||
#define BNXT_HWRM_REQS_PER_PAGE (BNXT_PAGE_SIZE / \
|
||||
BNXT_HWRM_REQ_MAX_SIZE)
|
||||
#define HWRM_SHORT_MIN_TIMEOUT 3
|
||||
#define HWRM_SHORT_MAX_TIMEOUT 10
|
||||
#define HWRM_SHORT_TIMEOUT_COUNTER 5
|
||||
|
||||
#define HWRM_MIN_TIMEOUT 25
|
||||
#define HWRM_MAX_TIMEOUT 40
|
||||
|
||||
#define HWRM_TOTAL_TIMEOUT(n) (((n) <= HWRM_SHORT_TIMEOUT_COUNTER) ? \
|
||||
((n) * HWRM_SHORT_MIN_TIMEOUT) : \
|
||||
(HWRM_SHORT_TIMEOUT_COUNTER * HWRM_SHORT_MIN_TIMEOUT + \
|
||||
((n) - HWRM_SHORT_TIMEOUT_COUNTER) * HWRM_MIN_TIMEOUT))
|
||||
|
||||
#define HWRM_VALID_BIT_DELAY_USEC 150
|
||||
|
||||
#define BNXT_HWRM_CHNL_CHIMP 0
|
||||
#define BNXT_HWRM_CHNL_KONG 1
|
||||
|
||||
#define BNXT_RX_EVENT 1
|
||||
#define BNXT_AGG_EVENT 2
|
||||
|
|
@ -833,6 +871,13 @@ struct bnxt_db_info {
|
|||
#define DB_RING_IDX(db, idx) (((idx) & (db)->db_ring_mask) | \
|
||||
DB_EPOCH(db, idx))
|
||||
|
||||
#define DB_PUSH_LEN(len) (DB_PUSH_INFO_PUSH_SIZE_MASK & \
|
||||
(((sizeof(struct db_push_info) + \
|
||||
sizeof(struct dbc_dbc)) / 8 + \
|
||||
(len)) << DB_PUSH_INFO_PUSH_SIZE_SFT))
|
||||
|
||||
#define DB_PUSH_INFO(db, len, idx) (DB_PUSH_LEN(len) | DB_RING_IDX(db, idx))
|
||||
|
||||
struct bnxt_tx_ring_info {
|
||||
struct bnxt_napi *bnapi;
|
||||
u16 tx_prod;
|
||||
|
|
@ -847,10 +892,7 @@ struct bnxt_tx_ring_info {
|
|||
|
||||
struct bnxt_db_info tx_push_db;
|
||||
void __iomem *tx_push_wcb;
|
||||
union {
|
||||
struct tx_push_buffer *tx_push;
|
||||
struct tx_push_buffer_p5 *tx_push_p5;
|
||||
};
|
||||
struct tx_push_buffer *tx_push;
|
||||
dma_addr_t tx_push_mapping;
|
||||
__le64 data_mapping;
|
||||
|
||||
|
|
@ -984,14 +1026,34 @@ struct bnxt_rx_ring_info {
|
|||
#endif
|
||||
};
|
||||
|
||||
struct bnxt_sw_stats {
|
||||
struct bnxt_rx_sw_stats {
|
||||
u64 rx_l4_csum_errors;
|
||||
u64 rx_resets;
|
||||
u64 rx_buf_errors;
|
||||
u64 missed_irqs;
|
||||
};
|
||||
|
||||
struct bnxt_tx_sw_stats {
|
||||
u64 tx_sw_errors;
|
||||
};
|
||||
|
||||
struct bnxt_cmn_sw_stats {
|
||||
u64 missed_irqs;
|
||||
};
|
||||
|
||||
struct bnxt_sw_stats {
|
||||
struct bnxt_rx_sw_stats rx;
|
||||
struct bnxt_tx_sw_stats tx;
|
||||
struct bnxt_cmn_sw_stats cmn;
|
||||
};
|
||||
|
||||
struct bnxt_stats_mem {
|
||||
u64 *sw_stats;
|
||||
u64 *hw_masks;
|
||||
void *hw_stats;
|
||||
dma_addr_t hw_stats_map;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct bnxt_cp_ring_info {
|
||||
struct bnxt_napi *bnapi;
|
||||
u32 cp_raw_cons;
|
||||
|
|
@ -1016,8 +1078,7 @@ struct bnxt_cp_ring_info {
|
|||
|
||||
dma_addr_t cp_desc_mapping[MAX_CP_PAGES];
|
||||
|
||||
struct ctx_hw_stats *hw_stats;
|
||||
dma_addr_t hw_stats_map;
|
||||
struct bnxt_stats_mem stats;
|
||||
u32 hw_stats_ctx_id;
|
||||
|
||||
struct bnxt_sw_stats sw_stats;
|
||||
|
|
@ -1102,6 +1163,16 @@ struct bnxt_vnic_info {
|
|||
__le16 *rss_table;
|
||||
dma_addr_t rss_hash_key_dma_addr;
|
||||
u64 *rss_hash_key;
|
||||
int rss_table_size;
|
||||
#define BNXT_RSS_TABLE_ENTRIES_P5 64
|
||||
#define BNXT_RSS_TABLE_SIZE_P5 (BNXT_RSS_TABLE_ENTRIES_P5 * 4)
|
||||
#define BNXT_RSS_TABLE_MAX_TBL_P5 8
|
||||
#define BNXT_MAX_RSS_TABLE_SIZE_P5 \
|
||||
(BNXT_RSS_TABLE_SIZE_P5 * BNXT_RSS_TABLE_MAX_TBL_P5)
|
||||
|
||||
#define BNXT_MAX_RSS_TABLE_ENTRIES_P5 \
|
||||
(BNXT_RSS_TABLE_ENTRIES_P5 * BNXT_RSS_TABLE_MAX_TBL_P5)
|
||||
|
||||
u32 rx_mask;
|
||||
|
||||
u8 *mc_list;
|
||||
|
|
@ -1170,7 +1241,6 @@ struct bnxt_vf_info {
|
|||
#define BNXT_VF_LINK_FORCED 0x4
|
||||
#define BNXT_VF_LINK_UP 0x8
|
||||
#define BNXT_VF_TRUST 0x10
|
||||
u32 func_flags; /* func cfg flags */
|
||||
u32 min_tx_rate;
|
||||
u32 max_tx_rate;
|
||||
u16 min_tx_rings;
|
||||
|
|
@ -1315,6 +1385,7 @@ struct bnxt_link_info {
|
|||
#define BNXT_LINK_SPEED_100GB PORT_PHY_QCFG_RESP_LINK_SPEED_100GB
|
||||
#define BNXT_LINK_SPEED_200GB PORT_PHY_QCFG_RESP_LINK_SPEED_200GB
|
||||
u16 support_speeds;
|
||||
u16 support_pam4_speeds;
|
||||
u16 auto_link_speeds; /* fw adv setting */
|
||||
#define BNXT_LINK_SPEED_MSK_100MB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100MB
|
||||
#define BNXT_LINK_SPEED_MSK_1GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_1GB
|
||||
|
|
@ -1326,10 +1397,16 @@ struct bnxt_link_info {
|
|||
#define BNXT_LINK_SPEED_MSK_40GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_40GB
|
||||
#define BNXT_LINK_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB
|
||||
#define BNXT_LINK_SPEED_MSK_100GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100GB
|
||||
#define BNXT_LINK_SPEED_MSK_200GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_200GB
|
||||
u16 auto_pam4_link_speeds;
|
||||
#define BNXT_LINK_PAM4_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_PAM4_SPEEDS_50G
|
||||
#define BNXT_LINK_PAM4_SPEED_MSK_100GB PORT_PHY_QCFG_RESP_SUPPORT_PAM4_SPEEDS_100G
|
||||
#define BNXT_LINK_PAM4_SPEED_MSK_200GB PORT_PHY_QCFG_RESP_SUPPORT_PAM4_SPEEDS_200G
|
||||
u16 support_auto_speeds;
|
||||
u16 support_pam4_auto_speeds;
|
||||
u16 lp_auto_link_speeds;
|
||||
u16 lp_auto_pam4_link_speeds;
|
||||
u16 force_link_speed;
|
||||
u16 force_pam4_link_speed;
|
||||
u32 preemphasis;
|
||||
u8 module_status;
|
||||
u16 fec_cfg;
|
||||
|
|
@ -1341,10 +1418,14 @@ struct bnxt_link_info {
|
|||
u8 autoneg;
|
||||
#define BNXT_AUTONEG_SPEED 1
|
||||
#define BNXT_AUTONEG_FLOW_CTRL 2
|
||||
u8 req_signal_mode;
|
||||
#define BNXT_SIG_MODE_NRZ PORT_PHY_QCFG_RESP_LINK_SIGNAL_MODE_NRZ
|
||||
#define BNXT_SIG_MODE_PAM4 PORT_PHY_QCFG_RESP_LINK_SIGNAL_MODE_PAM4
|
||||
u8 req_duplex;
|
||||
u8 req_flow_ctrl;
|
||||
u16 req_link_speed;
|
||||
u16 advertising; /* user adv setting */
|
||||
u16 advertising_pam4;
|
||||
bool force_link_chng;
|
||||
|
||||
bool phy_retry;
|
||||
|
|
@ -1525,6 +1606,7 @@ struct bnxt_ctx_mem_info {
|
|||
u16 mrav_num_entries_units;
|
||||
u8 tqm_entries_multiple;
|
||||
u8 ctx_kind_initializer;
|
||||
u8 tqm_fp_rings_count;
|
||||
|
||||
u32 flags;
|
||||
#define BNXT_CTX_FLAG_INITED 0x01
|
||||
|
|
@ -1558,6 +1640,7 @@ struct bnxt_fw_health {
|
|||
u8 enabled:1;
|
||||
u8 master:1;
|
||||
u8 fatal:1;
|
||||
u8 status_reliable:1;
|
||||
u8 tmr_multiplier;
|
||||
u8 tmr_counter;
|
||||
u8 fw_reset_seq_cnt;
|
||||
|
|
@ -1585,9 +1668,31 @@ struct bnxt_fw_reporter_ctx {
|
|||
#define BNXT_FW_HEALTH_WIN_BASE 0x3000
|
||||
#define BNXT_FW_HEALTH_WIN_MAP_OFF 8
|
||||
|
||||
#define BNXT_FW_HEALTH_WIN_OFF(reg) (BNXT_FW_HEALTH_WIN_BASE + \
|
||||
((reg) & BNXT_GRC_OFFSET_MASK))
|
||||
|
||||
#define BNXT_FW_STATUS_HEALTHY 0x8000
|
||||
#define BNXT_FW_STATUS_SHUTDOWN 0x100000
|
||||
|
||||
struct bnxt_oem_eem_req {
|
||||
__le32 entry_num;
|
||||
};
|
||||
|
||||
struct bnxt_oem_cmd_req {
|
||||
__le32 req_type;
|
||||
#define BNXT_OEM_CMD_TYPE_EEM_SYS_MEMORY 0x1
|
||||
union {
|
||||
struct bnxt_oem_eem_req eem_req;
|
||||
} req;
|
||||
};
|
||||
|
||||
enum bnxt_push_mode {
|
||||
BNXT_PUSH_MODE_NONE = 0,
|
||||
BNXT_PUSH_MODE_LEGACY, /* legacy silicon operation mode */
|
||||
BNXT_PUSH_MODE_WCB, /* write combining supported on P5 silicon */
|
||||
BNXT_PUSH_MODE_PPP, /* double buffered mode supported on SR2 */
|
||||
};
|
||||
|
||||
struct bnxt {
|
||||
void __iomem *bar0;
|
||||
void __iomem *bar1;
|
||||
|
|
@ -1677,6 +1782,15 @@ struct bnxt {
|
|||
#else
|
||||
#define BNXT_ASIC(bp) true
|
||||
#endif
|
||||
#define BNXT_VPD_FLD_LEN 32
|
||||
char board_partno[BNXT_VPD_FLD_LEN];
|
||||
|
||||
/* Must remain NULL for old bnxt_re upstream/
|
||||
* inbox driver.
|
||||
*/
|
||||
void *reserved_ulp_kabi_0;
|
||||
|
||||
char board_serialno[BNXT_VPD_FLD_LEN];
|
||||
|
||||
struct net_device *dev;
|
||||
struct pci_dev *pdev;
|
||||
|
|
@ -1743,12 +1857,14 @@ struct bnxt {
|
|||
#define BNXT_CHIP_SR2(bp) \
|
||||
((bp)->chip_num == CHIP_NUM_58818)
|
||||
|
||||
/* Chip class phase 5 */
|
||||
#define BNXT_CHIP_P5(bp) \
|
||||
#define BNXT_CHIP_P5_THOR(bp) \
|
||||
((bp)->chip_num == CHIP_NUM_57508 || \
|
||||
(bp)->chip_num == CHIP_NUM_57504 || \
|
||||
(bp)->chip_num == CHIP_NUM_57502 || \
|
||||
BNXT_CHIP_SR2(bp))
|
||||
(bp)->chip_num == CHIP_NUM_57502)
|
||||
|
||||
/* Chip class phase 5 */
|
||||
#define BNXT_CHIP_P5(bp) \
|
||||
(BNXT_CHIP_P5_THOR(bp) || BNXT_CHIP_SR2(bp))
|
||||
|
||||
/* Chip class phase 4.x */
|
||||
#define BNXT_CHIP_P4(bp) \
|
||||
|
|
@ -1761,6 +1877,12 @@ struct bnxt {
|
|||
#define BNXT_CHIP_P4_PLUS(bp) \
|
||||
(BNXT_CHIP_P4(bp) || BNXT_CHIP_P5(bp))
|
||||
|
||||
#define BNXT_CHIP_SUPPORTS_PHY(bp) (BNXT_ASIC(bp) || BNXT_CHIP_SR2(bp))
|
||||
/* Must remain NULL for new bnxt_re upstream/
|
||||
* inbox driver.
|
||||
*/
|
||||
void *reserved_ulp_kabi_1;
|
||||
|
||||
struct bnxt_en_dev *edev;
|
||||
/* The following 2 fields are for
|
||||
* OOT compatibility checking only.
|
||||
|
|
@ -1779,6 +1901,10 @@ struct bnxt {
|
|||
* bnxt_en and bnxt_re.
|
||||
*/
|
||||
struct bnxt_en_dev * (*ulp_probe)(struct net_device *);
|
||||
/* Do not add any fields before
|
||||
* ulp_probe in both OOT and
|
||||
* upstream/inbox drivers.
|
||||
*/
|
||||
|
||||
struct bnxt_napi **bnapi;
|
||||
|
||||
|
|
@ -1823,6 +1949,7 @@ struct bnxt {
|
|||
int tx_nr_rings_xdp;
|
||||
|
||||
int tx_wake_thresh;
|
||||
enum bnxt_push_mode tx_push_mode;
|
||||
int tx_push_thresh;
|
||||
int tx_push_size;
|
||||
|
||||
|
|
@ -1837,6 +1964,8 @@ struct bnxt {
|
|||
struct bnxt_vnic_info *vnic_info;
|
||||
int nr_vnics;
|
||||
u32 rss_hash_cfg;
|
||||
u16 *rss_indir_tbl;
|
||||
u16 rss_indir_tbl_entries;
|
||||
u8 usr_rss_hash_key[HW_HASH_KEY_SIZE];
|
||||
|
||||
u16 max_mtu;
|
||||
|
|
@ -1901,34 +2030,26 @@ struct bnxt {
|
|||
#define BNXT_FW_CAP_ERR_RECOVER_RELOAD 0x00100000
|
||||
#define BNXT_FW_CAP_HOT_RESET 0x00200000
|
||||
#define BNXT_FW_CAP_SHARED_PORT_CFG 0x00400000
|
||||
#define BNXT_FW_CAP_CRASHDUMP 0x00800000
|
||||
#define BNXT_FW_CAP_VLAN_RX_STRIP 0x01000000
|
||||
#define BNXT_FW_CAP_VLAN_TX_INSERT 0x02000000
|
||||
#define BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED 0x04000000
|
||||
#define BNXT_FW_CAP_CFA_EEM 0x08000000
|
||||
|
||||
#define BNXT_NEW_RM(bp) ((bp)->fw_cap & BNXT_FW_CAP_NEW_RM)
|
||||
u32 hwrm_spec_code;
|
||||
u16 hwrm_cmd_seq;
|
||||
u16 hwrm_cmd_kong_seq;
|
||||
u16 hwrm_intr_seq_id;
|
||||
void *hwrm_short_cmd_req_addr;
|
||||
dma_addr_t hwrm_short_cmd_req_dma_addr;
|
||||
void *hwrm_cmd_resp_addr;
|
||||
dma_addr_t hwrm_cmd_resp_dma_addr;
|
||||
void *hwrm_cmd_kong_resp_addr;
|
||||
dma_addr_t hwrm_cmd_kong_resp_dma_addr;
|
||||
void *hwrm_dbg_resp_addr;
|
||||
dma_addr_t hwrm_dbg_resp_dma_addr;
|
||||
struct dma_pool *hwrm_dma_pool;
|
||||
struct hlist_head hwrm_pending_list;
|
||||
#define HWRM_DBG_REG_BUF_SIZE 128
|
||||
|
||||
#ifdef NETDEV_GET_STATS64
|
||||
struct rtnl_link_stats64 net_stats_prev;
|
||||
#endif
|
||||
struct rx_port_stats *hw_rx_port_stats;
|
||||
struct tx_port_stats *hw_tx_port_stats;
|
||||
struct rx_port_stats_ext *hw_rx_port_stats_ext;
|
||||
struct tx_port_stats_ext *hw_tx_port_stats_ext;
|
||||
dma_addr_t hw_rx_port_stats_map;
|
||||
dma_addr_t hw_tx_port_stats_map;
|
||||
dma_addr_t hw_rx_port_stats_ext_map;
|
||||
dma_addr_t hw_tx_port_stats_ext_map;
|
||||
int hw_port_stats_size;
|
||||
struct bnxt_stats_mem port_stats;
|
||||
struct bnxt_stats_mem rx_port_stats_ext;
|
||||
struct bnxt_stats_mem tx_port_stats_ext;
|
||||
u16 fw_rx_stats_ext_size;
|
||||
u16 fw_tx_stats_ext_size;
|
||||
u16 hw_ring_stats_size;
|
||||
|
|
@ -1944,6 +2065,12 @@ struct bnxt {
|
|||
#define BC_HWRM_STR_LEN 21
|
||||
#define PHY_VER_STR_LEN (FW_VER_STR_LEN - BC_HWRM_STR_LEN)
|
||||
char fw_ver_str[FW_VER_STR_LEN];
|
||||
char hwrm_ver_supp[FW_VER_STR_LEN];
|
||||
u64 fw_ver_code;
|
||||
#define BNXT_FW_VER_CODE(maj, min, bld, rsv) \
|
||||
((u64)(maj) << 48 | (u64)(min) << 32 | (u64)(bld) << 16 | (rsv))
|
||||
#define BNXT_FW_MAJ(bp) ((bp)->fw_ver_code >> 48)
|
||||
|
||||
__be16 vxlan_port;
|
||||
u8 vxlan_port_cnt;
|
||||
__le16 vxlan_fw_dst_port_id;
|
||||
|
|
@ -1987,6 +2114,7 @@ struct bnxt {
|
|||
#define BNXT_FW_EXCEPTION_SP_EVENT 19
|
||||
#define BNXT_VF_VNIC_CHANGE_SP_EVENT 20
|
||||
#define BNXT_LINK_CFG_CHANGE_SP_EVENT 21
|
||||
#define BNXT_PTP_CURRENT_TIME_EVENT 22
|
||||
|
||||
struct delayed_work fw_reset_task;
|
||||
int fw_reset_state;
|
||||
|
|
@ -2095,17 +2223,34 @@ struct bnxt {
|
|||
struct list_head tc_indr_block_list;
|
||||
struct notifier_block tc_netdev_nb;
|
||||
#endif
|
||||
struct bnxt_eem_info *eem_info;
|
||||
void *dmabuf_data;
|
||||
struct dentry *debugfs_pdev;
|
||||
struct dentry *debugfs_dim;
|
||||
struct device *hwmon_dev;
|
||||
};
|
||||
|
||||
#define BNXT_GET_RING_STATS64(sw, counter) \
|
||||
(*((sw) + offsetof(struct ctx_hw_stats, counter) / 8))
|
||||
|
||||
#define BNXT_GET_RX_PORT_STATS64(sw, counter) \
|
||||
(*((sw) + offsetof(struct rx_port_stats, counter) / 8))
|
||||
|
||||
#define BNXT_GET_TX_PORT_STATS64(sw, counter) \
|
||||
(*((sw) + offsetof(struct tx_port_stats, counter) / 8))
|
||||
|
||||
#define BNXT_PORT_STATS_SIZE \
|
||||
(sizeof(struct rx_port_stats) + sizeof(struct tx_port_stats) + 1024)
|
||||
|
||||
#define BNXT_TX_PORT_STATS_BYTE_OFFSET \
|
||||
(sizeof(struct rx_port_stats) + 512)
|
||||
|
||||
#define BNXT_RX_STATS_OFFSET(counter) \
|
||||
(offsetof(struct rx_port_stats, counter) / 8)
|
||||
|
||||
#define BNXT_TX_STATS_OFFSET(counter) \
|
||||
((offsetof(struct tx_port_stats, counter) + \
|
||||
sizeof(struct rx_port_stats) + 512) / 8)
|
||||
BNXT_TX_PORT_STATS_BYTE_OFFSET) / 8)
|
||||
|
||||
#define BNXT_RX_STATS_EXT_OFFSET(counter) \
|
||||
(offsetof(struct rx_port_stats_ext, counter) / 8)
|
||||
|
|
@ -2113,6 +2258,11 @@ struct bnxt {
|
|||
#define BNXT_TX_STATS_EXT_OFFSET(counter) \
|
||||
(offsetof(struct tx_port_stats_ext, counter) / 8)
|
||||
|
||||
#define BNXT_HW_FEATURE_VLAN_ALL_RX \
|
||||
(NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)
|
||||
#define BNXT_HW_FEATURE_VLAN_ALL_TX \
|
||||
(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX)
|
||||
|
||||
#ifdef BNXT_PRIV_RX_BUSY_POLL
|
||||
static inline void bnxt_enable_poll(struct bnxt_napi *bnapi)
|
||||
{
|
||||
|
|
@ -2281,77 +2431,18 @@ static inline void bnxt_db_write(struct bnxt *bp, struct bnxt_db_info *db,
|
|||
}
|
||||
}
|
||||
|
||||
static inline bool bnxt_cfa_hwrm_message(u16 req_type)
|
||||
{
|
||||
switch (req_type) {
|
||||
case HWRM_CFA_ENCAP_RECORD_ALLOC:
|
||||
case HWRM_CFA_ENCAP_RECORD_FREE:
|
||||
case HWRM_CFA_DECAP_FILTER_ALLOC:
|
||||
case HWRM_CFA_DECAP_FILTER_FREE:
|
||||
case HWRM_CFA_EM_FLOW_ALLOC:
|
||||
case HWRM_CFA_EM_FLOW_FREE:
|
||||
case HWRM_CFA_EM_FLOW_CFG:
|
||||
case HWRM_CFA_FLOW_ALLOC:
|
||||
case HWRM_CFA_FLOW_FREE:
|
||||
case HWRM_CFA_FLOW_INFO:
|
||||
case HWRM_CFA_FLOW_FLUSH:
|
||||
case HWRM_CFA_FLOW_STATS:
|
||||
case HWRM_CFA_METER_PROFILE_ALLOC:
|
||||
case HWRM_CFA_METER_PROFILE_FREE:
|
||||
case HWRM_CFA_METER_PROFILE_CFG:
|
||||
case HWRM_CFA_METER_INSTANCE_ALLOC:
|
||||
case HWRM_CFA_METER_INSTANCE_FREE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool bnxt_kong_hwrm_message(struct bnxt *bp, struct input *req)
|
||||
{
|
||||
return (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL &&
|
||||
bnxt_cfa_hwrm_message(le16_to_cpu(req->req_type)));
|
||||
}
|
||||
|
||||
static inline bool bnxt_hwrm_kong_chnl(struct bnxt *bp, struct input *req)
|
||||
{
|
||||
return (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL &&
|
||||
req->resp_addr == cpu_to_le64(bp->hwrm_cmd_kong_resp_dma_addr));
|
||||
}
|
||||
|
||||
static inline void *bnxt_get_hwrm_resp_addr(struct bnxt *bp, void *req)
|
||||
{
|
||||
if (bnxt_hwrm_kong_chnl(bp, (struct input *)req))
|
||||
return bp->hwrm_cmd_kong_resp_addr;
|
||||
else
|
||||
return bp->hwrm_cmd_resp_addr;
|
||||
}
|
||||
|
||||
static inline u16 bnxt_get_hwrm_seq_id(struct bnxt *bp, u16 dst)
|
||||
{
|
||||
u16 seq_id;
|
||||
|
||||
if (dst == BNXT_HWRM_CHNL_CHIMP)
|
||||
seq_id = bp->hwrm_cmd_seq++;
|
||||
else
|
||||
seq_id = bp->hwrm_cmd_kong_seq++;
|
||||
return seq_id;
|
||||
}
|
||||
|
||||
extern const u16 bnxt_lhint_arr[];
|
||||
extern const struct pci_device_id bnxt_pci_tbl[];
|
||||
|
||||
int bnxt_alloc_ctx_pg_tbls(struct bnxt *bp, struct bnxt_ctx_pg_info *ctx_pg,
|
||||
u32 mem_size, u8 depth, bool use_init_val);
|
||||
void bnxt_free_ctx_pg_tbls(struct bnxt *bp, struct bnxt_ctx_pg_info *ctx_pg);
|
||||
int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
|
||||
u16 prod, gfp_t gfp);
|
||||
void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons, void *data);
|
||||
void bnxt_set_tpa_flags(struct bnxt *bp);
|
||||
void bnxt_set_ring_params(struct bnxt *);
|
||||
int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode);
|
||||
void bnxt_hwrm_cmd_hdr_init(struct bnxt *, void *, u16, u16, u16);
|
||||
int _hwrm_send_message(struct bnxt *, void *, u32, int);
|
||||
int _hwrm_send_message_silent(struct bnxt *, void *, u32, int);
|
||||
int hwrm_send_message(struct bnxt *, void *, u32, int);
|
||||
int hwrm_send_message_silent(struct bnxt *, void *, u32, int);
|
||||
int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp, unsigned long *bmap,
|
||||
int bmap_size, bool async_only);
|
||||
void bnxt_del_l2_filter(struct bnxt *bp, struct bnxt_l2_filter *fltr);
|
||||
|
|
@ -2365,6 +2456,7 @@ int bnxt_hwrm_cfa_ntuple_filter_free(struct bnxt *bp,
|
|||
int bnxt_hwrm_cfa_ntuple_filter_alloc(struct bnxt *bp,
|
||||
struct bnxt_ntuple_filter *fltr);
|
||||
void bnxt_fill_ipv6_mask(__be32 mask[4]);
|
||||
int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings);
|
||||
int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id);
|
||||
int __bnxt_hwrm_get_tx_rings(struct bnxt *bp, u16 fid, int *tx_rings);
|
||||
int bnxt_nq_rings_in_use(struct bnxt *bp);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,10 @@
|
|||
#include <net/flow_keys.h>
|
||||
#endif
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <linux/dma-buf.h>
|
||||
#ifdef HAVE_IEEE1588_SUPPORT
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#endif
|
||||
#if defined(HAVE_TC_FLOW_CLS_OFFLOAD) || defined(HAVE_TC_CLS_FLOWER_OFFLOAD)
|
||||
#include <net/pkt_cls.h>
|
||||
#endif
|
||||
|
|
@ -42,8 +45,11 @@
|
|||
|
||||
#if !IS_ENABLED(CONFIG_NET_DEVLINK)
|
||||
#undef HAVE_DEVLINK
|
||||
#undef HAVE_DEVLINK_INFO
|
||||
#undef HAVE_DEVLINK_PARAM
|
||||
#undef HAVE_NDO_DEVLINK_PORT
|
||||
#undef HAVE_DEVLINK_PORT_PARAM
|
||||
#undef HAVE_DEVLINK_FLASH_UPDATE
|
||||
#undef HAVE_DEVLINK_HEALTH_REPORT
|
||||
#endif
|
||||
|
||||
|
|
@ -305,6 +311,29 @@
|
|||
dma_unmap_page(dev, dma_addr, size, dir)
|
||||
#endif
|
||||
|
||||
static inline struct dma_buf *dma_buf_export_attr(void *priv, int pg_count,
|
||||
const struct dma_buf_ops *ops)
|
||||
{
|
||||
#ifdef HAVE_DMA_EXPORT
|
||||
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
||||
|
||||
exp_info.ops = ops;
|
||||
exp_info.size = pg_count << PAGE_SHIFT;
|
||||
exp_info.flags = O_RDWR;
|
||||
exp_info.priv = priv;
|
||||
exp_info.exp_name = "eem_dma_buf";
|
||||
return dma_buf_export(&exp_info);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DMA_EXPORT_FLAG_RESV
|
||||
return dma_buf_export(priv, ops, pg_count << PAGE_SHIFT, O_RDWR, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DMA_EXPORT_FLAG
|
||||
return dma_buf_export(priv, ops, pg_count << PAGE_SHIFT, O_RDWR);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef RHEL_RELEASE_VERSION
|
||||
#define RHEL_RELEASE_VERSION(a, b) 0
|
||||
#endif
|
||||
|
|
@ -343,6 +372,11 @@
|
|||
#define ndo_set_vf_trust extended.ndo_set_vf_trust
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NDO_UDP_TUNNEL_RH
|
||||
#define ndo_udp_tunnel_add extended.ndo_udp_tunnel_add
|
||||
#define ndo_udp_tunnel_del extended.ndo_udp_tunnel_del
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_TC_SETUP_QDISC_MQPRIO
|
||||
#define TC_SETUP_QDISC_MQPRIO TC_SETUP_MQPRIO
|
||||
#endif
|
||||
|
|
@ -402,6 +436,10 @@ struct ethtool_eee {
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ETHTOOL_RESET_CRASHDUMP
|
||||
enum compat_ethtool_reset_flags { ETH_RESET_CRASHDUMP = 1 << 9 };
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SKB_FRAG_PAGE
|
||||
static inline struct page *skb_frag_page(const skb_frag_t *frag)
|
||||
{
|
||||
|
|
@ -494,6 +532,15 @@ skb_set_hash(struct sk_buff *skb, __u32 hash, enum pkt_hash_types type)
|
|||
#undef CONFIG_RFS_ACCEL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
#if !defined(HAVE_FLOW_HASH_FROM_KEYS) && !defined(HAVE_GET_HASH_RAW)
|
||||
static inline __u32 skb_get_hash_raw(const struct sk_buff *skb)
|
||||
{
|
||||
return skb->rxhash;
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_RFS_ACCEL */
|
||||
|
||||
#if !defined(IEEE_8021QAZ_APP_SEL_DGRAM) || !defined(CONFIG_DCB) || !defined(HAVE_IEEE_DELAPP)
|
||||
#undef CONFIG_BNXT_DCB
|
||||
#endif
|
||||
|
|
@ -664,6 +711,23 @@ static inline const char *netdev_name(const struct net_device *dev)
|
|||
dev_warn(dev, format, ##args)
|
||||
#endif
|
||||
|
||||
#ifndef netdev_level_once
|
||||
#define netdev_level_once(level, dev, fmt, ...) \
|
||||
do { \
|
||||
static bool __print_once __read_mostly; \
|
||||
\
|
||||
if (!__print_once) { \
|
||||
__print_once = true; \
|
||||
netdev_printk(level, dev, fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define netdev_info_once(dev, fmt, ...) \
|
||||
netdev_level_once(KERN_INFO, dev, fmt, ##__VA_ARGS__)
|
||||
#define netdev_warn_once(dev, fmt, ...) \
|
||||
netdev_level_once(KERN_WARNING, dev, fmt, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef netdev_uc_count
|
||||
#define netdev_uc_count(dev) ((dev)->uc.count)
|
||||
#endif
|
||||
|
|
@ -698,6 +762,14 @@ static inline const char *netdev_name(const struct net_device *dev)
|
|||
#define writeq_relaxed(v, a) writeq(v, a)
|
||||
#endif
|
||||
|
||||
#ifndef WRITE_ONCE
|
||||
#define WRITE_ONCE(x, val) (x = val)
|
||||
#endif
|
||||
|
||||
#ifndef READ_ONCE
|
||||
#define READ_ONCE(val) (val)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||
#include <net/busy_poll.h>
|
||||
#if defined(HAVE_NAPI_HASH_ADD) && defined(NETDEV_BUSY_POLL)
|
||||
|
|
@ -713,6 +785,21 @@ static inline const char *netdev_name(const struct net_device *dev)
|
|||
#undef HAVE_IEEE1588_SUPPORT
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_PTP_GETTIMEX64)
|
||||
struct ptp_system_timestamp {
|
||||
struct timespec64 pre_ts;
|
||||
struct timespec64 post_ts;
|
||||
};
|
||||
|
||||
static inline void ptp_read_system_prets(struct ptp_system_timestamp *sts)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ptp_read_system_postts(struct ptp_system_timestamp *sts)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(RHEL_RELEASE_CODE) && (RHEL_RELEASE_CODE == RHEL_RELEASE_VERSION(7,0))
|
||||
#undef CONFIG_CRASH_DUMP
|
||||
#endif
|
||||
|
|
@ -873,6 +960,15 @@ static inline int netif_get_num_default_rss_queues(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef IFF_RXFH_CONFIGURED
|
||||
#define IFF_RXFH_CONFIGURED 0
|
||||
#undef HAVE_SET_RXFH
|
||||
static inline bool netif_is_rxfh_configured(const struct net_device *dev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_TCP_V6_CHECK)
|
||||
static __inline__ __sum16 tcp_v6_check(int len,
|
||||
const struct in6_addr *saddr,
|
||||
|
|
@ -943,6 +1039,22 @@ static inline void *kmalloc_array(unsigned n, size_t s, gfp_t gfp)
|
|||
#define ETH_MODULE_SFF_8636_LEN 256
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MSIX_RANGE
|
||||
static inline int
|
||||
pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
|
||||
int minvec, int maxvec)
|
||||
{
|
||||
int rc;
|
||||
|
||||
while (maxvec >= minvec) {
|
||||
rc = pci_enable_msix(dev, entries, maxvec);
|
||||
if (!rc || rc < 0)
|
||||
return rc;
|
||||
maxvec = rc;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_MSIX_RANGE */
|
||||
|
||||
#ifndef HAVE_PCI_PHYSFN
|
||||
static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
|
||||
{
|
||||
|
|
@ -967,16 +1079,23 @@ enum pci_bus_speed {
|
|||
PCIE_SPEED_2_5GT = 0x14,
|
||||
PCIE_SPEED_5_0GT = 0x15,
|
||||
PCIE_SPEED_8_0GT = 0x16,
|
||||
#ifndef PCIE_SPEED_16_0GT
|
||||
PCIE_SPEED_16_0GT = 0x17,
|
||||
#endif
|
||||
PCI_SPEED_UNKNOWN = 0xFF,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef PCIE_SPEED_16_0GT
|
||||
#define PCIE_SPEED_16_0GT 0x17
|
||||
#endif
|
||||
|
||||
static const unsigned char pcie_link_speed[] = {
|
||||
PCI_SPEED_UNKNOWN, /* 0 */
|
||||
PCIE_SPEED_2_5GT, /* 1 */
|
||||
PCIE_SPEED_5_0GT, /* 2 */
|
||||
PCIE_SPEED_8_0GT, /* 3 */
|
||||
PCI_SPEED_UNKNOWN, /* 4 */
|
||||
PCIE_SPEED_16_0GT, /* 4 */
|
||||
PCI_SPEED_UNKNOWN, /* 5 */
|
||||
PCI_SPEED_UNKNOWN, /* 6 */
|
||||
PCI_SPEED_UNKNOWN, /* 7 */
|
||||
|
|
@ -1004,6 +1123,10 @@ static const unsigned char pcie_link_speed[] = {
|
|||
#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x00000008 /* Supported Speed 8GT/s */
|
||||
#endif
|
||||
|
||||
#ifndef PCI_EXP_LNKCAP2_SLS_16_0GB
|
||||
#define PCI_EXP_LNKCAP2_SLS_16_0GB 0x00000010 /* Supported Speed 16GT/s */
|
||||
#endif
|
||||
|
||||
#ifndef PCI_EXP_LNKCAP_SLS_2_5GB
|
||||
#define PCI_EXP_LNKCAP_SLS_2_5GB 0x00000001 /* LNKCAP2 SLS Vector bit 0*/
|
||||
#define PCI_EXP_LNKCAP_SLS_5_0GB 0x00000002 /* LNKCAP2 SLS Vector bit 1*/
|
||||
|
|
@ -1013,17 +1136,23 @@ static const unsigned char pcie_link_speed[] = {
|
|||
#define PCI_EXP_LNKCAP_SLS_8_0GB 0x00000003 /* LNKCAP2 SLS Vector bit2 */
|
||||
#endif
|
||||
|
||||
#ifndef PCI_EXP_LNKCAP_SLS_16_0GB
|
||||
#define PCI_EXP_LNKCAP_SLS_16_0GB 0x00000004 /* LNKCAP2 SLS Vector bit 3 */
|
||||
#endif
|
||||
|
||||
#ifndef PCIE_SPEED2STR
|
||||
/* PCIe link information */
|
||||
#define PCIE_SPEED2STR(speed) \
|
||||
((speed) == PCIE_SPEED_8_0GT ? "8 GT/s" : \
|
||||
((speed) == PCIE_SPEED_16_0GT ? "16 GT/s" : \
|
||||
(speed) == PCIE_SPEED_8_0GT ? "8 GT/s" : \
|
||||
(speed) == PCIE_SPEED_5_0GT ? "5 GT/s" : \
|
||||
(speed) == PCIE_SPEED_2_5GT ? "2.5 GT/s" : \
|
||||
"Unknown speed")
|
||||
|
||||
/* PCIe speed to Mb/s reduced by encoding overhead */
|
||||
#define PCIE_SPEED2MBS_ENC(speed) \
|
||||
((speed) == PCIE_SPEED_8_0GT ? 8000 * 128 / 130 : \
|
||||
((speed) == PCIE_SPEED_16_0GT ? 16000 * 128 / 130 : \
|
||||
(speed) == PCIE_SPEED_8_0GT ? 8000 * 128 / 130 : \
|
||||
(speed) == PCIE_SPEED_5_0GT ? 5000 * 8 / 10 : \
|
||||
(speed) == PCIE_SPEED_2_5GT ? 2500 * 8 / 10 : \
|
||||
0)
|
||||
|
|
@ -1114,7 +1243,9 @@ static enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)
|
|||
pci_read_config_word(dev, BNXT_PCIE_CAP + PCI_EXP_LNKCAP2, &lnkcap2);
|
||||
#endif
|
||||
if (lnkcap2) { /* PCIe r3.0-compliant */
|
||||
if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB)
|
||||
if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_16_0GB)
|
||||
return PCIE_SPEED_16_0GT;
|
||||
else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB)
|
||||
return PCIE_SPEED_8_0GT;
|
||||
else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB)
|
||||
return PCIE_SPEED_5_0GT;
|
||||
|
|
@ -1129,7 +1260,9 @@ static enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)
|
|||
pci_read_config_word(dev, BNXT_PCIE_CAP + PCI_EXP_LNKCAP, &lnkcap);
|
||||
#endif
|
||||
if (lnkcap) {
|
||||
if (lnkcap & PCI_EXP_LNKCAP_SLS_8_0GB)
|
||||
if (lnkcap & PCI_EXP_LNKCAP_SLS_16_0GB)
|
||||
return PCIE_SPEED_16_0GT;
|
||||
else if (lnkcap & PCI_EXP_LNKCAP_SLS_8_0GB)
|
||||
return PCIE_SPEED_8_0GT;
|
||||
else if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB)
|
||||
return PCIE_SPEED_5_0GT;
|
||||
|
|
@ -1204,6 +1337,32 @@ static inline bool pci_is_bridge(struct pci_dev *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_PCI_GET_DSN
|
||||
static inline u64 pci_get_dsn(struct pci_dev *dev)
|
||||
{
|
||||
u32 dword;
|
||||
u64 dsn;
|
||||
int pos;
|
||||
|
||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DSN);
|
||||
if (!pos)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The Device Serial Number is two dwords offset 4 bytes from the
|
||||
* capability position. The specification says that the first dword is
|
||||
* the lower half, and the second dword is the upper half.
|
||||
*/
|
||||
pos += 4;
|
||||
pci_read_config_dword(dev, pos, &dword);
|
||||
dsn = (u64)dword;
|
||||
pci_read_config_dword(dev, pos + 4, &dword);
|
||||
dsn |= ((u64)dword) << 32;
|
||||
|
||||
return dsn;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_NDO_XDP
|
||||
struct netdev_bpf;
|
||||
struct xdp_buff;
|
||||
|
|
@ -1504,16 +1663,112 @@ static inline void devlink_flash_update_status_notify(struct devlink *devlink,
|
|||
#define DEVLINK_INFO_VERSION_GENERIC_ASIC_REV "asic.rev"
|
||||
#define DEVLINK_INFO_VERSION_GENERIC_FW "fw"
|
||||
#endif
|
||||
#ifndef DEVLINK_INFO_VERSION_GENERIC_FW_MGMT
|
||||
#define DEVLINK_INFO_VERSION_GENERIC_FW_MGMT "fw.mgmt"
|
||||
#endif
|
||||
#ifndef DEVLINK_INFO_VERSION_GENERIC_FW_APP
|
||||
#define DEVLINK_INFO_VERSION_GENERIC_FW_APP "fw.app"
|
||||
#endif
|
||||
#ifndef DEVLINK_INFO_VERSION_GENERIC_FW_PSID
|
||||
#define DEVLINK_INFO_VERSION_GENERIC_FW_PSID "fw.psid"
|
||||
#endif
|
||||
#ifndef DEVLINK_INFO_VERSION_GENERIC_FW_ROCE
|
||||
#define DEVLINK_INFO_VERSION_GENERIC_FW_ROCE "fw.roce"
|
||||
#endif
|
||||
#ifndef DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API
|
||||
#define DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API "fw.mgmt.api"
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_DEVLINK_INFO_BSN_PUT
|
||||
static inline int devlink_info_board_serial_number_put(struct devlink_info_req *req,
|
||||
const char *bsn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_DEVLINK_INFO */
|
||||
|
||||
#ifndef HAVE_PCIE_FLR
|
||||
static inline int pcie_flr(struct pci_dev *dev)
|
||||
{
|
||||
pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
|
||||
|
||||
msleep(100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* pcie_flr */
|
||||
|
||||
#if defined(HAVE_FLOW_OFFLOAD_H) && \
|
||||
!defined(HAVE_FLOW_ACTION_BASIC_HW_STATS_CHECK)
|
||||
static inline bool
|
||||
flow_action_basic_hw_stats_check(const struct flow_action *action,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#define flow_stats_update(flow_stats, bytes, pkts, last_used, used_hw_stats) \
|
||||
flow_stats_update(flow_stats, bytes, pkts, last_used)
|
||||
#endif
|
||||
|
||||
#ifndef fallthrough
|
||||
#define fallthrough do {} while (0) /* fall through */
|
||||
#endif
|
||||
|
||||
#ifndef __ALIGN_KERNEL_MASK
|
||||
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
|
||||
#endif
|
||||
#ifndef __ALIGN_KERNEL
|
||||
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
|
||||
#endif
|
||||
#ifndef ALIGN_DOWN
|
||||
#define ALIGN_DOWN(x, a) __ALIGN_KERNEL((x) - ((a) - 1), (a))
|
||||
#endif
|
||||
|
||||
struct bnxt_compat_dma_pool {
|
||||
struct dma_pool *pool;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static inline struct bnxt_compat_dma_pool*
|
||||
bnxt_compat_dma_pool_create(const char *name, struct device *dev, size_t size,
|
||||
size_t align, size_t allocation)
|
||||
{
|
||||
struct bnxt_compat_dma_pool *wrapper;
|
||||
|
||||
wrapper = kmalloc_node(sizeof(*wrapper), GFP_KERNEL, dev_to_node(dev));
|
||||
if (!wrapper)
|
||||
return NULL;
|
||||
|
||||
wrapper->pool = dma_pool_create(name, dev, size, align, allocation);
|
||||
wrapper->size = size;
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
static inline void
|
||||
bnxt_compat_dma_pool_destroy(struct bnxt_compat_dma_pool *wrapper)
|
||||
{
|
||||
dma_pool_destroy(wrapper->pool);
|
||||
kfree(wrapper);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
bnxt_compat_dma_pool_alloc(struct bnxt_compat_dma_pool *wrapper,
|
||||
gfp_t mem_flags, dma_addr_t *handle)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
mem = dma_pool_alloc(wrapper->pool, mem_flags & ~__GFP_ZERO, handle);
|
||||
if (mem_flags & __GFP_ZERO)
|
||||
memset(mem, 0, wrapper->size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
static inline void
|
||||
bnxt_compat_dma_pool_free(struct bnxt_compat_dma_pool *wrapper, void *vaddr,
|
||||
dma_addr_t addr)
|
||||
{
|
||||
dma_pool_free(wrapper->pool, vaddr, addr);
|
||||
}
|
||||
|
||||
#define dma_pool_create bnxt_compat_dma_pool_create
|
||||
#define dma_pool_destroy bnxt_compat_dma_pool_destroy
|
||||
#define dma_pool_alloc bnxt_compat_dma_pool_alloc
|
||||
#define dma_pool_free bnxt_compat_dma_pool_free
|
||||
#define dma_pool bnxt_compat_dma_pool
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/log2.h>
|
||||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_hwrm.h"
|
||||
#include "bnxt_dcb.h"
|
||||
|
||||
#ifdef CONFIG_BNXT_DCB
|
||||
|
|
@ -38,38 +40,42 @@ static int bnxt_queue_to_tc(struct bnxt *bp, u8 queue_id)
|
|||
|
||||
static int bnxt_hwrm_queue_pri2cos_cfg(struct bnxt *bp, struct ieee_ets *ets)
|
||||
{
|
||||
struct hwrm_queue_pri2cos_cfg_input req = {0};
|
||||
struct hwrm_queue_pri2cos_cfg_input *req;
|
||||
u8 *pri2cos;
|
||||
int i;
|
||||
int rc, i;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_CFG, -1, -1);
|
||||
req.flags = cpu_to_le32(QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_BIDIR |
|
||||
QUEUE_PRI2COS_CFG_REQ_FLAGS_IVLAN);
|
||||
rc = hwrm_req_init(bp, req, HWRM_QUEUE_PRI2COS_CFG);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pri2cos = &req.pri0_cos_queue_id;
|
||||
req->flags = cpu_to_le32(QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_BIDIR |
|
||||
QUEUE_PRI2COS_CFG_REQ_FLAGS_IVLAN);
|
||||
|
||||
pri2cos = &req->pri0_cos_queue_id;
|
||||
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
|
||||
u8 qidx;
|
||||
|
||||
req.enables |= cpu_to_le32(
|
||||
QUEUE_PRI2COS_CFG_REQ_ENABLES_PRI0_COS_QUEUE_ID << i);
|
||||
req->enables |= cpu_to_le32(QUEUE_PRI2COS_CFG_REQ_ENABLES_PRI0_COS_QUEUE_ID << i);
|
||||
|
||||
qidx = bp->tc_to_qidx[ets->prio_tc[i]];
|
||||
pri2cos[i] = bp->q_info[qidx].queue_id;
|
||||
}
|
||||
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
return hwrm_req_send(bp, req);
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt *bp, struct ieee_ets *ets)
|
||||
{
|
||||
struct hwrm_queue_pri2cos_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
struct hwrm_queue_pri2cos_qcfg_input req = {0};
|
||||
int rc = 0;
|
||||
struct hwrm_queue_pri2cos_qcfg_output *resp;
|
||||
struct hwrm_queue_pri2cos_qcfg_input *req;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_QCFG, -1, -1);
|
||||
req.flags = cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN);
|
||||
rc = hwrm_req_init(bp, req, HWRM_QUEUE_PRI2COS_QCFG);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
req->flags = cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN);
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
if (!rc) {
|
||||
u8 *pri2cos = &resp->pri0_cos_queue_id;
|
||||
int i;
|
||||
|
|
@ -83,25 +89,27 @@ static int bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt *bp, struct ieee_ets *ets)
|
|||
ets->prio_tc[i] = tc;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets,
|
||||
u8 max_tc)
|
||||
{
|
||||
struct hwrm_queue_cos2bw_cfg_input req = {0};
|
||||
struct hwrm_queue_cos2bw_cfg_input *req;
|
||||
struct bnxt_cos2bw_cfg cos2bw;
|
||||
void *data;
|
||||
int i;
|
||||
int rc, i;
|
||||
|
||||
rc = hwrm_req_init(bp, req, HWRM_QUEUE_COS2BW_CFG);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_CFG, -1, -1);
|
||||
for (i = 0; i < max_tc; i++) {
|
||||
u8 qidx = bp->tc_to_qidx[i];
|
||||
|
||||
req.enables |= cpu_to_le32(
|
||||
QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID0_VALID <<
|
||||
qidx);
|
||||
req->enables |=
|
||||
cpu_to_le32(QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID0_VALID << qidx);
|
||||
|
||||
memset(&cos2bw, 0, sizeof(cos2bw));
|
||||
cos2bw.queue_id = bp->q_info[qidx].queue_id;
|
||||
|
|
@ -120,30 +128,32 @@ static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets,
|
|||
cpu_to_le32((ets->tc_tx_bw[i] * 100) |
|
||||
BW_VALUE_UNIT_PERCENT1_100);
|
||||
}
|
||||
data = &req.unused_0 + qidx * (sizeof(cos2bw) - 4);
|
||||
data = &req->unused_0 + qidx * (sizeof(cos2bw) - 4);
|
||||
memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4);
|
||||
if (qidx == 0) {
|
||||
req.queue_id0 = cos2bw.queue_id;
|
||||
req.unused_0 = 0;
|
||||
req->queue_id0 = cos2bw.queue_id;
|
||||
req->unused_0 = 0;
|
||||
}
|
||||
}
|
||||
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
return hwrm_req_send(bp, req);
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets)
|
||||
{
|
||||
struct hwrm_queue_cos2bw_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
struct hwrm_queue_cos2bw_qcfg_input req = {0};
|
||||
struct hwrm_queue_cos2bw_qcfg_output *resp;
|
||||
struct hwrm_queue_cos2bw_qcfg_input *req;
|
||||
struct bnxt_cos2bw_cfg cos2bw;
|
||||
void *data;
|
||||
int rc, i;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_QCFG, -1, -1);
|
||||
rc = hwrm_req_init(bp, req, HWRM_QUEUE_COS2BW_QCFG);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
if (rc) {
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +177,7 @@ static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets)
|
|||
ets->tc_tx_bw[tc] = cos2bw.bw_weight;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -229,11 +239,12 @@ static int bnxt_queue_remap(struct bnxt *bp, unsigned int lltc_mask)
|
|||
|
||||
static int bnxt_hwrm_queue_pfc_cfg(struct bnxt *bp, struct ieee_pfc *pfc)
|
||||
{
|
||||
struct hwrm_queue_pfcenable_cfg_input req = {0};
|
||||
struct hwrm_queue_pfcenable_cfg_input *req;
|
||||
struct ieee_ets *my_ets = bp->ieee_ets;
|
||||
unsigned int tc_mask = 0, pri_mask = 0;
|
||||
u8 i, pri, lltc_count = 0;
|
||||
bool need_q_remap = false;
|
||||
int rc;
|
||||
|
||||
if (!my_ets)
|
||||
return -EINVAL;
|
||||
|
|
@ -266,38 +277,43 @@ static int bnxt_hwrm_queue_pfc_cfg(struct bnxt *bp, struct ieee_pfc *pfc)
|
|||
if (need_q_remap)
|
||||
bnxt_queue_remap(bp, tc_mask);
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_CFG, -1, -1);
|
||||
req.flags = cpu_to_le32(pri_mask);
|
||||
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
rc = hwrm_req_init(bp, req, HWRM_QUEUE_PFCENABLE_CFG);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
req->flags = cpu_to_le32(pri_mask);
|
||||
return hwrm_req_send(bp, req);
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_pfc_qcfg(struct bnxt *bp, struct ieee_pfc *pfc)
|
||||
{
|
||||
struct hwrm_queue_pfcenable_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
struct hwrm_queue_pfcenable_qcfg_input req = {0};
|
||||
struct hwrm_queue_pfcenable_qcfg_output *resp;
|
||||
struct hwrm_queue_pfcenable_qcfg_input *req;
|
||||
u8 pri_mask;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_QCFG, -1, -1);
|
||||
rc = hwrm_req_init(bp, req, HWRM_QUEUE_PFCENABLE_QCFG);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
if (rc) {
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pri_mask = le32_to_cpu(resp->flags);
|
||||
pfc->pfc_en = pri_mask;
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app,
|
||||
bool add)
|
||||
{
|
||||
struct hwrm_fw_set_structured_data_input set = {0};
|
||||
struct hwrm_fw_get_structured_data_input get = {0};
|
||||
struct hwrm_fw_set_structured_data_input *set;
|
||||
struct hwrm_fw_get_structured_data_input *get;
|
||||
struct hwrm_struct_data_dcbx_app *fw_app;
|
||||
struct hwrm_struct_hdr *data;
|
||||
dma_addr_t mapping;
|
||||
|
|
@ -307,19 +323,26 @@ static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app,
|
|||
if (bp->hwrm_spec_code < 0x10601)
|
||||
return 0;
|
||||
|
||||
rc = hwrm_req_init(bp, get, HWRM_FW_GET_STRUCTURED_DATA);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
hwrm_req_hold(bp, get);
|
||||
hwrm_req_alloc_flags(bp, get, GFP_KERNEL | __GFP_ZERO);
|
||||
|
||||
n = IEEE_8021QAZ_MAX_TCS;
|
||||
data_len = sizeof(*data) + sizeof(*fw_app) * n;
|
||||
data = dma_zalloc_coherent(&bp->pdev->dev, data_len, &mapping,
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
data = hwrm_req_dma_slice(bp, get, data_len, &mapping);
|
||||
if (!data) {
|
||||
rc = -ENOMEM;
|
||||
goto set_app_exit;
|
||||
}
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &get, HWRM_FW_GET_STRUCTURED_DATA, -1, -1);
|
||||
get.dest_data_addr = cpu_to_le64(mapping);
|
||||
get.structure_id = cpu_to_le16(STRUCT_HDR_STRUCT_ID_DCBX_APP);
|
||||
get.subtype = cpu_to_le16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
|
||||
get.count = 0;
|
||||
rc = hwrm_send_message(bp, &get, sizeof(get), HWRM_CMD_TIMEOUT);
|
||||
get->dest_data_addr = cpu_to_le64(mapping);
|
||||
get->structure_id = cpu_to_le16(STRUCT_HDR_STRUCT_ID_DCBX_APP);
|
||||
get->subtype = cpu_to_le16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
|
||||
get->count = 0;
|
||||
rc = hwrm_req_send(bp, get);
|
||||
if (rc)
|
||||
goto set_app_exit;
|
||||
|
||||
|
|
@ -365,44 +388,49 @@ static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app,
|
|||
data->len = cpu_to_le16(sizeof(*fw_app) * n);
|
||||
data->subtype = cpu_to_le16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &set, HWRM_FW_SET_STRUCTURED_DATA, -1, -1);
|
||||
set.src_data_addr = cpu_to_le64(mapping);
|
||||
set.data_len = cpu_to_le16(sizeof(*data) + sizeof(*fw_app) * n);
|
||||
set.hdr_cnt = 1;
|
||||
rc = hwrm_send_message(bp, &set, sizeof(set), HWRM_CMD_TIMEOUT);
|
||||
rc = hwrm_req_init(bp, set, HWRM_FW_SET_STRUCTURED_DATA);
|
||||
if (rc)
|
||||
goto set_app_exit;
|
||||
|
||||
set->src_data_addr = cpu_to_le64(mapping);
|
||||
set->data_len = cpu_to_le16(sizeof(*data) + sizeof(*fw_app) * n);
|
||||
set->hdr_cnt = 1;
|
||||
rc = hwrm_req_send(bp, set);
|
||||
|
||||
set_app_exit:
|
||||
dma_free_coherent(&bp->pdev->dev, data_len, data, mapping);
|
||||
hwrm_req_drop(bp, get); /* dropping get request and associated slice */
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_dscp_qcaps(struct bnxt *bp)
|
||||
{
|
||||
struct hwrm_queue_dscp_qcaps_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
struct hwrm_queue_dscp_qcaps_input req = {0};
|
||||
struct hwrm_queue_dscp_qcaps_output *resp;
|
||||
struct hwrm_queue_dscp_qcaps_input *req;
|
||||
int rc;
|
||||
|
||||
bp->max_dscp_value = 0;
|
||||
if (bp->hwrm_spec_code < 0x10800 || BNXT_VF(bp))
|
||||
return 0;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_DSCP_QCAPS, -1, -1);
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
rc = hwrm_req_init(bp, req, HWRM_QUEUE_DSCP_QCAPS);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send_silent(bp, req);
|
||||
if (!rc) {
|
||||
bp->max_dscp_value = (1 << resp->num_dscp_bits) - 1;
|
||||
if (bp->max_dscp_value < 0x3f)
|
||||
bp->max_dscp_value = 0;
|
||||
}
|
||||
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt *bp, struct dcb_app *app,
|
||||
bool add)
|
||||
{
|
||||
struct hwrm_queue_dscp2pri_cfg_input req = {0};
|
||||
struct hwrm_queue_dscp2pri_cfg_input *req;
|
||||
struct bnxt_dscp2pri_entry *dscp2pri;
|
||||
dma_addr_t mapping;
|
||||
int rc;
|
||||
|
|
@ -410,23 +438,25 @@ static int bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt *bp, struct dcb_app *app,
|
|||
if (bp->hwrm_spec_code < 0x10800)
|
||||
return 0;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_DSCP2PRI_CFG, -1, -1);
|
||||
dscp2pri = dma_alloc_coherent(&bp->pdev->dev, sizeof(*dscp2pri),
|
||||
&mapping, GFP_KERNEL);
|
||||
if (!dscp2pri)
|
||||
return -ENOMEM;
|
||||
rc = hwrm_req_init(bp, req, HWRM_QUEUE_DSCP2PRI_CFG);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
req.src_data_addr = cpu_to_le64(mapping);
|
||||
dscp2pri = hwrm_req_dma_slice(bp, req, sizeof(*dscp2pri), &mapping);
|
||||
if (!dscp2pri) {
|
||||
hwrm_req_drop(bp, req);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
req->src_data_addr = cpu_to_le64(mapping);
|
||||
dscp2pri->dscp = app->protocol;
|
||||
if (add)
|
||||
dscp2pri->mask = 0x3f;
|
||||
else
|
||||
dscp2pri->mask = 0;
|
||||
dscp2pri->pri = app->priority;
|
||||
req.entry_cnt = cpu_to_le16(1);
|
||||
rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
dma_free_coherent(&bp->pdev->dev, sizeof(*dscp2pri), dscp2pri,
|
||||
mapping);
|
||||
req->entry_cnt = cpu_to_le16(1);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -472,24 +502,26 @@ static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets)
|
|||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
struct ieee_ets *my_ets = bp->ieee_ets;
|
||||
int rc;
|
||||
|
||||
ets->ets_cap = bp->max_tc;
|
||||
|
||||
if (!my_ets) {
|
||||
int rc;
|
||||
|
||||
if (bp->dcbx_cap & DCB_CAP_DCBX_HOST)
|
||||
return 0;
|
||||
|
||||
my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL);
|
||||
if (!my_ets)
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
rc = bnxt_hwrm_queue_cos2bw_qcfg(bp, my_ets);
|
||||
if (rc)
|
||||
return 0;
|
||||
goto error;
|
||||
rc = bnxt_hwrm_queue_pri2cos_qcfg(bp, my_ets);
|
||||
if (rc)
|
||||
return 0;
|
||||
goto error;
|
||||
|
||||
/* cache result */
|
||||
bp->ieee_ets = my_ets;
|
||||
}
|
||||
|
||||
ets->cbs = my_ets->cbs;
|
||||
|
|
@ -498,6 +530,9 @@ static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets)
|
|||
memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
|
||||
memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
|
||||
return 0;
|
||||
error:
|
||||
kfree(my_ets);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)
|
||||
|
|
@ -539,7 +574,7 @@ static int bnxt_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)
|
|||
static int bnxt_dcbnl_ieee_getpfc(struct net_device *dev, struct ieee_pfc *pfc)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
__le64 *stats = (__le64 *)bp->hw_rx_port_stats;
|
||||
__le64 *stats = bp->port_stats.hw_stats;
|
||||
struct ieee_pfc *my_pfc = bp->ieee_pfc;
|
||||
long rx_off, tx_off;
|
||||
int i, rc;
|
||||
|
|
@ -667,6 +702,59 @@ static int bnxt_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void __bnxt_del_roce_app(struct bnxt *bp, struct dcb_app *app)
|
||||
{
|
||||
u32 prio_mask = dcb_ieee_getapp_mask(bp->dev, app);
|
||||
|
||||
if (!prio_mask)
|
||||
return;
|
||||
|
||||
app->priority = ilog2(prio_mask);
|
||||
dcb_ieee_delapp(bp->dev, app);
|
||||
}
|
||||
|
||||
static void bnxt_del_roce_apps(struct bnxt *bp)
|
||||
{
|
||||
struct dcb_app app;
|
||||
|
||||
if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
|
||||
!(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
|
||||
return;
|
||||
|
||||
app.selector = IEEE_8021QAZ_APP_SEL_ETHERTYPE;
|
||||
app.protocol = ETH_P_ROCE;
|
||||
__bnxt_del_roce_app(bp, &app);
|
||||
|
||||
app.selector = IEEE_8021QAZ_APP_SEL_DGRAM;
|
||||
app.protocol = ROCE_V2_UDP_DPORT;
|
||||
__bnxt_del_roce_app(bp, &app);
|
||||
}
|
||||
|
||||
static void bnxt_del_dscp_apps(struct bnxt *bp)
|
||||
{
|
||||
#ifdef HAVE_DSCP_MASK_MAP
|
||||
struct dcb_ieee_app_prio_map dscp_map;
|
||||
struct dcb_app app;
|
||||
int i, j;
|
||||
|
||||
if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
|
||||
!(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
|
||||
return;
|
||||
|
||||
app.selector = IEEE_8021QAZ_APP_SEL_DSCP;
|
||||
dcb_ieee_getapp_prio_dscp_mask_map(bp->dev, &dscp_map);
|
||||
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
|
||||
for (j = 0; j < 64; j++) {
|
||||
if (dscp_map.map[i] & (1ULL << j)) {
|
||||
app.protocol = j;
|
||||
app.priority = i;
|
||||
dcb_ieee_delapp(bp->dev, &app);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static u8 bnxt_dcbnl_getdcbx(struct net_device *dev)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
|
|
@ -725,12 +813,16 @@ void bnxt_dcb_init(struct bnxt *bp)
|
|||
bp->dev->dcbnl_ops = &dcbnl_ops;
|
||||
}
|
||||
|
||||
void bnxt_dcb_free(struct bnxt *bp)
|
||||
void bnxt_dcb_free(struct bnxt *bp, bool reset)
|
||||
{
|
||||
kfree(bp->ieee_pfc);
|
||||
kfree(bp->ieee_ets);
|
||||
bp->ieee_pfc = NULL;
|
||||
bp->ieee_ets = NULL;
|
||||
if (reset) {
|
||||
bnxt_del_roce_apps(bp);
|
||||
bnxt_del_dscp_apps(bp);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
@ -739,7 +831,7 @@ void bnxt_dcb_init(struct bnxt *bp)
|
|||
{
|
||||
}
|
||||
|
||||
void bnxt_dcb_free(struct bnxt *bp)
|
||||
void bnxt_dcb_free(struct bnxt *bp, bool reset)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,6 @@ struct bnxt_dscp2pri_entry {
|
|||
|
||||
#define HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL 0x0300
|
||||
|
||||
void bnxt_dcb_init(struct bnxt *);
|
||||
void bnxt_dcb_free(struct bnxt *);
|
||||
void bnxt_dcb_init(struct bnxt *bp);
|
||||
void bnxt_dcb_free(struct bnxt *bp, bool reset);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_hwrm.h"
|
||||
#include "bnxt_vfr.h"
|
||||
#include "bnxt_devlink.h"
|
||||
#include "bnxt_ethtool.h"
|
||||
|
|
@ -25,25 +26,36 @@ static void bnxt_copy_from_nvm_data(union devlink_param_value *dst,
|
|||
union bnxt_nvm_data *src,
|
||||
int nvm_num_bits, int dl_num_bytes);
|
||||
|
||||
static int bnxt_hwrm_get_nvm_cfg_ver(struct bnxt *bp,
|
||||
union devlink_param_value *nvm_cfg_ver)
|
||||
static int bnxt_hwrm_nvm_get_var(struct bnxt *bp, dma_addr_t data_dma_addr,
|
||||
u16 offset, u16 num_bits)
|
||||
{
|
||||
struct hwrm_nvm_get_variable_input *req;
|
||||
int rc;
|
||||
|
||||
rc = hwrm_req_init(bp, req, HWRM_NVM_GET_VARIABLE);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
req->dest_data_addr = cpu_to_le64(data_dma_addr);
|
||||
req->option_num = cpu_to_le16(offset);
|
||||
req->data_len = cpu_to_le16(num_bits);
|
||||
return hwrm_req_send_silent(bp, req);
|
||||
}
|
||||
|
||||
static int bnxt_get_nvm_cfg_ver(struct bnxt *bp,
|
||||
union devlink_param_value *nvm_cfg_ver)
|
||||
{
|
||||
struct hwrm_nvm_get_variable_input req = {0};
|
||||
union bnxt_nvm_data *data;
|
||||
dma_addr_t data_dma_addr;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_VARIABLE, -1, -1);
|
||||
data = dma_zalloc_coherent(&bp->pdev->dev, sizeof(*data),
|
||||
&data_dma_addr, GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
req.dest_data_addr = cpu_to_le64(data_dma_addr);
|
||||
req.data_len = cpu_to_le16(BNXT_NVM_CFG_VER_BITS);
|
||||
req.option_num = cpu_to_le16(NVM_OFF_NVM_CFG_VER);
|
||||
|
||||
rc = hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
rc = bnxt_hwrm_nvm_get_var(bp, data_dma_addr, NVM_OFF_NVM_CFG_VER,
|
||||
BNXT_NVM_CFG_VER_BITS);
|
||||
if (!rc)
|
||||
bnxt_copy_from_nvm_data(nvm_cfg_ver, data,
|
||||
BNXT_NVM_CFG_VER_BITS,
|
||||
|
|
@ -69,6 +81,20 @@ static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (strlen(bp->board_partno)) {
|
||||
rc = devlink_info_version_fixed_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
|
||||
bp->board_partno);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (strlen(bp->board_serialno)) {
|
||||
rc = devlink_info_board_serial_number_put(req, bp->board_serialno);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
sprintf(buf, "%X", bp->chip_num);
|
||||
rc = devlink_info_version_fixed_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf);
|
||||
|
|
@ -91,6 +117,13 @@ static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
|
|||
return rc;
|
||||
}
|
||||
|
||||
if (strlen(bp->board_serialno)) {
|
||||
rc = devlink_info_version_fixed_put(req, "vpd.serialno",
|
||||
bp->board_serialno);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (strlen(ver_resp->active_pkg_name)) {
|
||||
rc =
|
||||
devlink_info_version_running_put(req,
|
||||
|
|
@ -100,7 +133,7 @@ static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
|
|||
return rc;
|
||||
}
|
||||
|
||||
if (BNXT_PF(bp) && !bnxt_hwrm_get_nvm_cfg_ver(bp, &nvm_cfg_ver)) {
|
||||
if (BNXT_PF(bp) && !bnxt_get_nvm_cfg_ver(bp, &nvm_cfg_ver)) {
|
||||
u32 ver = nvm_cfg_ver.vu32;
|
||||
|
||||
sprintf(buf, "%X.%X.%X", (ver >> 16) & 0xF, (ver >> 8) & 0xF,
|
||||
|
|
@ -137,13 +170,19 @@ static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
|
|||
ver_resp->roce_fw_bld_8b, ver_resp->roce_fw_rsvd_8b);
|
||||
}
|
||||
rc = devlink_info_version_running_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW_APP, fw_ver);
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, fw_ver);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = devlink_info_version_running_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
|
||||
bp->hwrm_ver_supp);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!(bp->flags & BNXT_FLAG_CHIP_P5)) {
|
||||
rc = devlink_info_version_running_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, mgmt_ver);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -288,6 +327,27 @@ struct devlink_health_reporter_ops bnxt_dl_fw_fatal_reporter_ops = {
|
|||
.recover = bnxt_fw_fatal_recover,
|
||||
};
|
||||
|
||||
static struct devlink_health_reporter *
|
||||
__bnxt_dl_reporter_create(struct bnxt *bp,
|
||||
const struct devlink_health_reporter_ops *ops)
|
||||
{
|
||||
struct devlink_health_reporter *reporter;
|
||||
|
||||
#ifndef HAVE_DEVLINK_HEALTH_AUTO_RECOVER
|
||||
reporter = devlink_health_reporter_create(bp->dl, ops, 0, bp);
|
||||
#else
|
||||
reporter = devlink_health_reporter_create(bp->dl, ops, 0,
|
||||
!!ops->recover, bp);
|
||||
#endif
|
||||
if (IS_ERR(reporter)) {
|
||||
netdev_warn(bp->dev, "Failed to create %s health reporter, rc = %ld\n",
|
||||
ops->name, PTR_ERR(reporter));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return reporter;
|
||||
}
|
||||
|
||||
void bnxt_dl_fw_reporters_create(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_fw_health *health = bp->fw_health;
|
||||
|
|
@ -299,15 +359,9 @@ void bnxt_dl_fw_reporters_create(struct bnxt *bp)
|
|||
goto err_recovery;
|
||||
|
||||
health->fw_reset_reporter =
|
||||
devlink_health_reporter_create(bp->dl,
|
||||
&bnxt_dl_fw_reset_reporter_ops,
|
||||
0, true, bp);
|
||||
if (IS_ERR(health->fw_reset_reporter)) {
|
||||
netdev_warn(bp->dev, "Failed to create FW reset health reporter, rc = %ld\n",
|
||||
PTR_ERR(health->fw_reset_reporter));
|
||||
health->fw_reset_reporter = NULL;
|
||||
__bnxt_dl_reporter_create(bp, &bnxt_dl_fw_reset_reporter_ops);
|
||||
if (!health->fw_reset_reporter)
|
||||
bp->fw_cap &= ~BNXT_FW_CAP_HOT_RESET;
|
||||
}
|
||||
|
||||
err_recovery:
|
||||
if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY))
|
||||
|
|
@ -315,13 +369,8 @@ err_recovery:
|
|||
|
||||
if (!health->fw_reporter) {
|
||||
health->fw_reporter =
|
||||
devlink_health_reporter_create(bp->dl,
|
||||
&bnxt_dl_fw_reporter_ops,
|
||||
0, false, bp);
|
||||
if (IS_ERR(health->fw_reporter)) {
|
||||
netdev_warn(bp->dev, "Failed to create FW health reporter, rc = %ld\n",
|
||||
PTR_ERR(health->fw_reporter));
|
||||
health->fw_reporter = NULL;
|
||||
__bnxt_dl_reporter_create(bp, &bnxt_dl_fw_reporter_ops);
|
||||
if (!health->fw_reporter) {
|
||||
bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
|
||||
return;
|
||||
}
|
||||
|
|
@ -331,15 +380,9 @@ err_recovery:
|
|||
return;
|
||||
|
||||
health->fw_fatal_reporter =
|
||||
devlink_health_reporter_create(bp->dl,
|
||||
&bnxt_dl_fw_fatal_reporter_ops,
|
||||
0, true, bp);
|
||||
if (IS_ERR(health->fw_fatal_reporter)) {
|
||||
netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n",
|
||||
PTR_ERR(health->fw_fatal_reporter));
|
||||
health->fw_fatal_reporter = NULL;
|
||||
__bnxt_dl_reporter_create(bp, &bnxt_dl_fw_fatal_reporter_ops);
|
||||
if (!health->fw_fatal_reporter)
|
||||
bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
|
||||
}
|
||||
}
|
||||
|
||||
void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all)
|
||||
|
|
@ -517,17 +560,20 @@ static void bnxt_copy_from_nvm_data(union devlink_param_value *dst,
|
|||
}
|
||||
|
||||
static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
|
||||
int msg_len, union devlink_param_value *val)
|
||||
union devlink_param_value *val)
|
||||
{
|
||||
struct hwrm_nvm_get_variable_input *req = msg;
|
||||
struct bnxt_dl_nvm_param nvm_param;
|
||||
struct hwrm_err_output *resp;
|
||||
union bnxt_nvm_data *data;
|
||||
dma_addr_t data_dma_addr;
|
||||
int idx = 0, rc, i;
|
||||
|
||||
/* Get/Set NVM CFG parameter is supported only on PFs */
|
||||
if (BNXT_VF(bp))
|
||||
if (BNXT_VF(bp)) {
|
||||
hwrm_req_drop(bp, req);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(nvm_params); i++) {
|
||||
if (nvm_params[i].id == param_id) {
|
||||
|
|
@ -536,18 +582,22 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
|
|||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(nvm_params))
|
||||
if (i == ARRAY_SIZE(nvm_params)) {
|
||||
hwrm_req_drop(bp, req);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (nvm_param.dir_type == BNXT_NVM_PORT_CFG)
|
||||
idx = bp->pf.port_id;
|
||||
else if (nvm_param.dir_type == BNXT_NVM_FUNC_CFG)
|
||||
idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID;
|
||||
|
||||
data = dma_zalloc_coherent(&bp->pdev->dev, sizeof(*data),
|
||||
&data_dma_addr, GFP_KERNEL);
|
||||
if (!data)
|
||||
data = hwrm_req_dma_slice(bp, req, sizeof(*data), &data_dma_addr);
|
||||
|
||||
if (!data) {
|
||||
hwrm_req_drop(bp, req);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
req->dest_data_addr = cpu_to_le64(data_dma_addr);
|
||||
req->data_len = cpu_to_le16(nvm_param.nvm_num_bits);
|
||||
|
|
@ -556,26 +606,24 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
|
|||
if (idx)
|
||||
req->dimensions = cpu_to_le16(1);
|
||||
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) {
|
||||
bnxt_copy_to_nvm_data(data, val, nvm_param.nvm_num_bits,
|
||||
nvm_param.dl_num_bytes);
|
||||
rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
|
||||
rc = hwrm_req_send(bp, msg);
|
||||
} else {
|
||||
rc = hwrm_send_message_silent(bp, msg, msg_len,
|
||||
HWRM_CMD_TIMEOUT);
|
||||
rc = hwrm_req_send_silent(bp, msg);
|
||||
if (!rc) {
|
||||
bnxt_copy_from_nvm_data(val, data,
|
||||
nvm_param.nvm_num_bits,
|
||||
nvm_param.dl_num_bytes);
|
||||
} else {
|
||||
struct hwrm_err_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
|
||||
if (resp->cmd_err ==
|
||||
NVM_GET_VARIABLE_CMD_ERR_CODE_VAR_NOT_EXIST)
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
dma_free_coherent(&bp->pdev->dev, sizeof(*data), data, data_dma_addr);
|
||||
hwrm_req_drop(bp, req);
|
||||
if (rc == -EACCES)
|
||||
netdev_err(bp->dev, "PF does not have admin privileges to modify NVM config\n");
|
||||
return rc;
|
||||
|
|
@ -584,30 +632,35 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
|
|||
static int bnxt_dl_nvm_param_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
{
|
||||
struct hwrm_nvm_get_variable_input req = {0};
|
||||
struct hwrm_nvm_get_variable_input *req;
|
||||
struct bnxt *bp = bnxt_get_bp_from_dl(dl);
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_VARIABLE, -1, -1);
|
||||
rc = bnxt_hwrm_nvm_req(bp, id, &req, sizeof(req), &ctx->val);
|
||||
if (!rc)
|
||||
if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
|
||||
ctx->val.vbool = !ctx->val.vbool;
|
||||
rc = hwrm_req_init(bp, req, HWRM_NVM_GET_VARIABLE);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = bnxt_hwrm_nvm_req(bp, id, req, &ctx->val);
|
||||
if (!rc && id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
|
||||
ctx->val.vbool = !ctx->val.vbool;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_dl_nvm_param_set(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
{
|
||||
struct hwrm_nvm_set_variable_input req = {0};
|
||||
struct bnxt *bp = bnxt_get_bp_from_dl(dl);
|
||||
struct hwrm_nvm_set_variable_input *req;
|
||||
int rc;
|
||||
|
||||
if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
|
||||
ctx->val.vbool = !ctx->val.vbool;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_SET_VARIABLE, -1, -1);
|
||||
return bnxt_hwrm_nvm_req(bp, id, &req, sizeof(req), &ctx->val);
|
||||
rc = hwrm_req_init(bp, req, HWRM_NVM_SET_VARIABLE);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return bnxt_hwrm_nvm_req(bp, id, req, &ctx->val);
|
||||
}
|
||||
|
||||
#ifdef HAVE_IGNORE_ARI
|
||||
|
|
@ -675,7 +728,7 @@ static int bnxt_dl_params_register(struct bnxt *bp)
|
|||
rc = devlink_params_register(bp->dl, bnxt_dl_params,
|
||||
ARRAY_SIZE(bnxt_dl_params));
|
||||
if (rc) {
|
||||
netdev_warn(bp->dev, "devlink_params_register failed. rc=%d",
|
||||
netdev_warn(bp->dev, "devlink_params_register failed. rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -683,7 +736,7 @@ static int bnxt_dl_params_register(struct bnxt *bp)
|
|||
rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params,
|
||||
ARRAY_SIZE(bnxt_dl_port_params));
|
||||
if (rc) {
|
||||
netdev_err(bp->dev, "devlink_port_params_register failed");
|
||||
netdev_err(bp->dev, "devlink_port_params_register failed\n");
|
||||
devlink_params_unregister(bp->dl, bnxt_dl_params,
|
||||
ARRAY_SIZE(bnxt_dl_params));
|
||||
return rc;
|
||||
|
|
@ -720,7 +773,7 @@ int bnxt_dl_register(struct bnxt *bp)
|
|||
else
|
||||
dl = devlink_alloc(&bnxt_vf_dl_ops, sizeof(struct bnxt_dl));
|
||||
if (!dl) {
|
||||
netdev_warn(bp->dev, "devlink_alloc failed");
|
||||
netdev_warn(bp->dev, "devlink_alloc failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
@ -735,7 +788,7 @@ int bnxt_dl_register(struct bnxt *bp)
|
|||
|
||||
rc = devlink_register(dl, &bp->pdev->dev);
|
||||
if (rc) {
|
||||
netdev_warn(bp->dev, "devlink_register failed. rc=%d", rc);
|
||||
netdev_warn(bp->dev, "devlink_register failed. rc=%d\n", rc);
|
||||
goto err_dl_free;
|
||||
}
|
||||
|
||||
|
|
@ -750,7 +803,7 @@ int bnxt_dl_register(struct bnxt *bp)
|
|||
#endif
|
||||
rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id);
|
||||
if (rc) {
|
||||
netdev_err(bp->dev, "devlink_port_register failed");
|
||||
netdev_err(bp->dev, "devlink_port_register failed\n");
|
||||
goto err_dl_unreg;
|
||||
}
|
||||
#endif /* HAVE_DEVLINK_PORT_PARAM */
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ static inline void bnxt_link_bp_to_dl(struct bnxt *bp, struct devlink *dl)
|
|||
#define BNXT_NVM_CFG_VER_BITS 24
|
||||
#define BNXT_NVM_CFG_VER_BYTES 4
|
||||
|
||||
#define BNXT_MSIX_VEC_MAX 1280
|
||||
#define BNXT_MSIX_VEC_MAX 512
|
||||
#define BNXT_MSIX_VEC_MIN_MAX 128
|
||||
|
||||
union bnxt_nvm_data {
|
||||
|
|
|
|||
|
|
@ -36,3 +36,32 @@ void bnxt_dim_work(struct work_struct *work)
|
|||
bnxt_hwrm_set_ring_coal(bnapi->bp, bnapi);
|
||||
dim->state = DIM_START_MEASURE;
|
||||
}
|
||||
|
||||
#ifndef HAVE_DIM
|
||||
void net_dim(struct dim *dim, struct dim_sample end_sample)
|
||||
{
|
||||
struct dim_stats curr_stats;
|
||||
u16 nevents;
|
||||
|
||||
switch (dim->state) {
|
||||
case DIM_MEASURE_IN_PROGRESS:
|
||||
nevents = BIT_GAP(BITS_PER_TYPE(u16),
|
||||
end_sample.event_ctr,
|
||||
dim->start_sample.event_ctr);
|
||||
if (nevents < DIM_NEVENTS)
|
||||
break;
|
||||
dim_calc_stats(&dim->start_sample, &end_sample, &curr_stats);
|
||||
if (net_dim_decision(&curr_stats, dim)) {
|
||||
dim->state = DIM_APPLY_NEW_PROFILE;
|
||||
schedule_work(&dim->work);
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
case DIM_START_MEASURE:
|
||||
dim->state = DIM_MEASURE_IN_PROGRESS;
|
||||
break;
|
||||
case DIM_APPLY_NEW_PROFILE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -348,32 +348,6 @@ static inline void dim_calc_stats(struct dim_sample *start,
|
|||
delta_us);
|
||||
}
|
||||
|
||||
static inline void net_dim(struct dim *dim,
|
||||
struct dim_sample end_sample)
|
||||
{
|
||||
struct dim_stats curr_stats;
|
||||
u16 nevents;
|
||||
|
||||
switch (dim->state) {
|
||||
case DIM_MEASURE_IN_PROGRESS:
|
||||
nevents = BIT_GAP(BITS_PER_TYPE(u16),
|
||||
end_sample.event_ctr,
|
||||
dim->start_sample.event_ctr);
|
||||
if (nevents < DIM_NEVENTS)
|
||||
break;
|
||||
dim_calc_stats(&dim->start_sample, &end_sample, &curr_stats);
|
||||
if (net_dim_decision(&curr_stats, dim)) {
|
||||
dim->state = DIM_APPLY_NEW_PROFILE;
|
||||
schedule_work(&dim->work);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case DIM_START_MEASURE:
|
||||
dim->state = DIM_MEASURE_IN_PROGRESS;
|
||||
break;
|
||||
case DIM_APPLY_NEW_PROFILE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void net_dim(struct dim *dim, struct dim_sample end_sample);
|
||||
|
||||
#endif /* NET_DIM_H */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,497 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2020 Broadcom Limited
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_hwrm.h"
|
||||
#include "bnxt_eem.h"
|
||||
|
||||
static int bnxt_hwrm_cfa_eem_qcaps(struct bnxt *bp, enum bnxt_eem_dir dir)
|
||||
{
|
||||
struct bnxt_eem_ctx_mem_info *ctxp = &bp->eem_info->eem_ctx_info[dir];
|
||||
struct bnxt_eem_pg_misc *tbl = &ctxp->eem_misc[KEY0_TABLE];
|
||||
struct bnxt_eem_caps *cap = &bp->eem_info->eem_caps[dir];
|
||||
struct hwrm_cfa_eem_qcaps_output *resp;
|
||||
struct hwrm_cfa_eem_qcaps_input *req;
|
||||
u32 flags;
|
||||
int rc;
|
||||
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_EEM_QCAPS);
|
||||
if (!rc) {
|
||||
flags = dir == BNXT_EEM_DIR_TX ?
|
||||
CFA_EEM_QCAPS_REQ_FLAGS_PATH_TX :
|
||||
CFA_EEM_QCAPS_REQ_FLAGS_PATH_RX;
|
||||
req->flags = cpu_to_le32(flags);
|
||||
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
}
|
||||
if (rc) {
|
||||
hwrm_req_drop(bp, req);
|
||||
netdev_warn(bp->dev, "Failed to read CFA %s EEM Capabilities\n",
|
||||
BNXT_EEM_DIR(dir));
|
||||
return rc;
|
||||
}
|
||||
|
||||
cap->flags = le32_to_cpu(resp->flags);
|
||||
cap->supported = le32_to_cpu(resp->supported);
|
||||
cap->max_entries_supported = le32_to_cpu(resp->max_entries_supported);
|
||||
cap->key_entry_size = le16_to_cpu(resp->key_entry_size);
|
||||
cap->record_entry_size = le16_to_cpu(resp->record_entry_size);
|
||||
cap->efc_entry_size = le16_to_cpu(resp->efc_entry_size);
|
||||
hwrm_req_drop(bp, req);
|
||||
|
||||
netdev_dbg(bp->dev, "%s CFA EEM Capabilities:\n", BNXT_EEM_DIR(dir));
|
||||
netdev_dbg(bp->dev, "supported: 0x%x max_entries_supported: 0x%x\n",
|
||||
resp->supported, resp->max_entries_supported);
|
||||
netdev_dbg(bp->dev, "key_entry_size: 0x%x record_entry_size: 0x%x\n",
|
||||
resp->key_entry_size, resp->record_entry_size);
|
||||
|
||||
tbl[KEY0_TABLE].type = KEY0_TABLE;
|
||||
tbl[KEY1_TABLE].type = KEY1_TABLE;
|
||||
tbl[RECORD_TABLE].type = RECORD_TABLE;
|
||||
tbl[EFC_TABLE].type = EFC_TABLE;
|
||||
|
||||
tbl[KEY0_TABLE].entry_size = cap->key_entry_size;
|
||||
tbl[KEY1_TABLE].entry_size = cap->key_entry_size;
|
||||
tbl[RECORD_TABLE].entry_size = cap->record_entry_size;
|
||||
tbl[EFC_TABLE].entry_size = cap->efc_entry_size;
|
||||
|
||||
if (BNXT_CHIP_P4(bp) && (dir == BNXT_EEM_DIR_TX))
|
||||
cap->record_entry_size = BNXT_EEM_TX_RECORD_SIZE;
|
||||
|
||||
tbl[KEY0_TABLE].ctx_id = BNXT_EEM_CTX_ID_INVALID;
|
||||
tbl[KEY1_TABLE].ctx_id = BNXT_EEM_CTX_ID_INVALID;
|
||||
tbl[RECORD_TABLE].ctx_id = BNXT_EEM_CTX_ID_INVALID;
|
||||
tbl[EFC_TABLE].ctx_id = BNXT_EEM_CTX_ID_INVALID;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void bnxt_hwrm_query_eem_caps(struct bnxt *bp)
|
||||
{
|
||||
if (!(bp->fw_cap & BNXT_FW_CAP_CFA_EEM))
|
||||
return;
|
||||
|
||||
bp->eem_info = kzalloc(sizeof(*bp->eem_info), GFP_KERNEL);
|
||||
if (!bp->eem_info)
|
||||
return;
|
||||
|
||||
/* Query tx eem caps */
|
||||
bnxt_hwrm_cfa_eem_qcaps(bp, BNXT_EEM_DIR_TX);
|
||||
|
||||
/* Query rx eem caps */
|
||||
bnxt_hwrm_cfa_eem_qcaps(bp, BNXT_EEM_DIR_RX);
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_cfa_eem_op(struct bnxt *bp, enum bnxt_eem_dir dir, u16 op)
|
||||
{
|
||||
struct hwrm_cfa_eem_op_input *req;
|
||||
u32 flags;
|
||||
int rc;
|
||||
|
||||
if (op != CFA_EEM_OP_REQ_OP_EEM_ENABLE &&
|
||||
op != CFA_EEM_OP_REQ_OP_EEM_DISABLE &&
|
||||
op != CFA_EEM_OP_REQ_OP_EEM_CLEANUP)
|
||||
return -EINVAL;
|
||||
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_EEM_OP);
|
||||
if (!rc) {
|
||||
flags = (dir == BNXT_EEM_DIR_TX) ?
|
||||
CFA_EEM_OP_REQ_FLAGS_PATH_TX :
|
||||
CFA_EEM_OP_REQ_FLAGS_PATH_RX;
|
||||
req->flags = cpu_to_le32(flags);
|
||||
req->op = cpu_to_le16(op);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
}
|
||||
if (rc)
|
||||
netdev_warn(bp->dev, "%s CFA EEM OP:%d failed, rc=%d",
|
||||
BNXT_EEM_DIR(dir), op, rc);
|
||||
else
|
||||
netdev_dbg(bp->dev, "%s CFA EEM OP:%d succeeded",
|
||||
BNXT_EEM_DIR(dir), op);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_cfa_eem_mem_unrgtr(struct bnxt *bp, u16 *ctx_id)
|
||||
{
|
||||
struct hwrm_cfa_ctx_mem_unrgtr_input *req;
|
||||
int rc = 0;
|
||||
|
||||
if (*ctx_id == BNXT_EEM_CTX_ID_INVALID)
|
||||
return rc;
|
||||
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_CTX_MEM_UNRGTR);
|
||||
if (!rc) {
|
||||
req->ctx_id = cpu_to_le16(*ctx_id);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
}
|
||||
if (rc)
|
||||
netdev_warn(bp->dev, "Failed to Unregister CFA EEM Mem\n");
|
||||
else
|
||||
*ctx_id = BNXT_EEM_CTX_ID_INVALID;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void bnxt_eem_ctx_unreg(struct bnxt *bp, enum bnxt_eem_dir dir)
|
||||
{
|
||||
struct bnxt_eem_ctx_mem_info *ctxp = &bp->eem_info->eem_ctx_info[dir];
|
||||
struct bnxt_eem_pg_misc *tbl_misc;
|
||||
struct bnxt_ctx_pg_info *tbl;
|
||||
int tbl_type;
|
||||
|
||||
for (tbl_type = KEY0_TABLE; tbl_type < MAX_TABLE; tbl_type++) {
|
||||
if (tbl_type == EFC_TABLE)
|
||||
continue;
|
||||
tbl = &ctxp->eem_tables[tbl_type];
|
||||
tbl_misc = &ctxp->eem_misc[tbl_type];
|
||||
bnxt_hwrm_cfa_eem_mem_unrgtr(bp, &tbl_misc->ctx_id);
|
||||
bnxt_free_ctx_pg_tbls(bp, tbl);
|
||||
}
|
||||
}
|
||||
|
||||
static void bnxt_unconfig_eem(struct bnxt *bp, enum bnxt_eem_dir dir)
|
||||
{
|
||||
bool configured = false;
|
||||
|
||||
if (!(bp->fw_cap & BNXT_FW_CAP_CFA_EEM) ||
|
||||
dir < BNXT_EEM_DIR_TX || dir > BNXT_EEM_DIR_RX)
|
||||
return;
|
||||
|
||||
if (dir == BNXT_EEM_DIR_TX) {
|
||||
configured = bp->eem_info->eem_cfg_tx_dir ? true : false;
|
||||
bp->eem_info->eem_cfg_tx_dir = false;
|
||||
} else {
|
||||
configured = bp->eem_info->eem_cfg_rx_dir ? true : false;
|
||||
bp->eem_info->eem_cfg_rx_dir = false;
|
||||
}
|
||||
|
||||
if (configured) {
|
||||
bnxt_hwrm_cfa_eem_op(bp, dir, CFA_EEM_OP_REQ_OP_EEM_DISABLE);
|
||||
bnxt_hwrm_cfa_eem_op(bp, dir, CFA_EEM_OP_REQ_OP_EEM_CLEANUP);
|
||||
}
|
||||
|
||||
if (bp->eem_info->eem_primary)
|
||||
bnxt_eem_ctx_unreg(bp, dir);
|
||||
|
||||
if (!bp->eem_info->eem_cfg_tx_dir && !bp->eem_info->eem_cfg_rx_dir) {
|
||||
bp->eem_info->eem_primary = false;
|
||||
bp->eem_info->eem_group = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int bnxt_eem_validate_num_entries(struct bnxt *bp,
|
||||
enum bnxt_eem_dir dir,
|
||||
u32 num_entries)
|
||||
{
|
||||
struct bnxt_eem_caps *cap = &bp->eem_info->eem_caps[dir];
|
||||
|
||||
if (num_entries < BNXT_EEM_MIN_ENTRIES ||
|
||||
num_entries > cap->max_entries_supported ||
|
||||
num_entries != roundup_pow_of_two(num_entries)) {
|
||||
netdev_warn(bp->dev, "EEM: Invalid num_entries requested: %u\n",
|
||||
num_entries);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bp->eem_info->eem_ctx_info[dir].num_entries = num_entries;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bnxt_eem_pg_size_table(struct bnxt_eem_caps *cap, int tbl_type,
|
||||
u32 num_entries, u32 *size, u8 *depth,
|
||||
struct bnxt_eem_pg_misc *tbl_misc)
|
||||
{
|
||||
u32 mem_size = 0;
|
||||
|
||||
if (tbl_type == KEY0_TABLE || tbl_type == KEY1_TABLE) {
|
||||
mem_size = cap->key_entry_size * num_entries;
|
||||
tbl_misc->entry_size = cap->key_entry_size;
|
||||
}
|
||||
|
||||
if (tbl_type == RECORD_TABLE) {
|
||||
mem_size = cap->record_entry_size * num_entries * 2;
|
||||
tbl_misc->entry_size = cap->record_entry_size;
|
||||
}
|
||||
|
||||
if (tbl_type == EFC_TABLE) {
|
||||
mem_size = cap->efc_entry_size * num_entries;
|
||||
tbl_misc->entry_size = cap->efc_entry_size;
|
||||
}
|
||||
|
||||
tbl_misc->type = tbl_type;
|
||||
*size = mem_size;
|
||||
*depth = (DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE) < MAX_CTX_PAGES) ?
|
||||
1 : 2;
|
||||
}
|
||||
|
||||
static u8 bnxt_eem_page_level_code(int pg_lvl)
|
||||
{
|
||||
u8 page_level;
|
||||
|
||||
switch (pg_lvl) {
|
||||
case PT_LVL_2:
|
||||
page_level = CFA_CTX_MEM_RGTR_REQ_PAGE_LEVEL_LVL_2;
|
||||
break;
|
||||
case PT_LVL_1:
|
||||
page_level = CFA_CTX_MEM_RGTR_REQ_PAGE_LEVEL_LVL_1;
|
||||
break;
|
||||
case PT_LVL_0:
|
||||
page_level = CFA_CTX_MEM_RGTR_REQ_PAGE_LEVEL_LVL_0;
|
||||
break;
|
||||
default:
|
||||
page_level = 0xff;
|
||||
break;
|
||||
}
|
||||
return page_level;
|
||||
}
|
||||
|
||||
static u8 bnxt_eem_page_size_code(u32 page_size)
|
||||
{
|
||||
u8 pg_sz_code = 0xff;
|
||||
|
||||
switch (page_size) {
|
||||
case BNXT_EEM_PG_SZ_4K:
|
||||
pg_sz_code = CFA_CTX_MEM_RGTR_REQ_PAGE_SIZE_4K;
|
||||
break;
|
||||
case BNXT_EEM_PG_SZ_8K:
|
||||
pg_sz_code = CFA_CTX_MEM_RGTR_REQ_PAGE_SIZE_8K;
|
||||
break;
|
||||
case BNXT_EEM_PG_SZ_64K:
|
||||
pg_sz_code = CFA_CTX_MEM_RGTR_REQ_PAGE_SIZE_64K;
|
||||
break;
|
||||
case BNXT_EEM_PG_SZ_256K:
|
||||
pg_sz_code = CFA_CTX_MEM_RGTR_REQ_PAGE_SIZE_256K;
|
||||
break;
|
||||
case BNXT_EEM_PG_SZ_1M:
|
||||
pg_sz_code = CFA_CTX_MEM_RGTR_REQ_PAGE_SIZE_1M;
|
||||
break;
|
||||
case BNXT_EEM_PG_SZ_2M:
|
||||
pg_sz_code = CFA_CTX_MEM_RGTR_REQ_PAGE_SIZE_2M;
|
||||
break;
|
||||
case BNXT_EEM_PG_SZ_4M:
|
||||
pg_sz_code = CFA_CTX_MEM_RGTR_REQ_PAGE_SIZE_4M;
|
||||
break;
|
||||
case BNXT_EEM_PG_SZ_1G:
|
||||
pg_sz_code = CFA_CTX_MEM_RGTR_REQ_PAGE_SIZE_1G;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return pg_sz_code;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_cfa_eem_mem_rgtr(struct bnxt *bp, int page_level,
|
||||
u32 page_size, u64 page_dir, u16 *ctx_id)
|
||||
{
|
||||
struct hwrm_cfa_ctx_mem_rgtr_output *resp;
|
||||
struct hwrm_cfa_ctx_mem_rgtr_input *req;
|
||||
int rc;
|
||||
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_CTX_MEM_RGTR);
|
||||
if (!rc) {
|
||||
req->flags = 0;
|
||||
req->page_level = bnxt_eem_page_level_code(page_level);
|
||||
req->page_size = bnxt_eem_page_size_code(page_size);
|
||||
req->page_dir = cpu_to_le64(page_dir);
|
||||
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
}
|
||||
if (rc) {
|
||||
hwrm_req_drop(bp, req);
|
||||
netdev_warn(bp->dev, "Failed to register CFA EEM Mem\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
*ctx_id = le16_to_cpu(resp->ctx_id);
|
||||
hwrm_req_drop(bp, req);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_eem_ctx_reg(struct bnxt *bp, enum bnxt_eem_dir dir,
|
||||
u16 grp_id, u32 num_entries)
|
||||
{
|
||||
struct bnxt_eem_ctx_mem_info *ctxp = &bp->eem_info->eem_ctx_info[dir];
|
||||
struct bnxt_eem_caps *cap = &bp->eem_info->eem_caps[dir];
|
||||
struct bnxt_eem_pg_misc *tbl_misc;
|
||||
struct bnxt_ctx_pg_info *tbl;
|
||||
int tbl_type;
|
||||
u32 mem_size;
|
||||
u8 depth;
|
||||
int rc;
|
||||
|
||||
ctxp->num_entries = num_entries;
|
||||
if (!num_entries)
|
||||
return 0;
|
||||
|
||||
for (tbl_type = KEY0_TABLE; tbl_type < MAX_TABLE; tbl_type++) {
|
||||
tbl = &ctxp->eem_tables[tbl_type];
|
||||
tbl_misc = &ctxp->eem_misc[tbl_type];
|
||||
|
||||
/* No EFC table support, skip EFC */
|
||||
if (tbl_type == EFC_TABLE) {
|
||||
tbl_misc->ctx_id = 0;
|
||||
tbl_misc->entry_size = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
bnxt_eem_pg_size_table(cap, tbl_type, num_entries,
|
||||
&mem_size, &depth, tbl_misc);
|
||||
rc = bnxt_alloc_ctx_pg_tbls(bp, tbl, mem_size, depth, false);
|
||||
if (rc) {
|
||||
netdev_err(bp->dev,
|
||||
"alloc failed size 0x%x, depth %d\n",
|
||||
mem_size, depth);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = bnxt_hwrm_cfa_eem_mem_rgtr(bp, depth,
|
||||
BNXT_EEM_PAGE_SIZE,
|
||||
tbl->ring_mem.pg_tbl_map,
|
||||
&tbl_misc->ctx_id);
|
||||
if (rc)
|
||||
goto cleanup;
|
||||
}
|
||||
return rc;
|
||||
cleanup:
|
||||
bnxt_eem_ctx_unreg(bp, dir);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_cfa_eem_cfg(struct bnxt *bp, enum bnxt_eem_dir dir,
|
||||
u32 cfg_flags,
|
||||
u16 grp_id)
|
||||
{
|
||||
struct bnxt_eem_ctx_mem_info *ctxp = &bp->eem_info->eem_ctx_info[dir];
|
||||
struct bnxt_eem_pg_misc *tbl = &ctxp->eem_misc[KEY0_TABLE];
|
||||
struct hwrm_cfa_eem_cfg_input *req;
|
||||
u32 flags;
|
||||
int rc;
|
||||
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_EEM_CFG);
|
||||
if (!rc) {
|
||||
flags = (dir == BNXT_EEM_DIR_TX) ?
|
||||
CFA_EEM_CFG_REQ_FLAGS_PATH_TX :
|
||||
CFA_EEM_CFG_REQ_FLAGS_PATH_RX;
|
||||
flags |= CFA_EEM_CFG_REQ_FLAGS_PREFERRED_OFFLOAD;
|
||||
|
||||
if (cfg_flags) {
|
||||
req->key0_ctx_id = cpu_to_le16(tbl[KEY0_TABLE].ctx_id);
|
||||
req->key1_ctx_id = cpu_to_le16(tbl[KEY1_TABLE].ctx_id);
|
||||
req->record_ctx_id = cpu_to_le16(tbl[RECORD_TABLE].ctx_id);
|
||||
req->efc_ctx_id = cpu_to_le16(tbl[EFC_TABLE].ctx_id);
|
||||
req->num_entries = cpu_to_le32(ctxp->num_entries);
|
||||
} else {
|
||||
flags |= CFA_EEM_CFG_REQ_FLAGS_SECONDARY_PF;
|
||||
}
|
||||
req->flags = cpu_to_le32(flags);
|
||||
req->group_id = cpu_to_le16(grp_id);
|
||||
|
||||
rc = hwrm_req_send(bp, req);
|
||||
}
|
||||
if (rc) {
|
||||
netdev_warn(bp->dev, "Failed to configure %s CFA EEM: rc=%d",
|
||||
BNXT_EEM_DIR(dir), rc);
|
||||
return rc;
|
||||
}
|
||||
netdev_dbg(bp->dev, "Configured %s EEM\n", BNXT_EEM_DIR(dir));
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_config_eem(struct bnxt *bp, enum bnxt_eem_dir dir, u32 flags,
|
||||
u32 num_entries, u16 grp_id)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!(bp->fw_cap & BNXT_FW_CAP_CFA_EEM) || dir < BNXT_EEM_DIR_TX ||
|
||||
dir > BNXT_EEM_DIR_RX ||
|
||||
bnxt_eem_validate_num_entries(bp, dir, num_entries))
|
||||
return -EINVAL;
|
||||
|
||||
if ((bp->eem_info->eem_cfg_tx_dir && (dir == BNXT_EEM_DIR_TX)) ||
|
||||
(bp->eem_info->eem_cfg_rx_dir && (dir == BNXT_EEM_DIR_RX))) {
|
||||
netdev_warn(bp->dev,
|
||||
"already config the EEM in dir %d\n",
|
||||
dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bp->eem_info->eem_primary = flags ? true : false;
|
||||
if (bp->eem_info->eem_primary) {
|
||||
rc = bnxt_eem_ctx_reg(bp, dir, grp_id, num_entries);
|
||||
if (rc)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = bnxt_hwrm_cfa_eem_cfg(bp, dir, flags, grp_id);
|
||||
if (rc)
|
||||
goto cleanup;
|
||||
|
||||
rc = bnxt_hwrm_cfa_eem_op(bp, dir, CFA_EEM_OP_REQ_OP_EEM_ENABLE);
|
||||
if (rc)
|
||||
goto cleanup;
|
||||
|
||||
if (dir == BNXT_EEM_DIR_TX)
|
||||
bp->eem_info->eem_cfg_tx_dir = true;
|
||||
else
|
||||
bp->eem_info->eem_cfg_rx_dir = true;
|
||||
bp->eem_info->eem_group = grp_id;
|
||||
|
||||
return rc;
|
||||
cleanup:
|
||||
bnxt_unconfig_eem(bp, dir);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bnxt_eem_clear_cfg_system_memory(struct bnxt *bp)
|
||||
{
|
||||
int dir;
|
||||
|
||||
netdev_dbg(bp->dev, "call undo system memory\n");
|
||||
for (dir = BNXT_EEM_DIR_TX; dir < BNXT_EEM_NUM_DIR; dir++)
|
||||
bnxt_unconfig_eem(bp, dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_eem_cfg_system_memory(struct bnxt *bp, u32 entry_num)
|
||||
{
|
||||
int dir;
|
||||
int rc;
|
||||
|
||||
netdev_dbg(bp->dev,
|
||||
"call cfg system memory, entry num: %d\n",
|
||||
entry_num);
|
||||
|
||||
for (dir = BNXT_EEM_DIR_TX; dir < BNXT_EEM_NUM_DIR; dir++) {
|
||||
rc = bnxt_config_eem(bp, dir, true, entry_num, 0);
|
||||
if (rc) {
|
||||
netdev_err(bp->dev,
|
||||
"config EEM fail. dir %d entry_num %d\n",
|
||||
dir, entry_num);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
cleanup:
|
||||
for (dir = BNXT_EEM_DIR_TX; dir < BNXT_EEM_NUM_DIR; dir++)
|
||||
bnxt_unconfig_eem(bp, dir);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2020 Broadcom Limited
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef BNXT_EEM_H
|
||||
#define BNXT_EEM_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#if (PAGE_SHIFT < 12) /* < 4K >> 4K */
|
||||
#define BNXT_EEM_PAGE_SHIFT 12
|
||||
#elif (PAGE_SHIFT <= 13) /* 4K, 8K */
|
||||
#define BNXT_EEM_PAGE_SHIFT PAGE_SHIFT
|
||||
#elif (PAGE_SHIFT < 16) /* 16K, 32K >> 8K */
|
||||
#define BNXT_EEM_PAGE_SHIFT 13
|
||||
#elif (PAGE_SHIFT <= 17) /* 64K, 128K >> 64K */
|
||||
#define BNXT_EEM_PAGE_SHIFT 16
|
||||
#elif (PAGE_SHIFT <= 19) /* 256K, 512K >> 256K */
|
||||
#define BNXT_EEM_PAGE_SHIFT 18
|
||||
#elif (PAGE_SHIFT <= 22) /* 1M, 2M, 4M */
|
||||
#define BNXT_EEM_PAGE_SHIFT PAGE_SHIFT
|
||||
#elif (PAGE_SHIFT <= 29) /* 8M ... 512M >> 4M */
|
||||
#define BNXT_EEM_PAGE_SHIFT 22
|
||||
#else /* >= 1G >> 1G */
|
||||
#define BNXT_EEM_PAGE_SHIFT 30
|
||||
#endif
|
||||
|
||||
#define BNXT_EEM_PAGE_SIZE BIT(BNXT_EEM_PAGE_SHIFT)
|
||||
|
||||
#define BNXT_EEM_PG_SZ_4K BIT(12)
|
||||
#define BNXT_EEM_PG_SZ_8K BIT(13)
|
||||
#define BNXT_EEM_PG_SZ_64K BIT(16)
|
||||
#define BNXT_EEM_PG_SZ_256K BIT(18)
|
||||
#define BNXT_EEM_PG_SZ_1M BIT(20)
|
||||
#define BNXT_EEM_PG_SZ_2M BIT(21)
|
||||
#define BNXT_EEM_PG_SZ_4M BIT(22)
|
||||
#define BNXT_EEM_PG_SZ_1G BIT(30)
|
||||
|
||||
#define BNXT_EEM_MIN_ENTRIES BIT(15) /* 32K */
|
||||
#define BNXT_EEM_MAX_ENTRIES BIT(27) /* 128M */
|
||||
|
||||
#define BNXT_EEM_TX_RECORD_SIZE 64
|
||||
#define BNXT_EEM_CTX_ID_INVALID 0xFFFF
|
||||
|
||||
enum bnxt_eem_dir {
|
||||
BNXT_EEM_DIR_TX,
|
||||
BNXT_EEM_DIR_RX,
|
||||
BNXT_EEM_NUM_DIR
|
||||
};
|
||||
|
||||
#define BNXT_EEM_DIR(dir) ((dir) == BNXT_EEM_DIR_TX ? "TX" : "RX")
|
||||
|
||||
enum bnxt_eem_table_type {
|
||||
KEY0_TABLE,
|
||||
KEY1_TABLE,
|
||||
RECORD_TABLE,
|
||||
EFC_TABLE,
|
||||
MAX_TABLE
|
||||
};
|
||||
|
||||
enum bnxt_pg_tbl_lvl {
|
||||
PT_LVL_0,
|
||||
PT_LVL_1,
|
||||
PT_LVL_2,
|
||||
PT_LVL_MAX
|
||||
};
|
||||
|
||||
/* CFA EEM Caps saved from the response to HWRM_CFA_EEM_QCAPS */
|
||||
struct bnxt_eem_caps {
|
||||
u32 flags;
|
||||
u32 supported;
|
||||
u32 max_entries_supported;
|
||||
u16 key_entry_size;
|
||||
u16 record_entry_size;
|
||||
u16 efc_entry_size;
|
||||
};
|
||||
|
||||
struct bnxt_eem_pg_misc {
|
||||
int type;
|
||||
u16 ctx_id;
|
||||
u32 entry_size;
|
||||
};
|
||||
|
||||
struct bnxt_eem_ctx_mem_info {
|
||||
u32 num_entries;
|
||||
struct bnxt_eem_pg_misc eem_misc[MAX_TABLE];
|
||||
struct bnxt_ctx_pg_info eem_tables[MAX_TABLE];
|
||||
};
|
||||
|
||||
struct bnxt_eem_info {
|
||||
u8 eem_cfg_tx_dir:1;
|
||||
u8 eem_cfg_rx_dir:1;
|
||||
u8 eem_primary:1;
|
||||
u16 eem_group;
|
||||
struct bnxt_eem_caps eem_caps[BNXT_EEM_NUM_DIR];
|
||||
struct bnxt_eem_ctx_mem_info
|
||||
eem_ctx_info[BNXT_EEM_NUM_DIR];
|
||||
};
|
||||
|
||||
void bnxt_hwrm_query_eem_caps(struct bnxt *bp);
|
||||
int bnxt_eem_clear_cfg_system_memory(struct bnxt *bp);
|
||||
int bnxt_eem_cfg_system_memory(struct bnxt *bp, u32 entry_num);
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -92,8 +92,13 @@ struct hwrm_dbg_cmn_output {
|
|||
#define BNXT_LED_DFLT_ENABLES(x) \
|
||||
cpu_to_le32(BNXT_LED_DFLT_ENA << (BNXT_LED_DFLT_ENA_SHIFT * (x)))
|
||||
|
||||
#define BNXT_FW_RESET_AP 0xfffe
|
||||
#define BNXT_FW_RESET_CHIP 0xffff
|
||||
#define BNXT_FW_RESET_CRASHDUMP (ETH_RESET_CRASHDUMP << ETH_RESET_SHARED_SHIFT)
|
||||
#define BNXT_FW_RESET_AP (ETH_RESET_AP << ETH_RESET_SHARED_SHIFT)
|
||||
#define BNXT_FW_RESET_CHIP ((ETH_RESET_MGMT | ETH_RESET_IRQ | \
|
||||
ETH_RESET_DMA | ETH_RESET_FILTER | \
|
||||
ETH_RESET_OFFLOAD | ETH_RESET_MAC | \
|
||||
ETH_RESET_PHY | ETH_RESET_RAM) \
|
||||
<< ETH_RESET_SHARED_SHIFT)
|
||||
|
||||
#define BNXT_PXP_REG_LEN 0x3110
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@
|
|||
#ifndef BNXT_EXTRA_VER_H
|
||||
#define BNXT_EXTRA_VER_H
|
||||
|
||||
#define DRV_MODULE_EXTRA_VER "-216.1.92.0"
|
||||
#define DRV_MODULE_EXTRA_VER "-216.1.192.4"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,566 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2020 Broadcom Limited
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmapool.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_hwrm.h"
|
||||
|
||||
static u64 hwrm_calc_sentinel(struct bnxt_hwrm_ctx *ctx, u16 req_type)
|
||||
{
|
||||
return (((u64)ctx) + req_type) ^ BNXT_HWRM_SENTINEL;
|
||||
}
|
||||
|
||||
int __hwrm_req_init(struct bnxt *bp, void **req, u16 req_type, u32 req_len)
|
||||
{
|
||||
struct bnxt_hwrm_ctx *ctx;
|
||||
dma_addr_t dma_handle;
|
||||
u8 *req_addr;
|
||||
|
||||
if (req_len > BNXT_HWRM_CTX_OFFSET)
|
||||
return -E2BIG;
|
||||
|
||||
req_addr = dma_pool_alloc(bp->hwrm_dma_pool, GFP_KERNEL | __GFP_ZERO,
|
||||
&dma_handle);
|
||||
if (!req_addr)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx = (struct bnxt_hwrm_ctx *)(req_addr + BNXT_HWRM_CTX_OFFSET);
|
||||
/* safety first, sentinel used to check for invalid requests */
|
||||
ctx->sentinel = hwrm_calc_sentinel(ctx, req_type);
|
||||
ctx->req_len = req_len;
|
||||
ctx->req = (struct input *)req_addr;
|
||||
ctx->resp = (struct output *)(req_addr + BNXT_HWRM_RESP_OFFSET);
|
||||
ctx->dma_handle = dma_handle;
|
||||
ctx->flags = 0; /* __GFP_ZERO, but be explicit regarding ownership */
|
||||
ctx->timeout = bp->hwrm_cmd_timeout ?: DFLT_HWRM_CMD_TIMEOUT;
|
||||
ctx->allocated = BNXT_HWRM_DMA_SIZE - BNXT_HWRM_CTX_OFFSET;
|
||||
ctx->gfp = GFP_KERNEL;
|
||||
ctx->slice_addr = NULL;
|
||||
|
||||
/* initialize common request fields */
|
||||
ctx->req->req_type = cpu_to_le16(req_type);
|
||||
ctx->req->resp_addr = cpu_to_le64(dma_handle + BNXT_HWRM_RESP_OFFSET);
|
||||
ctx->req->cmpl_ring = cpu_to_le16(BNXT_HWRM_NO_CMPL_RING);
|
||||
ctx->req->target_id = cpu_to_le16(BNXT_HWRM_TARGET);
|
||||
*req = ctx->req;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct bnxt_hwrm_ctx *__hwrm_ctx(struct bnxt *bp, u8 *req_addr)
|
||||
{
|
||||
void *ctx_addr = req_addr + BNXT_HWRM_CTX_OFFSET;
|
||||
struct input *req = (struct input *)req_addr;
|
||||
struct bnxt_hwrm_ctx *ctx = ctx_addr;
|
||||
u64 sentinel;
|
||||
|
||||
if (!req) {
|
||||
/* can only be due to software bug, be loud */
|
||||
netdev_err(bp->dev, "null HWRM request");
|
||||
dump_stack();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* HWRM API has no type safety, verify sentinel to validate address */
|
||||
sentinel = hwrm_calc_sentinel(ctx, le16_to_cpu(req->req_type));
|
||||
if (ctx->sentinel != sentinel) {
|
||||
/* can only be due to software bug, be loud */
|
||||
netdev_err(bp->dev, "HWRM sentinel mismatch, req_type = %u\n",
|
||||
(u32)le16_to_cpu(req->req_type));
|
||||
dump_stack();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void hwrm_req_silence(struct bnxt *bp, void *req)
|
||||
{
|
||||
struct bnxt_hwrm_ctx *ctx = __hwrm_ctx(bp, req);
|
||||
|
||||
if (ctx)
|
||||
ctx->flags |= BNXT_HWRM_CTX_SILENT;
|
||||
}
|
||||
|
||||
void hwrm_req_timeout(struct bnxt *bp, void *req, int timeout)
|
||||
{
|
||||
struct bnxt_hwrm_ctx *ctx = __hwrm_ctx(bp, req);
|
||||
|
||||
if (ctx)
|
||||
ctx->timeout = timeout;
|
||||
}
|
||||
|
||||
void hwrm_req_alloc_flags(struct bnxt *bp, void *req, gfp_t gfp)
|
||||
{
|
||||
struct bnxt_hwrm_ctx *ctx = __hwrm_ctx(bp, req);
|
||||
|
||||
if (ctx)
|
||||
ctx->gfp = gfp;
|
||||
}
|
||||
|
||||
int hwrm_req_replace(struct bnxt *bp, void *req, void *new_req, u32 len)
|
||||
{
|
||||
struct bnxt_hwrm_ctx *ctx = __hwrm_ctx(bp, req);
|
||||
struct input *internal_req = req;
|
||||
u16 req_type;
|
||||
|
||||
if (!ctx)
|
||||
return -EINVAL;
|
||||
|
||||
if (len > BNXT_HWRM_CTX_OFFSET)
|
||||
return -E2BIG;
|
||||
|
||||
/* free any existing slices */
|
||||
ctx->allocated = BNXT_HWRM_DMA_SIZE - BNXT_HWRM_CTX_OFFSET;
|
||||
if (ctx->slice_addr) {
|
||||
dma_free_coherent(&bp->pdev->dev, ctx->slice_size,
|
||||
ctx->slice_addr, ctx->slice_handle);
|
||||
ctx->slice_addr = NULL;
|
||||
}
|
||||
ctx->gfp = GFP_KERNEL;
|
||||
|
||||
if ((bp->fw_cap & BNXT_FW_CAP_SHORT_CMD) || len > BNXT_HWRM_MAX_REQ_LEN) {
|
||||
memcpy(internal_req, new_req, len);
|
||||
} else {
|
||||
internal_req->req_type = ((struct input *)new_req)->req_type;
|
||||
ctx->req = new_req;
|
||||
}
|
||||
|
||||
ctx->req_len = len;
|
||||
ctx->req->resp_addr = cpu_to_le64(ctx->dma_handle +
|
||||
BNXT_HWRM_RESP_OFFSET);
|
||||
|
||||
/* update sentinel for potentially new request type */
|
||||
req_type = le16_to_cpu(internal_req->req_type);
|
||||
ctx->sentinel = hwrm_calc_sentinel(ctx, req_type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hwrm_req_capture_ts(struct bnxt *bp, void *req,
|
||||
struct ptp_system_timestamp *sts)
|
||||
{
|
||||
struct bnxt_hwrm_ctx *ctx = __hwrm_ctx(bp, req);
|
||||
|
||||
if (ctx)
|
||||
ctx->sts = sts;
|
||||
}
|
||||
|
||||
void *hwrm_req_hold(struct bnxt *bp, void *req)
|
||||
{
|
||||
struct bnxt_hwrm_ctx *ctx = __hwrm_ctx(bp, req);
|
||||
struct input *input = (struct input *)req;
|
||||
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
if (ctx->flags & BNXT_HWRM_CTX_OWNED) {
|
||||
/* can only be due to software bug, be loud */
|
||||
netdev_err(bp->dev, "HWRM context already owned, req_type = %u\n",
|
||||
(u32)le16_to_cpu(input->req_type));
|
||||
dump_stack();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->flags |= BNXT_HWRM_CTX_OWNED;
|
||||
return ((u8 *)req) + BNXT_HWRM_RESP_OFFSET;
|
||||
}
|
||||
|
||||
static void __hwrm_ctx_drop(struct bnxt *bp, struct bnxt_hwrm_ctx *ctx)
|
||||
{
|
||||
void *addr = ((u8 *)ctx) - BNXT_HWRM_CTX_OFFSET;
|
||||
dma_addr_t dma_handle = ctx->dma_handle; /* save before invalidate */
|
||||
|
||||
/* unmap any auxiliary DMA slice */
|
||||
if (ctx->slice_addr)
|
||||
dma_free_coherent(&bp->pdev->dev, ctx->slice_size,
|
||||
ctx->slice_addr, ctx->slice_handle);
|
||||
|
||||
/* invalidate, ensure ownership, sentinel and dma_handle are cleared */
|
||||
memset(ctx, 0, sizeof(struct bnxt_hwrm_ctx));
|
||||
|
||||
/* return the buffer to the DMA pool */
|
||||
if (dma_handle)
|
||||
dma_pool_free(bp->hwrm_dma_pool, addr, dma_handle);
|
||||
}
|
||||
|
||||
/* void because failure is irrecoverable */
|
||||
void hwrm_req_drop(struct bnxt *bp, void *req)
|
||||
{
|
||||
struct bnxt_hwrm_ctx *ctx = __hwrm_ctx(bp, req);
|
||||
|
||||
if (ctx)
|
||||
__hwrm_ctx_drop(bp, ctx);
|
||||
}
|
||||
|
||||
static int __hwrm_to_stderr(u32 hwrm_err)
|
||||
{
|
||||
switch (hwrm_err) {
|
||||
case HWRM_ERR_CODE_SUCCESS:
|
||||
return 0;
|
||||
case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
|
||||
return -EACCES;
|
||||
case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
|
||||
return -ENOSPC;
|
||||
case HWRM_ERR_CODE_INVALID_PARAMS:
|
||||
case HWRM_ERR_CODE_INVALID_FLAGS:
|
||||
case HWRM_ERR_CODE_INVALID_ENABLES:
|
||||
case HWRM_ERR_CODE_UNSUPPORTED_TLV:
|
||||
case HWRM_ERR_CODE_UNSUPPORTED_OPTION_ERR:
|
||||
return -EINVAL;
|
||||
case HWRM_ERR_CODE_NO_BUFFER:
|
||||
return -ENOMEM;
|
||||
case HWRM_ERR_CODE_HOT_RESET_PROGRESS:
|
||||
case HWRM_ERR_CODE_BUSY:
|
||||
return -EAGAIN;
|
||||
case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
|
||||
return -EOPNOTSUPP;
|
||||
default:
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
static struct bnxt_hwrm_wait_token *
|
||||
__hwrm_acquire_token(struct bnxt *bp, enum bnxt_hwrm_chnl dst)
|
||||
__acquires(&bp->hwrm_cmd_lock)
|
||||
{
|
||||
struct bnxt_hwrm_wait_token *token;
|
||||
|
||||
token = kzalloc(sizeof(*token), GFP_KERNEL);
|
||||
if (!token)
|
||||
return NULL;
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
|
||||
token->dst = dst;
|
||||
token->state = BNXT_HWRM_PENDING;
|
||||
if (dst == BNXT_HWRM_CHNL_CHIMP) {
|
||||
token->seq_id = bp->hwrm_cmd_seq++;
|
||||
hlist_add_head_rcu(&token->node, &bp->hwrm_pending_list);
|
||||
} else {
|
||||
token->seq_id = bp->hwrm_cmd_kong_seq++;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
static void
|
||||
__hwrm_release_token(struct bnxt *bp, struct bnxt_hwrm_wait_token *token)
|
||||
__releases(&bp->hwrm_cmd_lock)
|
||||
{
|
||||
if (token->dst == BNXT_HWRM_CHNL_CHIMP) {
|
||||
hlist_del_rcu(&token->node);
|
||||
kfree_rcu(token, rcu);
|
||||
} else {
|
||||
kfree(token);
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
}
|
||||
|
||||
void
|
||||
hwrm_update_token(struct bnxt *bp, u16 seq_id, enum bnxt_hwrm_wait_state state)
|
||||
{
|
||||
struct hlist_node __maybe_unused *dummy;
|
||||
struct bnxt_hwrm_wait_token *token;
|
||||
|
||||
rcu_read_lock();
|
||||
__hlist_for_each_entry_rcu(token, dummy, &bp->hwrm_pending_list, node) {
|
||||
if (token->seq_id == seq_id) {
|
||||
WRITE_ONCE(token->state, state);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
netdev_err(bp->dev, "Invalid hwrm seq id %d\n", seq_id);
|
||||
}
|
||||
|
||||
static int __hwrm_send(struct bnxt *bp, struct bnxt_hwrm_ctx *ctx)
|
||||
{
|
||||
u32 doorbell_offset = BNXT_GRCPF_REG_CHIMP_COMM_TRIGGER;
|
||||
enum bnxt_hwrm_chnl dst = BNXT_HWRM_CHNL_CHIMP;
|
||||
u32 bar_offset = BNXT_GRCPF_REG_CHIMP_COMM;
|
||||
struct bnxt_hwrm_wait_token *token = NULL;
|
||||
struct hwrm_short_input short_input = {0};
|
||||
u16 max_req_len = BNXT_HWRM_MAX_REQ_LEN;
|
||||
int i, timeout, tmo_count, rc = -EBUSY;
|
||||
u32 *data = (u32 *)ctx->req;
|
||||
u32 msg_len = ctx->req_len;
|
||||
u16 len = 0;
|
||||
u8 *valid;
|
||||
|
||||
#ifndef HSI_DBG_DISABLE
|
||||
decode_hwrm_req(ctx->req);
|
||||
#endif
|
||||
|
||||
if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
|
||||
goto exit;
|
||||
|
||||
if (msg_len > BNXT_HWRM_MAX_REQ_LEN &&
|
||||
msg_len > bp->hwrm_max_ext_req_len) {
|
||||
rc = -E2BIG;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (hwrm_req_kong(bp, ctx->req)) {
|
||||
dst = BNXT_HWRM_CHNL_KONG;
|
||||
bar_offset = BNXT_GRCPF_REG_KONG_COMM;
|
||||
doorbell_offset = BNXT_GRCPF_REG_KONG_COMM_TRIGGER;
|
||||
if (le16_to_cpu(ctx->req->cmpl_ring) != INVALID_HW_RING_ID) {
|
||||
netdev_err(bp->dev, "Ring completions not supported for KONG commands, req_type = %d\n",
|
||||
(u32)le16_to_cpu(ctx->req->req_type));
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->flags & BNXT_HWRM_RESP_DIRTY)
|
||||
memset(ctx->resp, 0, PAGE_SIZE);
|
||||
|
||||
token = __hwrm_acquire_token(bp, dst);
|
||||
if (!token) {
|
||||
rc = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
ctx->req->seq_id = cpu_to_le16(token->seq_id);
|
||||
|
||||
if ((bp->fw_cap & BNXT_FW_CAP_SHORT_CMD) ||
|
||||
msg_len > BNXT_HWRM_MAX_REQ_LEN) {
|
||||
short_input.req_type = ctx->req->req_type;
|
||||
short_input.signature =
|
||||
cpu_to_le16(SHORT_REQ_SIGNATURE_SHORT_CMD);
|
||||
short_input.size = cpu_to_le16(msg_len);
|
||||
short_input.req_addr = cpu_to_le64(ctx->dma_handle);
|
||||
|
||||
data = (u32 *)&short_input;
|
||||
msg_len = sizeof(short_input);
|
||||
|
||||
max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
|
||||
}
|
||||
|
||||
/* Ensure any associated DMA buffers are written before doorbell */
|
||||
wmb();
|
||||
|
||||
/* Write request msg to hwrm channel */
|
||||
__iowrite32_copy(bp->bar0 + bar_offset, data, msg_len / 4);
|
||||
|
||||
for (i = msg_len; i < max_req_len; i += 4)
|
||||
writel(0, bp->bar0 + bar_offset + i);
|
||||
|
||||
ptp_read_system_prets(ctx->sts);
|
||||
|
||||
/* Ring channel doorbell */
|
||||
writel(1, bp->bar0 + doorbell_offset);
|
||||
|
||||
if (!pci_is_enabled(bp->pdev)) {
|
||||
rc = 0; /* don't wait for response during error recovery */
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* convert timeout to usec */
|
||||
timeout = ctx->timeout * 1000;
|
||||
|
||||
i = 0;
|
||||
/* Short timeout for the first few iterations:
|
||||
* number of loops = number of loops for short timeout +
|
||||
* number of loops for standard timeout.
|
||||
*/
|
||||
tmo_count = HWRM_SHORT_TIMEOUT_COUNTER;
|
||||
timeout = timeout - HWRM_SHORT_MIN_TIMEOUT * HWRM_SHORT_TIMEOUT_COUNTER;
|
||||
tmo_count += DIV_ROUND_UP(timeout, HWRM_MIN_TIMEOUT);
|
||||
|
||||
if (le16_to_cpu(ctx->req->cmpl_ring) != INVALID_HW_RING_ID) {
|
||||
/* Wait until hwrm response cmpl interrupt is processed */
|
||||
while (READ_ONCE(token->state) < BNXT_HWRM_COMPLETE &&
|
||||
i++ < tmo_count) {
|
||||
/* Abort the wait for completion if the FW health
|
||||
* check has failed.
|
||||
*/
|
||||
if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
|
||||
goto exit;
|
||||
/* on first few passes, just barely sleep */
|
||||
if (i < HWRM_SHORT_TIMEOUT_COUNTER)
|
||||
usleep_range(HWRM_SHORT_MIN_TIMEOUT,
|
||||
HWRM_SHORT_MAX_TIMEOUT);
|
||||
else
|
||||
usleep_range(HWRM_MIN_TIMEOUT,
|
||||
HWRM_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
if (READ_ONCE(token->state) != BNXT_HWRM_COMPLETE) {
|
||||
if (!(ctx->flags & BNXT_HWRM_CTX_SILENT))
|
||||
netdev_err(bp->dev, "Resp cmpl intr err msg: 0x%x\n",
|
||||
le16_to_cpu(ctx->req->req_type));
|
||||
goto exit;
|
||||
}
|
||||
len = le16_to_cpu(ctx->resp->resp_len);
|
||||
valid = ((u8 *)ctx->resp) + len - 1;
|
||||
} else {
|
||||
int j;
|
||||
|
||||
/* Check if response len is updated */
|
||||
for (i = 0; i < tmo_count; i++) {
|
||||
/* Abort the wait for completion if the FW health
|
||||
* check has failed.
|
||||
*/
|
||||
if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
|
||||
goto exit;
|
||||
|
||||
if (token &&
|
||||
READ_ONCE(token->state) == BNXT_HWRM_DEFERRED) {
|
||||
__hwrm_release_token(bp, token);
|
||||
token = NULL;
|
||||
}
|
||||
|
||||
len = le16_to_cpu(ctx->resp->resp_len);
|
||||
if (len)
|
||||
break;
|
||||
/* on first few passes, just barely sleep */
|
||||
if (i < HWRM_SHORT_TIMEOUT_COUNTER)
|
||||
usleep_range(HWRM_SHORT_MIN_TIMEOUT,
|
||||
HWRM_SHORT_MAX_TIMEOUT);
|
||||
else
|
||||
usleep_range(HWRM_MIN_TIMEOUT,
|
||||
HWRM_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
if (i >= tmo_count) {
|
||||
if (!(ctx->flags & BNXT_HWRM_CTX_SILENT))
|
||||
netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d\n",
|
||||
hwrm_total_timeout(i),
|
||||
le16_to_cpu(ctx->req->req_type),
|
||||
le16_to_cpu(ctx->req->seq_id), len);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Last byte of resp contains valid bit */
|
||||
valid = ((u8 *)ctx->resp) + len - 1;
|
||||
for (j = 0; j < HWRM_VALID_BIT_DELAY_USEC; j++) {
|
||||
/* make sure we read from updated DMA memory */
|
||||
dma_rmb();
|
||||
if (*valid)
|
||||
break;
|
||||
usleep_range(1, 5);
|
||||
}
|
||||
|
||||
if (j >= HWRM_VALID_BIT_DELAY_USEC) {
|
||||
if (!(ctx->flags & BNXT_HWRM_CTX_SILENT))
|
||||
netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d v:%d\n",
|
||||
hwrm_total_timeout(i),
|
||||
le16_to_cpu(ctx->req->req_type),
|
||||
le16_to_cpu(ctx->req->seq_id), len,
|
||||
*valid);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Zero valid bit for compatibility. Valid bit in an older spec
|
||||
* may become a new field in a newer spec. We must make sure that
|
||||
* a new field not implemented by old spec will read zero.
|
||||
*/
|
||||
*valid = 0;
|
||||
rc = le16_to_cpu(ctx->resp->error_code);
|
||||
if (rc && !(ctx->flags & BNXT_HWRM_CTX_SILENT)) {
|
||||
if (rc == HWRM_ERR_CODE_BUSY)
|
||||
netdev_warn(bp->dev, "FW returned busy, hwrm req_type 0x%x\n",
|
||||
le16_to_cpu(ctx->resp->req_type));
|
||||
else
|
||||
netdev_err(bp->dev, "hwrm req_type 0x%x seq id 0x%x error 0x%x\n",
|
||||
le16_to_cpu(ctx->resp->req_type),
|
||||
le16_to_cpu(ctx->resp->seq_id), rc);
|
||||
}
|
||||
#ifndef HSI_DBG_DISABLE
|
||||
decode_hwrm_resp(ctx->resp);
|
||||
#endif
|
||||
rc = __hwrm_to_stderr(rc);
|
||||
exit:
|
||||
ptp_read_system_postts(ctx->sts);
|
||||
if (token)
|
||||
__hwrm_release_token(bp, token);
|
||||
if (ctx->flags & BNXT_HWRM_CTX_OWNED)
|
||||
ctx->flags |= BNXT_HWRM_RESP_DIRTY;
|
||||
else
|
||||
__hwrm_ctx_drop(bp, ctx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int hwrm_req_send(struct bnxt *bp, void *req)
|
||||
{
|
||||
struct bnxt_hwrm_ctx *ctx = __hwrm_ctx(bp, req);
|
||||
|
||||
if (!ctx)
|
||||
return -EINVAL;
|
||||
|
||||
return __hwrm_send(bp, ctx);
|
||||
}
|
||||
|
||||
int hwrm_req_send_silent(struct bnxt *bp, void *req)
|
||||
{
|
||||
hwrm_req_silence(bp, req);
|
||||
return hwrm_req_send(bp, req);
|
||||
}
|
||||
|
||||
void *
|
||||
hwrm_req_dma_slice(struct bnxt *bp, void *req, u32 size, dma_addr_t *dma_handle)
|
||||
{
|
||||
struct bnxt_hwrm_ctx *ctx = __hwrm_ctx(bp, req);
|
||||
u8 *end = ((u8 *)req) + BNXT_HWRM_DMA_SIZE;
|
||||
struct input *input = req;
|
||||
u8 *addr, *req_addr = req;
|
||||
u32 max_offset, offset;
|
||||
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
max_offset = BNXT_HWRM_DMA_SIZE - ctx->allocated;
|
||||
offset = max_offset - size;
|
||||
offset = ALIGN_DOWN(offset, BNXT_HWRM_DMA_ALIGN);
|
||||
addr = req_addr + offset;
|
||||
|
||||
if (addr < req_addr + max_offset && req_addr + ctx->req_len <= addr) {
|
||||
ctx->allocated = end - addr;
|
||||
*dma_handle = ctx->dma_handle + offset;
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* could not suballocate from ctx buffer, try create a new mapping */
|
||||
if (ctx->slice_addr) {
|
||||
/* if one exists, can only be due to software bug, be loud */
|
||||
netdev_err(bp->dev, "HWRM refusing to reallocate DMA slice, req_type = %u\n",
|
||||
(u32)le16_to_cpu(input->req_type));
|
||||
dump_stack();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
addr = dma_alloc_coherent(&bp->pdev->dev, size, dma_handle, ctx->gfp);
|
||||
|
||||
if (!addr)
|
||||
return NULL;
|
||||
|
||||
ctx->slice_addr = addr;
|
||||
ctx->slice_size = size;
|
||||
ctx->slice_handle = *dma_handle;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
|
@ -0,0 +1,357 @@
|
|||
/* Broadcom NetXtreme-C/E network driver.
|
||||
*
|
||||
* Copyright (c) 2020 Broadcom Limited
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef BNXT_HWRM_H
|
||||
#define BNXT_HWRM_H
|
||||
|
||||
#include "bnxt_hsi.h"
|
||||
|
||||
enum bnxt_hwrm_ctx_flags {
|
||||
BNXT_HWRM_CTX_OWNED = BIT(0), /* caller owns the context */
|
||||
BNXT_HWRM_CTX_SILENT = BIT(1), /* squelch firmware errors */
|
||||
BNXT_HWRM_RESP_DIRTY = BIT(2), /* response contains data */
|
||||
};
|
||||
|
||||
struct bnxt_hwrm_ctx {
|
||||
u64 sentinel;
|
||||
dma_addr_t dma_handle;
|
||||
struct output *resp;
|
||||
struct input *req;
|
||||
dma_addr_t slice_handle;
|
||||
void *slice_addr;
|
||||
struct ptp_system_timestamp *sts;
|
||||
u32 slice_size;
|
||||
u32 req_len;
|
||||
enum bnxt_hwrm_ctx_flags flags;
|
||||
int timeout;
|
||||
u32 allocated;
|
||||
gfp_t gfp;
|
||||
};
|
||||
|
||||
enum bnxt_hwrm_wait_state {
|
||||
BNXT_HWRM_PENDING,
|
||||
BNXT_HWRM_DEFERRED,
|
||||
BNXT_HWRM_COMPLETE,
|
||||
BNXT_HWRM_CANCELLED,
|
||||
};
|
||||
|
||||
enum bnxt_hwrm_chnl { BNXT_HWRM_CHNL_CHIMP, BNXT_HWRM_CHNL_KONG };
|
||||
|
||||
struct bnxt_hwrm_wait_token {
|
||||
struct rcu_head rcu;
|
||||
struct hlist_node node;
|
||||
enum bnxt_hwrm_wait_state state;
|
||||
enum bnxt_hwrm_chnl dst;
|
||||
u16 seq_id;
|
||||
};
|
||||
|
||||
void hwrm_update_token(struct bnxt *bp, u16 seq, enum bnxt_hwrm_wait_state s);
|
||||
|
||||
#define BNXT_HWRM_MAX_REQ_LEN (bp->hwrm_max_req_len)
|
||||
#define BNXT_HWRM_SHORT_REQ_LEN sizeof(struct hwrm_short_input)
|
||||
#define SHORT_HWRM_CMD_TIMEOUT 20
|
||||
#define HWRM_CMD_TIMEOUT (bp->hwrm_cmd_timeout)
|
||||
#define HWRM_RESET_TIMEOUT ((HWRM_CMD_TIMEOUT) * 4)
|
||||
#define HWRM_COREDUMP_TIMEOUT ((HWRM_CMD_TIMEOUT) * 12)
|
||||
#define BNXT_HWRM_TARGET 0xffff
|
||||
#define BNXT_HWRM_NO_CMPL_RING -1
|
||||
#define BNXT_HWRM_REQ_MAX_SIZE 128
|
||||
#define BNXT_HWRM_DMA_SIZE (2 * PAGE_SIZE) /* space for req+resp */
|
||||
#define BNXT_HWRM_RESP_RESERVED PAGE_SIZE
|
||||
#define BNXT_HWRM_RESP_OFFSET (BNXT_HWRM_DMA_SIZE - \
|
||||
BNXT_HWRM_RESP_RESERVED)
|
||||
#define BNXT_HWRM_CTX_OFFSET (BNXT_HWRM_RESP_OFFSET - \
|
||||
sizeof(struct bnxt_hwrm_ctx))
|
||||
#define BNXT_HWRM_DMA_ALIGN 16
|
||||
#define BNXT_HWRM_SENTINEL 0xb6e1f68a12e9a7eb /* arbitrary value */
|
||||
#define BNXT_HWRM_REQS_PER_PAGE (BNXT_PAGE_SIZE / \
|
||||
BNXT_HWRM_REQ_MAX_SIZE)
|
||||
#define HWRM_SHORT_MIN_TIMEOUT 3
|
||||
#define HWRM_SHORT_MAX_TIMEOUT 10
|
||||
#define HWRM_SHORT_TIMEOUT_COUNTER 5
|
||||
|
||||
#define HWRM_MIN_TIMEOUT 25
|
||||
#define HWRM_MAX_TIMEOUT 40
|
||||
|
||||
static inline int hwrm_total_timeout(int n)
|
||||
{
|
||||
return n <= HWRM_SHORT_TIMEOUT_COUNTER ? n * HWRM_SHORT_MIN_TIMEOUT :
|
||||
HWRM_SHORT_TIMEOUT_COUNTER * HWRM_SHORT_MIN_TIMEOUT +
|
||||
(n - HWRM_SHORT_TIMEOUT_COUNTER) * HWRM_MIN_TIMEOUT;
|
||||
}
|
||||
|
||||
#define HWRM_VALID_BIT_DELAY_USEC 150
|
||||
|
||||
static inline bool hwrm_req_type_cfa(u16 req_type)
|
||||
{
|
||||
switch (req_type) {
|
||||
case HWRM_CFA_ENCAP_RECORD_ALLOC:
|
||||
case HWRM_CFA_ENCAP_RECORD_FREE:
|
||||
case HWRM_CFA_DECAP_FILTER_ALLOC:
|
||||
case HWRM_CFA_DECAP_FILTER_FREE:
|
||||
case HWRM_CFA_EM_FLOW_ALLOC:
|
||||
case HWRM_CFA_EM_FLOW_FREE:
|
||||
case HWRM_CFA_EM_FLOW_CFG:
|
||||
case HWRM_CFA_FLOW_ALLOC:
|
||||
case HWRM_CFA_FLOW_FREE:
|
||||
case HWRM_CFA_FLOW_INFO:
|
||||
case HWRM_CFA_FLOW_FLUSH:
|
||||
case HWRM_CFA_FLOW_STATS:
|
||||
case HWRM_CFA_METER_PROFILE_ALLOC:
|
||||
case HWRM_CFA_METER_PROFILE_FREE:
|
||||
case HWRM_CFA_METER_PROFILE_CFG:
|
||||
case HWRM_CFA_METER_INSTANCE_ALLOC:
|
||||
case HWRM_CFA_METER_INSTANCE_FREE:
|
||||
case HWRM_CFA_EEM_QCAPS:
|
||||
case HWRM_CFA_EEM_OP:
|
||||
case HWRM_CFA_EEM_CFG:
|
||||
case HWRM_CFA_EEM_QCFG:
|
||||
case HWRM_CFA_CTX_MEM_RGTR:
|
||||
case HWRM_CFA_CTX_MEM_UNRGTR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool hwrm_req_kong(struct bnxt *bp, struct input *req)
|
||||
{
|
||||
return (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL &&
|
||||
(hwrm_req_type_cfa(le16_to_cpu(req->req_type)) ||
|
||||
le16_to_cpu(req->target_id) == HWRM_TARGET_ID_KONG));
|
||||
}
|
||||
|
||||
/**
|
||||
* __hwrm_req_init() - Initialize an HWRM request.
|
||||
* @bp: The driver context.
|
||||
* @req: A pointer to the request pointer to initialize.
|
||||
* @req_type: The request type. This will be converted to the little endian
|
||||
* before being written to the req_type field of the returned request.
|
||||
* @req_len: The length of the request to be allocated.
|
||||
*
|
||||
* Allocate DMA resources and initialize a new HWRM request object of the
|
||||
* given type. The response address field in the request is configured with
|
||||
* the DMA bus address that has been mapped for the response and the passed
|
||||
* request is pointed to kernel virtual memory mapped for the request (such
|
||||
* that short_input indirection can be accomplished without copying). The
|
||||
* request’s target and completion ring are initialized to default values and
|
||||
* can be overridden by writing to the returned request object directly.
|
||||
*
|
||||
* The initialized request can be further customized by writing to its fields
|
||||
* directly, taking care to covert such fields to little endian. The request
|
||||
* object will be consumed (and all its associated resources release) upon
|
||||
* passing it to hwrm_req_send() unless ownership of the request has been
|
||||
* claimed by the caller via a call to hwrm_req_hold(). If the request is not
|
||||
* consumed, either because it is never sent or because ownership has been
|
||||
* claimed, then it must be released by a call to hwrm_req_drop().
|
||||
*
|
||||
* Return: zero on success, negative error code otherwise:
|
||||
* E2BIG: the type of request pointer is too large to fit.
|
||||
* ENOMEM: an allocation failure occurred.
|
||||
*/
|
||||
int __hwrm_req_init(struct bnxt *bp, void **req, u16 req_type, u32 req_len);
|
||||
#define hwrm_req_init(bp, req, req_type) \
|
||||
__hwrm_req_init((bp), (void **)&(req), (req_type), sizeof(*(req)))
|
||||
|
||||
/**
|
||||
* hwrm_req_hold() - Claim ownership of the request's resources.
|
||||
* @bp: The driver context.
|
||||
* @req: A pointer to the request to own. The request will no longer be
|
||||
* consumed by calls to hwrm_req_send().
|
||||
*
|
||||
* Take ownership of the request. Ownership places responsibility on the
|
||||
* caller to free the resources associated with the request via a call to
|
||||
* hwrm_req_drop(). The caller taking ownership implies that a subsequent
|
||||
* call to hwrm_req_send() will not consume the request (ie. sending will
|
||||
* not free the associated resources if the request is owned by the caller).
|
||||
* Taking ownership returns a reference to the response. Retaining and
|
||||
* accessing the response data is the most common reason to take ownership
|
||||
* of the request. Ownership can also be acquired in order to reuse the same
|
||||
* request object across multiple invocations of hwrm_req_send().
|
||||
*
|
||||
* Return: A pointer to the response object.
|
||||
*
|
||||
* The resources associated with the response will remain available to the
|
||||
* caller until ownership of the request is relinquished via a call to
|
||||
* hwrm_req_drop(). It is not possible for hwrm_req_hold() to return NULL if
|
||||
* a valid request is provided. A returned NULL value would imply a driver
|
||||
* bug and the implementation will complain loudly in the logs to aid in
|
||||
* detection. It should not be necessary to check the result for NULL.
|
||||
*/
|
||||
void *hwrm_req_hold(struct bnxt *bp, void *req);
|
||||
|
||||
/**
|
||||
* hwrm_req_drop() - Release all resources associated with the request.
|
||||
* @bp: The driver context.
|
||||
* @req: The request to consume, releasing the associated resources. The
|
||||
* request object, any slices, and its associated response are no
|
||||
* longer valid.
|
||||
*
|
||||
* It is legal to call hwrm_req_drop() on an unowned request, provided it
|
||||
* has not already been consumed by hwrm_req_send() (for example, to release
|
||||
* an aborted request). A given request should not be dropped more than once,
|
||||
* nor should it be dropped after having been consumed by hwrm_req_send(). To
|
||||
* do so is an error (the context will not be found and a stack trace will be
|
||||
* rendered in the kernel log).
|
||||
*/
|
||||
void hwrm_req_drop(struct bnxt *bp, void *req);
|
||||
|
||||
/**
|
||||
* hwrm_req_silence() - Do not log HWRM errors.
|
||||
* @bp: The driver context.
|
||||
* @req: The request to silence.
|
||||
*
|
||||
* Do not print HWRM errors to the kernel log for the associated request
|
||||
* during a subsequent call to hwrm_req_send(). Some requests are expected
|
||||
* to fail in certain scenarios and, as such, errors should be suppressed.
|
||||
*/
|
||||
void hwrm_req_silence(struct bnxt *bp, void *req);
|
||||
|
||||
/**
|
||||
* hwrm_req_timeout() - Set the completion timeout for the request.
|
||||
* @bp: The driver context.
|
||||
* @req: The request to set the timeout.
|
||||
* @timeout: The timeout in milliseconds.
|
||||
*
|
||||
* Set the timeout associated with the request for subsequent calls to
|
||||
* hwrm_req_send(). Some requests are long running and require a different
|
||||
* timeout than the default.
|
||||
*/
|
||||
void hwrm_req_timeout(struct bnxt *bp, void *req, int timeout);
|
||||
|
||||
/**
|
||||
* hwrm_req_send() - Execute an HWRM command.
|
||||
* @bp: The driver context.
|
||||
* @req: A pointer to the request to send. The DMA resources associated with
|
||||
* the request will be released (ie. the request will be consumed) unless
|
||||
* ownership of the request has been assumed by the caller via a call to
|
||||
* hwrm_req_hold().
|
||||
*
|
||||
* Send an HWRM request to the device and wait for a response. The request is
|
||||
* consumed if it is not owned by the caller. This function will block until
|
||||
* the request has either completed or times out due to an error.
|
||||
*
|
||||
* Return: A result code.
|
||||
*
|
||||
* The result is zero on success, otherwise the negative error code indicates
|
||||
* one of the following errors:
|
||||
* E2BIG: The request was too large.
|
||||
* EBUSY: The firmware is in a fatal state or the request timed out
|
||||
* EACCESS: HWRM access denied.
|
||||
* ENOSPC: HWRM resource allocation error.
|
||||
* EINVAL: Request parameters are invalid.
|
||||
* ENOMEM: HWRM has no buffers.
|
||||
* EAGAIN: HWRM busy or reset in progress.
|
||||
* EOPNOTSUPP: Invalid request type.
|
||||
* EIO: Any other error.
|
||||
* Error handling is orthogonal to request ownership. An unowned request will
|
||||
* still be consumed on error. If the caller owns the request, then the caller
|
||||
* is responsible for releasing the resources. Otherwise, hwrm_req_send() will
|
||||
* always consume the request.
|
||||
*/
|
||||
int hwrm_req_send(struct bnxt *bp, void *req);
|
||||
|
||||
/**
|
||||
* hwrm_req_send_silent() - A silent version of hwrm_req_send().
|
||||
* @bp: The driver context.
|
||||
* @req: The request to send without logging.
|
||||
*
|
||||
* The same as hwrm_req_send(), except that the request is silenced using
|
||||
* hwrm_req_silence() prior the call. This version of the function is
|
||||
* provided solely to preserve the legacy API’s flavor for this functionality.
|
||||
*
|
||||
* Return: A result code, see hwrm_req_send().
|
||||
*/
|
||||
int hwrm_req_send_silent(struct bnxt *bp, void *req);
|
||||
|
||||
/**
|
||||
* hwrm_req_replace() - Replace request data.
|
||||
* @bp: The driver context.
|
||||
* @req: The request to modify. A call to hwrm_req_replace() is conceptually
|
||||
* an assignment of new_req to req. Subsequent calls to HWRM API functions,
|
||||
* such as hwrm_req_send(), should thus use req and not new_req (in fact,
|
||||
* calls to HWRM API functions will fail if non-managed request objects
|
||||
* are passed).
|
||||
* @len: The length of new_req.
|
||||
* @new_req: The pre-built request to copy or reference.
|
||||
*
|
||||
* Replaces the request data in req with that of new_req. This is useful in
|
||||
* scenarios where a request object has already been constructed by a third
|
||||
* party prior to creating a resource managed request using hwrm_req_init().
|
||||
* Depending on the length, hwrm_req_replace() will either copy the new
|
||||
* request data into the DMA memory allocated for req, or it will simply
|
||||
* reference the new request and use it in lieu of req during subsequent
|
||||
* calls to hwrm_req_send(). The resource management is associated with
|
||||
* req and is independent of and does not apply to new_req. The caller must
|
||||
* ensure that the lifetime of new_req is least as long as req. Any slices
|
||||
* that may have been associated with the original request are released.
|
||||
*
|
||||
* Return: zero on success, negative error code otherwise:
|
||||
* E2BIG: Request is too large.
|
||||
* EINVAL: Invalid request to modify.
|
||||
*/
|
||||
int hwrm_req_replace(struct bnxt *bp, void *req, void *new_req, u32 len);
|
||||
|
||||
/**
|
||||
* hwrm_req_alloc_flags() - Sets GFP allocation flags for slices.
|
||||
* @bp: The driver context.
|
||||
* @req: The request for which calls to hwrm_req_dma_slice() will have altered
|
||||
* allocation flags.
|
||||
* @flags: A bitmask of GFP flags. These flags are passed to
|
||||
* dma_alloc_coherent() whenever it is used to allocate backing memory
|
||||
* for slices. Note that calls to hwrm_req_dma_slice() will not always
|
||||
* result in new allocations, however, memory suballocated from the
|
||||
* request buffer is already __GFP_ZERO.
|
||||
*
|
||||
* Sets the GFP allocation flags associated with the request for subsequent
|
||||
* calls to hwrm_req_dma_slice(). This can be useful for specifying __GFP_ZERO
|
||||
* for slice allocations.
|
||||
*/
|
||||
void hwrm_req_alloc_flags(struct bnxt *bp, void *req, gfp_t flags);
|
||||
|
||||
/**
|
||||
* hwrm_req_dma_slice() - Allocate a slice of DMA mapped memory.
|
||||
* @bp: The driver context.
|
||||
* @req: The request for which indirect data will be associated.
|
||||
* @size: The size of the allocation.
|
||||
* @dma: The bus address associated with the allocation. The HWRM API has no
|
||||
* knowledge about the type of the request and so cannot infer how the
|
||||
* caller intends to use the indirect data. Thus, the caller is
|
||||
* responsible for configuring the request object appropriately to
|
||||
* point to the associated indirect memory. Note, DMA handle has the
|
||||
* same definition as it does in dma_alloc_coherent(), the caller is
|
||||
* responsible for endian conversions via cpu_to_le64() before assigning
|
||||
* this address.
|
||||
*
|
||||
* Allocates DMA mapped memory for indirect data related to a request. The
|
||||
* lifetime of the DMA resources will be bound to that of the request (ie.
|
||||
* they will be automatically released when the request is either consumed by
|
||||
* hwrm_req_send() or dropped by hwrm_req_drop()). Small allocations are
|
||||
* efficiently suballocated out of the request buffer space, hence the name
|
||||
* slice, while larger requests are satisfied via an underlying call to
|
||||
* dma_alloc_coherent(). Multiple suballocations are supported, however, only
|
||||
* one externally mapped region is.
|
||||
*
|
||||
* Return: The kernel virtual address of the DMA mapping.
|
||||
*/
|
||||
void *hwrm_req_dma_slice(struct bnxt *bp, void *req, u32 size, dma_addr_t *dma);
|
||||
|
||||
/**
|
||||
* hwrm_req_capture_ts() - Get system time into PTP provided time structure
|
||||
* @bp: The driver context.
|
||||
* @req: The request to query free running timer of the NIC
|
||||
* @sts: System provided ptp_system_timestamp structure
|
||||
*
|
||||
* PTP's gettimex64() optionally provides a system timestamp structure that
|
||||
* driver should update. This function sets the sts member of bnxt_hwrm_ctx
|
||||
* associated with the request. The __hwrm_send() will eventually update the
|
||||
* pre and post system time in this structure when executing the gettimex64()
|
||||
*/
|
||||
void hwrm_req_capture_ts(struct bnxt *bp, void *req, struct ptp_system_timestamp *sts);
|
||||
#endif
|
||||
|
|
@ -18,10 +18,13 @@
|
|||
#include <linux/uaccess.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_eem.h"
|
||||
#include "bnxt_hwrm.h"
|
||||
#include "bnxt_ulp.h"
|
||||
#include "bnxt_lfc.h"
|
||||
#include "bnxt_lfc_ioctl.h"
|
||||
|
|
@ -546,6 +549,394 @@ err1:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void bnxt_eem_dmabuf_release(struct bnxt *bp,
|
||||
struct bnxt_eem_dmabuf_info *dmabuf_priv)
|
||||
{
|
||||
struct bnxt_eem_dmabuf_info *priv;
|
||||
int tbl_type;
|
||||
int dir;
|
||||
|
||||
for (dir = BNXT_EEM_DIR_TX; dir < BNXT_EEM_NUM_DIR; dir++) {
|
||||
for (tbl_type = 0; tbl_type < MAX_TABLE; tbl_type++) {
|
||||
if (tbl_type == EFC_TABLE)
|
||||
continue;
|
||||
|
||||
priv = dmabuf_priv + (dir * MAX_TABLE + tbl_type);
|
||||
netdev_dbg(bp->dev,
|
||||
"Dir:%d, tbl_type:%d, priv->fd %d\n",
|
||||
dir, priv->type, priv->fd);
|
||||
|
||||
if (priv->type != MAX_TABLE) {
|
||||
if (priv->buf)
|
||||
dma_buf_put(priv->buf);
|
||||
|
||||
if (priv->pages) {
|
||||
sg_free_table(&priv->sg);
|
||||
kfree(priv->pages);
|
||||
}
|
||||
|
||||
priv->buf = NULL;
|
||||
priv->fd = 0;
|
||||
priv->pages = NULL;
|
||||
priv->type = MAX_TABLE;
|
||||
}
|
||||
}
|
||||
dmabuf_priv->dir &= ~(1 << dir);
|
||||
}
|
||||
}
|
||||
|
||||
static int bnxt_eem_dmabuf_close(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_eem_dmabuf_info *dmabuf_priv;
|
||||
|
||||
if (!bp->dmabuf_data)
|
||||
return 0;
|
||||
|
||||
dmabuf_priv = bp->dmabuf_data;
|
||||
bnxt_eem_dmabuf_release(bp, dmabuf_priv);
|
||||
|
||||
if (!dmabuf_priv->dir) {
|
||||
kfree(dmabuf_priv);
|
||||
bp->dmabuf_data = NULL;
|
||||
netdev_dbg(bp->dev, "release dmabuf data\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t bnxt_lfc_process_dmabuf_close(struct bnxt_lfc_dev *blfc_dev)
|
||||
{
|
||||
struct bnxt *bp = blfc_dev->bp;
|
||||
|
||||
return bnxt_eem_dmabuf_close(bp);
|
||||
}
|
||||
|
||||
static int bnxt_eem_dmabuf_reg(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_eem_dmabuf_info *priv;
|
||||
int i;
|
||||
|
||||
if (bp->dmabuf_data) {
|
||||
bnxt_eem_dmabuf_close(bp);
|
||||
netdev_warn(bp->dev, "clear existed dmabuf\n");
|
||||
}
|
||||
|
||||
priv = kzalloc(sizeof(*priv) * BNXT_EEM_NUM_DIR * MAX_TABLE,
|
||||
GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
bp->dmabuf_data = priv;
|
||||
for (i = 0; i < BNXT_EEM_NUM_DIR * MAX_TABLE; i++) {
|
||||
priv[i].dev = &bp->pdev->dev;
|
||||
priv[i].type = MAX_TABLE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DMABUF_ATTACH_DEV
|
||||
static int bnxt_dmabuf_attach(struct dma_buf *buf, struct device *dev,
|
||||
struct dma_buf_attachment *attach)
|
||||
#else
|
||||
static int bnxt_dmabuf_attach(struct dma_buf *buf,
|
||||
struct dma_buf_attachment *attach)
|
||||
#endif
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bnxt_dmabuf_detach(struct dma_buf *buf,
|
||||
struct dma_buf_attachment *attach)
|
||||
{
|
||||
}
|
||||
|
||||
static
|
||||
struct sg_table *bnxt_dmabuf_map_dma_buf(struct dma_buf_attachment *attach,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void bnxt_dmabuf_unmap_dma_buf(struct dma_buf_attachment *attach,
|
||||
struct sg_table *sgt,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
}
|
||||
|
||||
static void bnxt_dmabuf_release(struct dma_buf *buf)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(HAVE_DMABUF_KMAP_ATOMIC) || defined(HAVE_DMABUF_KMAP) || \
|
||||
defined(HAVE_DMABUF_MAP_ATOMIC) || defined(HAVE_DMABUF_MAP)
|
||||
static void *bnxt_dmabuf_kmap(struct dma_buf *buf, unsigned long page)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void bnxt_dmabuf_kunmap(struct dma_buf *buf, unsigned long page,
|
||||
void *vaddr)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static void bnxt_dmabuf_vm_open(struct vm_area_struct *vma)
|
||||
{
|
||||
}
|
||||
|
||||
static void bnxt_dmabuf_vm_close(struct vm_area_struct *vma)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct vm_operations_struct dmabuf_vm_ops = {
|
||||
.open = bnxt_dmabuf_vm_open,
|
||||
.close = bnxt_dmabuf_vm_close,
|
||||
};
|
||||
|
||||
static int bnxt_dmabuf_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
|
||||
{
|
||||
pgprot_t prot = vm_get_page_prot(vma->vm_flags);
|
||||
struct bnxt_eem_dmabuf_info *priv = buf->priv;
|
||||
int page_block = vma->vm_pgoff / MAX_CTX_PAGES;
|
||||
int page_no = vma->vm_pgoff % MAX_CTX_PAGES;
|
||||
struct bnxt_ctx_pg_info *ctx_pg;
|
||||
dma_addr_t pg_phys;
|
||||
|
||||
vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND;
|
||||
vma->vm_ops = &dmabuf_vm_ops;
|
||||
vma->vm_private_data = priv;
|
||||
vma->vm_page_prot = pgprot_writecombine(prot);
|
||||
|
||||
ctx_pg = priv->tbl->ctx_pg_tbl[page_block];
|
||||
pg_phys = ctx_pg->ctx_dma_arr[page_no];
|
||||
return remap_pfn_range(vma, vma->vm_start, pg_phys >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start, vma->vm_page_prot);
|
||||
}
|
||||
|
||||
static void *bnxt_dmabuf_vmap(struct dma_buf *buf)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void bnxt_dmabuf_vunmap(struct dma_buf *buf, void *vaddr)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct dma_buf_ops bnxt_dmabuf_ops = {
|
||||
.attach = bnxt_dmabuf_attach,
|
||||
.detach = bnxt_dmabuf_detach,
|
||||
.map_dma_buf = bnxt_dmabuf_map_dma_buf,
|
||||
.unmap_dma_buf = bnxt_dmabuf_unmap_dma_buf,
|
||||
.release = bnxt_dmabuf_release,
|
||||
#ifdef HAVE_DMABUF_KMAP_ATOMIC
|
||||
.kmap_atomic = bnxt_dmabuf_kmap,
|
||||
.kunmap_atomic = bnxt_dmabuf_kunmap,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF_KMAP
|
||||
.kmap = bnxt_dmabuf_kmap,
|
||||
.kunmap = bnxt_dmabuf_kunmap,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF_MAP_ATOMIC
|
||||
.map_atomic = bnxt_dmabuf_kmap,
|
||||
.unmap_atomic = bnxt_dmabuf_kunmap,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF_MAP
|
||||
.map = bnxt_dmabuf_kmap,
|
||||
.unmap = bnxt_dmabuf_kunmap,
|
||||
#endif
|
||||
.mmap = bnxt_dmabuf_mmap,
|
||||
.vmap = bnxt_dmabuf_vmap,
|
||||
.vunmap = bnxt_dmabuf_vunmap,
|
||||
};
|
||||
|
||||
static int bnxt_dmabuf_page_map(struct bnxt *bp, int dir, int tbl_type,
|
||||
struct bnxt_eem_dmabuf_info *priv)
|
||||
{
|
||||
struct bnxt_ctx_pg_info *pg_tbl = NULL;
|
||||
struct bnxt_ctx_pg_info *ctx_pg;
|
||||
int page_no = 0;
|
||||
int ctx_block;
|
||||
int i, j;
|
||||
|
||||
priv->tbl = &bp->eem_info->eem_ctx_info[dir].eem_tables[tbl_type];
|
||||
ctx_pg = &bp->eem_info->eem_ctx_info[dir].eem_tables[tbl_type];
|
||||
|
||||
if (!ctx_pg->nr_pages)
|
||||
return -EINVAL;
|
||||
|
||||
priv->pg_count = ctx_pg->nr_pages;
|
||||
priv->pages = kcalloc(priv->pg_count, sizeof(*priv->pages), GFP_KERNEL);
|
||||
if (!priv->pages)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx_block = priv->pg_count / MAX_CTX_PAGES;
|
||||
for (i = 0; i < ctx_block; i++) {
|
||||
pg_tbl = ctx_pg->ctx_pg_tbl[i];
|
||||
if (pg_tbl) {
|
||||
for (j = 0; j < MAX_CTX_PAGES; j++) {
|
||||
priv->pages[page_no] =
|
||||
virt_to_page(pg_tbl->ctx_pg_arr[j]);
|
||||
page_no++;
|
||||
if (page_no == priv->pg_count)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sg_alloc_table_from_pages(&priv->sg, priv->pages, priv->pg_count,
|
||||
0, (priv->pg_count << PAGE_SHIFT),
|
||||
GFP_KERNEL)) {
|
||||
kfree(priv->pages);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!dma_map_sg(priv->dev, priv->sg.sgl,
|
||||
priv->sg.nents, DMA_BIDIRECTIONAL)) {
|
||||
sg_free_table(&priv->sg);
|
||||
kfree(priv->pages);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_dmabuf_export(struct bnxt_eem_dmabuf_info *priv)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
priv->buf = dma_buf_export_attr(priv, priv->pg_count, &bnxt_dmabuf_ops);
|
||||
if (!priv->buf)
|
||||
rc = -EBUSY;
|
||||
|
||||
if (IS_ERR(priv->buf))
|
||||
rc = PTR_ERR(priv->buf);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_eem_dmabuf_export(struct bnxt *bp, u32 flags)
|
||||
{
|
||||
struct bnxt_eem_dmabuf_info *dmabuf_priv;
|
||||
struct bnxt_eem_dmabuf_info *priv;
|
||||
int tbl_type;
|
||||
int dir;
|
||||
int rc;
|
||||
|
||||
dmabuf_priv = bp->dmabuf_data;
|
||||
for (dir = BNXT_EEM_DIR_TX; dir < BNXT_EEM_NUM_DIR; dir++) {
|
||||
for (tbl_type = KEY0_TABLE; tbl_type < MAX_TABLE; tbl_type++) {
|
||||
if (tbl_type == EFC_TABLE)
|
||||
continue;
|
||||
|
||||
priv = dmabuf_priv + (dir * MAX_TABLE + tbl_type);
|
||||
netdev_dbg(bp->dev,
|
||||
"export: dir %d, tbl:%d\n", dir, tbl_type);
|
||||
|
||||
if (priv->type != MAX_TABLE && priv->fd) {
|
||||
rc = -EIO;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = bnxt_dmabuf_page_map(bp, dir, tbl_type, priv);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = bnxt_dmabuf_export(priv);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
priv->type = tbl_type;
|
||||
}
|
||||
dmabuf_priv->dir |= (1 << dir);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_eem_dmabuf_fd(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_eem_dmabuf_info *priv;
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
if (!bp->dmabuf_data) {
|
||||
netdev_err(bp->dev, "Failed to export dmabuf file");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (priv = bp->dmabuf_data, i = 0;
|
||||
i < BNXT_EEM_NUM_DIR * MAX_TABLE; i++, priv++) {
|
||||
if (!priv->buf) {
|
||||
priv->fd = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
get_dma_buf(priv->buf);
|
||||
fd = dma_buf_fd(priv->buf, O_ACCMODE);
|
||||
if (fd < 0) {
|
||||
dma_buf_put(priv->buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
priv->fd = fd;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_eem_dmabuf_export_fd(struct bnxt *bp)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = bnxt_eem_dmabuf_reg(bp);
|
||||
if (rc) {
|
||||
netdev_err(bp->dev, "dmabuf private data initial failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = bnxt_eem_dmabuf_export(bp, O_ACCMODE);
|
||||
if (rc) {
|
||||
netdev_err(bp->dev, "prepare dmabuf fail.\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
rc = bnxt_eem_dmabuf_fd(bp);
|
||||
if (rc) {
|
||||
netdev_err(bp->dev, "dmabuf fd fail.\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
return rc;
|
||||
clean:
|
||||
bnxt_eem_dmabuf_close(bp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static
|
||||
int32_t bnxt_lfc_process_dmabuf_export(struct bnxt_lfc_dev *blfc_dev,
|
||||
struct bnxt_lfc_req *lfc_req)
|
||||
{
|
||||
struct bnxt_lfc_dmabuf_fd dmabuf_fd;
|
||||
struct bnxt_eem_dmabuf_info *priv;
|
||||
struct bnxt *bp = blfc_dev->bp;
|
||||
int32_t rc;
|
||||
int i;
|
||||
|
||||
rc = bnxt_eem_dmabuf_export_fd(bp);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
for (priv = bp->dmabuf_data, i = 0;
|
||||
i < BNXT_LFC_EEM_MAX_TABLE; i++, priv++)
|
||||
dmabuf_fd.fd[i] = priv->fd;
|
||||
|
||||
rc = copy_to_user(lfc_req->req.eem_dmabuf_export_fd_req.dma_fd,
|
||||
&dmabuf_fd, sizeof(dmabuf_fd));
|
||||
if (rc)
|
||||
rc = -EFAULT;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int32_t bnxt_lfc_process_req(struct bnxt_lfc_dev *blfc_dev,
|
||||
struct bnxt_lfc_req *lfc_req)
|
||||
{
|
||||
|
|
@ -566,6 +957,12 @@ static int32_t bnxt_lfc_process_req(struct bnxt_lfc_dev *blfc_dev,
|
|||
case BNXT_LFC_GENERIC_HWRM_REQ:
|
||||
rc = bnxt_lfc_process_hwrm(blfc_dev, lfc_req);
|
||||
break;
|
||||
case BNXT_LFC_DMABUF_CLOSE_REQ:
|
||||
rc = bnxt_lfc_process_dmabuf_close(blfc_dev);
|
||||
break;
|
||||
case BNXT_LFC_EEM_DMABUF_EXPORT_FD_REQ:
|
||||
rc = bnxt_lfc_process_dmabuf_export(blfc_dev, lfc_req);
|
||||
break;
|
||||
default:
|
||||
BNXT_LFC_DEBUG(&blfc_dev->pdev->dev,
|
||||
"No valid request found\n");
|
||||
|
|
@ -693,6 +1090,7 @@ not_taken:
|
|||
|
||||
if (bnxt_lfc_is_valid_pdev(blfc_dev->pdev) != true) {
|
||||
mutex_unlock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
kfree(blfc_dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -703,6 +1101,7 @@ not_taken:
|
|||
pci_dev_put(blfc_dev->pdev);
|
||||
rtnl_unlock();
|
||||
mutex_unlock(&blfc_global_dev.bnxt_lfc_lock);
|
||||
kfree(blfc_dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,18 @@ struct bnxt_gloabl_dev {
|
|||
struct mutex bnxt_lfc_lock;
|
||||
};
|
||||
|
||||
struct bnxt_eem_dmabuf_info {
|
||||
int fd;
|
||||
u32 dir;
|
||||
int type;
|
||||
int pg_count;
|
||||
struct dma_buf *buf;
|
||||
struct sg_table sg;
|
||||
struct device *dev;
|
||||
struct page **pages;
|
||||
struct bnxt_ctx_pg_info *tbl;
|
||||
};
|
||||
|
||||
int32_t bnxt_lfc_init(void);
|
||||
void bnxt_lfc_exit(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ enum bnxt_lfc_req_type {
|
|||
BNXT_LFC_NVM_SET_VAR_REQ,
|
||||
BNXT_LFC_NVM_FLUSH_REQ,
|
||||
BNXT_LFC_GENERIC_HWRM_REQ,
|
||||
BNXT_LFC_EEM_DMABUF_EXPORT_FD_REQ,
|
||||
BNXT_LFC_DMABUF_CLOSE_REQ,
|
||||
};
|
||||
|
||||
struct bnxt_lfc_req_hdr {
|
||||
|
|
@ -93,11 +95,23 @@ struct bnxt_lfc_generic_msg {
|
|||
__u32 value;
|
||||
};
|
||||
|
||||
#define BNXT_LFC_EEM_MAX_TABLE 8
|
||||
|
||||
struct bnxt_lfc_dmabuf_fd {
|
||||
int fd[BNXT_LFC_EEM_MAX_TABLE];
|
||||
};
|
||||
|
||||
struct bnxt_lfc_eem_dmabuf_export_fd_req {
|
||||
void __user *dma_fd;
|
||||
};
|
||||
|
||||
struct bnxt_lfc_req {
|
||||
struct bnxt_lfc_req_hdr hdr;
|
||||
union {
|
||||
struct bnxt_lfc_nvm_get_var_req nvm_get_var_req;
|
||||
struct bnxt_lfc_nvm_set_var_req nvm_set_var_req;
|
||||
struct bnxt_lfc_eem_dmabuf_export_fd_req
|
||||
eem_dmabuf_export_fd_req;
|
||||
__u64 hreq; /* Pointer to "struct blfc_fw_msg" */
|
||||
} req;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "bnxt_hsi.h"
|
||||
#include "bnxt_netlink.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_hwrm.h"
|
||||
|
||||
/* attribute policy */
|
||||
static struct nla_policy bnxt_netlink_policy[BNXT_NUM_ATTRS] = {
|
||||
|
|
@ -86,14 +87,13 @@ err_inval:
|
|||
static int bnxt_netlink_hwrm(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr **a = info->attrs;
|
||||
int len;
|
||||
struct sk_buff *reply = NULL;
|
||||
struct input *req;
|
||||
struct output *resp;
|
||||
struct bnxt *bp = NULL;
|
||||
int rc = 0;
|
||||
void *hdr;
|
||||
struct net_device *dev = NULL;
|
||||
struct sk_buff *reply = NULL;
|
||||
struct input *req, *nl_req;
|
||||
struct bnxt *bp = NULL;
|
||||
struct output *resp;
|
||||
int len, rc;
|
||||
void *hdr;
|
||||
|
||||
rc = bnxt_parse_attrs(a, &bp, &dev);
|
||||
if (rc)
|
||||
|
|
@ -104,28 +104,20 @@ static int bnxt_netlink_hwrm(struct sk_buff *skb, struct genl_info *info)
|
|||
goto err_rc;
|
||||
}
|
||||
|
||||
if (!bp->hwrm_cmd_resp_addr) {
|
||||
if (!bp->hwrm_dma_pool) {
|
||||
netdev_warn(bp->dev, "HWRM interface not currently available on %s\n",
|
||||
dev->name);
|
||||
rc = -EINVAL;
|
||||
goto err_rc;
|
||||
}
|
||||
|
||||
if (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL &&
|
||||
!bp->hwrm_cmd_kong_resp_addr) {
|
||||
netdev_warn(bp->dev, "HWRM Kong interface not currently available on %s\n",
|
||||
dev->name);
|
||||
rc = -EINVAL;
|
||||
goto err_rc;
|
||||
}
|
||||
|
||||
if (!a[BNXT_ATTR_REQUEST]) {
|
||||
netdev_warn(bp->dev, "No request specified\n");
|
||||
rc = -EINVAL;
|
||||
goto err_rc;
|
||||
}
|
||||
len = nla_len(a[BNXT_ATTR_REQUEST]);
|
||||
req = nla_data(a[BNXT_ATTR_REQUEST]);
|
||||
nl_req = nla_data(a[BNXT_ATTR_REQUEST]);
|
||||
|
||||
reply = genlmsg_new(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!reply) {
|
||||
|
|
@ -134,9 +126,16 @@ static int bnxt_netlink_hwrm(struct sk_buff *skb, struct genl_info *info)
|
|||
goto err_rc;
|
||||
}
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, req, req->req_type, -1, -1);
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message_silent(bp, req, len, HWRM_CMD_TIMEOUT);
|
||||
rc = hwrm_req_init(bp, req, nl_req->req_type);
|
||||
if (rc)
|
||||
goto err_rc;
|
||||
|
||||
rc = hwrm_req_replace(bp, req, nl_req, len);
|
||||
if (rc)
|
||||
goto err_rc;
|
||||
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send_silent(bp, req);
|
||||
if (rc) {
|
||||
/*
|
||||
* Indicate success for the hwrm transport, while letting
|
||||
|
|
@ -150,15 +149,14 @@ static int bnxt_netlink_hwrm(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
hdr = genlmsg_put_reply(reply, info, &bnxt_netlink_family, 0,
|
||||
BNXT_CMD_HWRM);
|
||||
resp = (struct output *)bnxt_get_hwrm_resp_addr(bp, req);
|
||||
if (nla_put(reply, BNXT_ATTR_RESPONSE, resp->resp_len, resp)) {
|
||||
netdev_warn(bp->dev, "No space for response attribte\n");
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
rc = -ENOMEM;
|
||||
goto err_rc;
|
||||
}
|
||||
genlmsg_end(reply, hdr);
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
|
||||
dev_put(dev);
|
||||
dev = NULL;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_hwrm.h"
|
||||
#include "bnxt_ptp.h"
|
||||
|
||||
#ifdef HAVE_IEEE1588_SUPPORT
|
||||
|
|
@ -30,11 +31,68 @@ static int bnxt_ptp_settime(struct ptp_clock_info *ptp_info,
|
|||
ptp_info);
|
||||
u64 ns = timespec64_to_ns(ts);
|
||||
|
||||
ns = timespec64_to_ns(ts);
|
||||
timecounter_init(&ptp->tc, &ptp->cc, ns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_port_ts_query(struct bnxt *bp, u32 flags, u64 *ts,
|
||||
struct ptp_system_timestamp *sts)
|
||||
{
|
||||
struct hwrm_port_ts_query_output *resp;
|
||||
struct hwrm_port_ts_query_input *req;
|
||||
int rc;
|
||||
|
||||
rc = hwrm_req_init(bp, req, HWRM_PORT_TS_QUERY);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
req->flags = cpu_to_le32(flags);
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
if (sts)
|
||||
hwrm_req_capture_ts(bp, req, sts);
|
||||
|
||||
rc = hwrm_req_send(bp, req);
|
||||
if (rc) {
|
||||
hwrm_req_drop(bp, req);
|
||||
return rc;
|
||||
}
|
||||
*ts = le64_to_cpu(resp->ptp_msg_ts);
|
||||
hwrm_req_drop(bp, req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_ptp_get_current_time(struct bnxt *bp)
|
||||
{
|
||||
u32 flags = PORT_TS_QUERY_REQ_FLAGS_CURRENT_TIME;
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
|
||||
if (!ptp)
|
||||
return 0;
|
||||
ptp->old_time = ptp->current_time;
|
||||
return bnxt_hwrm_port_ts_query(bp, flags, &ptp->current_time, NULL);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PTP_GETTIMEX64
|
||||
static int bnxt_ptp_gettimex(struct ptp_clock_info *ptp_info,
|
||||
struct timespec64 *ts,
|
||||
struct ptp_system_timestamp *sts)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
|
||||
ptp_info);
|
||||
u32 flags = PORT_TS_QUERY_REQ_FLAGS_CURRENT_TIME;
|
||||
u64 ns, cycles;
|
||||
int rc;
|
||||
|
||||
rc = bnxt_hwrm_port_ts_query(ptp->bp, flags, &cycles, sts);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
ns = timecounter_cyc2time(&ptp->tc, cycles);
|
||||
*ts = ns_to_timespec64(ns);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int bnxt_ptp_gettime(struct ptp_clock_info *ptp_info,
|
||||
struct timespec64 *ts)
|
||||
{
|
||||
|
|
@ -46,7 +104,7 @@ static int bnxt_ptp_gettime(struct ptp_clock_info *ptp_info,
|
|||
*ts = ns_to_timespec64(ns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
static int bnxt_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
|
||||
|
|
@ -65,6 +123,24 @@ static int bnxt_ptp_adjfreq(struct ptp_clock_info *ptp_info, s32 ppb)
|
|||
s32 best_dif = BNXT_MAX_PHC_DRIFT;
|
||||
u32 drift_sign = 1;
|
||||
|
||||
if (ptp->bp->flags & BNXT_FLAG_CHIP_P5) {
|
||||
struct hwrm_port_mac_cfg_input *req;
|
||||
int rc;
|
||||
|
||||
rc = hwrm_req_init(ptp->bp, req, HWRM_PORT_MAC_CFG);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
req->ptp_freq_adj_ppb = ppb;
|
||||
req->enables =
|
||||
cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_PTP_FREQ_ADJ_PPB);
|
||||
rc = hwrm_req_send(ptp->bp, req);
|
||||
if (rc)
|
||||
netdev_err(ptp->bp->dev,
|
||||
"ptp adjfreq failed. rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Frequency adjustment requires programming 3 values:
|
||||
* 1-bit direction
|
||||
* 5-bit adjustment step in 1 ns unit
|
||||
|
|
@ -128,7 +204,7 @@ static void bnxt_clr_rx_ts(struct bnxt *bp)
|
|||
int i = 0;
|
||||
u32 fifo;
|
||||
|
||||
if (!ptp)
|
||||
if (!ptp || (bp->flags & BNXT_FLAG_CHIP_P5))
|
||||
return;
|
||||
|
||||
port_id = pf->port_id;
|
||||
|
|
@ -143,14 +219,17 @@ static void bnxt_clr_rx_ts(struct bnxt *bp)
|
|||
|
||||
static int bnxt_hwrm_ptp_cfg(struct bnxt *bp)
|
||||
{
|
||||
struct hwrm_port_mac_cfg_input req = {0};
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
struct hwrm_port_mac_cfg_input *req;
|
||||
u32 flags = 0;
|
||||
int rc;
|
||||
|
||||
if (!ptp)
|
||||
return 0;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_MAC_CFG, -1, -1);
|
||||
rc = hwrm_req_init(bp, req, HWRM_PORT_MAC_CFG);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (ptp->rx_filter)
|
||||
flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_ENABLE;
|
||||
|
|
@ -160,12 +239,11 @@ static int bnxt_hwrm_ptp_cfg(struct bnxt *bp)
|
|||
flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_ENABLE;
|
||||
else
|
||||
flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_DISABLE;
|
||||
req.flags = cpu_to_le32(flags);
|
||||
req.enables = cpu_to_le32(
|
||||
PORT_MAC_CFG_REQ_ENABLES_RX_TS_CAPTURE_PTP_MSG_TYPE);
|
||||
req.rx_ts_capture_ptp_msg_type = cpu_to_le16(ptp->rxctl);
|
||||
req->flags = cpu_to_le32(flags);
|
||||
req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_RX_TS_CAPTURE_PTP_MSG_TYPE);
|
||||
req->rx_ts_capture_ptp_msg_type = cpu_to_le16(ptp->rxctl);
|
||||
|
||||
return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
return hwrm_req_send(bp, req);
|
||||
}
|
||||
|
||||
int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
|
||||
|
|
@ -321,8 +399,19 @@ static u64 bnxt_cc_read(const struct cyclecounter *cc)
|
|||
struct bnxt *bp = ptp->bp;
|
||||
u64 ns;
|
||||
|
||||
ns = readl(bp->bar0 + BNXT_GRCPF_REG_SYNC_TIME);
|
||||
ns |= (u64)readl(bp->bar0 + BNXT_GRCPF_REG_SYNC_TIME + 4) << 32;
|
||||
if (bp->flags & BNXT_FLAG_CHIP_P5) {
|
||||
u32 flags = PORT_TS_QUERY_REQ_FLAGS_CURRENT_TIME;
|
||||
int rc;
|
||||
|
||||
rc = bnxt_hwrm_port_ts_query(bp, flags, &ns, NULL);
|
||||
if (rc)
|
||||
netdev_err(bp->dev, "TS query for cc_read failed rc = %x\n",
|
||||
rc);
|
||||
} else {
|
||||
ns = readl(bp->bar0 + BNXT_GRCPF_REG_SYNC_TIME);
|
||||
ns |= (u64)readl(bp->bar0 + BNXT_GRCPF_REG_SYNC_TIME + 4) << 32;
|
||||
}
|
||||
|
||||
return ns;
|
||||
}
|
||||
|
||||
|
|
@ -374,6 +463,80 @@ int bnxt_get_rx_ts(struct bnxt *bp, u64 *ts)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void bnxt_ptp_ts_task(struct work_struct *work)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = container_of(work, struct bnxt_ptp_cfg,
|
||||
ptp_ts_task);
|
||||
u32 flags = PORT_TS_QUERY_REQ_FLAGS_PATH_TX;
|
||||
struct skb_shared_hwtstamps timestamp;
|
||||
struct bnxt *bp = ptp->bp;
|
||||
u64 ts = 0, ns = 0;
|
||||
int rc;
|
||||
|
||||
if (!ptp->tx_skb)
|
||||
return;
|
||||
|
||||
rc = bnxt_hwrm_port_ts_query(bp, flags, &ts, NULL);
|
||||
if (rc) {
|
||||
netdev_err(bp->dev, "TS query for TX timer failed rc = %x\n",
|
||||
rc);
|
||||
} else {
|
||||
memset(×tamp, 0, sizeof(timestamp));
|
||||
ns = timecounter_cyc2time(&ptp->tc, ts);
|
||||
timestamp.hwtstamp = ns_to_ktime(ns);
|
||||
skb_tstamp_tx(ptp->tx_skb, ×tamp);
|
||||
}
|
||||
|
||||
dev_kfree_skb_any(ptp->tx_skb);
|
||||
ptp->tx_skb = NULL;
|
||||
atomic_inc(&bp->ptp_cfg->tx_avail);
|
||||
}
|
||||
|
||||
int bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
|
||||
if (ptp->tx_skb) {
|
||||
netdev_err(bp->dev, "deferring skb:one SKB is still outstanding\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
ptp->tx_skb = skb;
|
||||
schedule_work(&ptp->ptp_ts_task);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_get_rx_ts_p5(struct bnxt *bp, u64 *ts, u32 pkt_ts)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
u64 time;
|
||||
|
||||
time = READ_ONCE(ptp->old_time);
|
||||
*ts = (time & BNXT_HI_TIMER_MASK) | pkt_ts;
|
||||
if (pkt_ts < (time & BNXT_LO_TIMER_MASK))
|
||||
*ts += BNXT_LO_TIMER_MASK + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_ptp_start(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
int rc = 0;
|
||||
|
||||
if (!ptp)
|
||||
return 0;
|
||||
|
||||
if (bp->flags & BNXT_FLAG_CHIP_P5) {
|
||||
u32 flags = PORT_TS_QUERY_REQ_FLAGS_CURRENT_TIME;
|
||||
int rc;
|
||||
|
||||
rc = bnxt_hwrm_port_ts_query(bp, flags, &ptp->current_time,
|
||||
NULL);
|
||||
ptp->old_time = ptp->current_time;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct ptp_clock_info bnxt_ptp_caps = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "bnxt clock",
|
||||
|
|
@ -385,7 +548,11 @@ static const struct ptp_clock_info bnxt_ptp_caps = {
|
|||
.pps = 0,
|
||||
.adjfreq = bnxt_ptp_adjfreq,
|
||||
.adjtime = bnxt_ptp_adjtime,
|
||||
.gettime64 = bnxt_ptp_gettime,
|
||||
#ifdef HAVE_PTP_GETTIMEX64
|
||||
.gettimex64 = bnxt_ptp_gettimex,
|
||||
#else
|
||||
.gettime64 = bnxt_ptp_gettime,
|
||||
#endif
|
||||
.settime64 = bnxt_ptp_settime,
|
||||
.enable = bnxt_ptp_enable,
|
||||
};
|
||||
|
|
@ -393,13 +560,17 @@ static const struct ptp_clock_info bnxt_ptp_caps = {
|
|||
int bnxt_ptp_init(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
||||
int rc;
|
||||
|
||||
if (!ptp)
|
||||
return 0;
|
||||
rc = bnxt_map_ptp_regs(bp);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!(bp->flags & BNXT_FLAG_CHIP_P5)) {
|
||||
int rc;
|
||||
|
||||
rc = bnxt_map_ptp_regs(bp);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
atomic_set(&ptp->tx_avail, BNXT_MAX_TX_TS);
|
||||
|
||||
|
|
@ -416,6 +587,7 @@ int bnxt_ptp_init(struct bnxt *bp)
|
|||
if (IS_ERR(ptp->ptp_clock))
|
||||
ptp->ptp_clock = NULL;
|
||||
|
||||
INIT_WORK(&ptp->ptp_ts_task, bnxt_ptp_ts_task);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -429,12 +601,22 @@ void bnxt_ptp_free(struct bnxt *bp)
|
|||
if (ptp->ptp_clock)
|
||||
ptp_clock_unregister(ptp->ptp_clock);
|
||||
|
||||
cancel_work_sync(&ptp->ptp_ts_task);
|
||||
ptp->ptp_clock = NULL;
|
||||
if (ptp->tx_skb) {
|
||||
dev_kfree_skb_any(ptp->tx_skb);
|
||||
ptp->tx_skb = NULL;
|
||||
}
|
||||
bnxt_unmap_ptp_regs(bp);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int bnxt_ptp_get_current_time(struct bnxt *bp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
|
|
@ -445,6 +627,11 @@ int bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int bnxt_ptp_start(struct bnxt *bp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_ptp_init(struct bnxt *bp)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
#define BNXT_PTP_H
|
||||
|
||||
#define BNXT_MAX_PHC_DRIFT 31000000
|
||||
#define BNXT_LO_TIMER_MASK 0x0000ffffffffUL
|
||||
#define BNXT_HI_TIMER_MASK 0xffff00000000UL
|
||||
|
||||
struct bnxt_ptp_cfg {
|
||||
#ifdef HAVE_IEEE1588_SUPPORT
|
||||
|
|
@ -18,6 +20,10 @@ struct bnxt_ptp_cfg {
|
|||
struct ptp_clock *ptp_clock;
|
||||
struct cyclecounter cc;
|
||||
struct timecounter tc;
|
||||
struct sk_buff *tx_skb;
|
||||
u64 current_time;
|
||||
u64 old_time;
|
||||
struct work_struct ptp_ts_task;
|
||||
#endif
|
||||
struct bnxt *bp;
|
||||
atomic_t tx_avail;
|
||||
|
|
@ -60,11 +66,16 @@ struct bnxt_ptp_cfg {
|
|||
u32 tx_mapped_regs[BNXT_PTP_TX_REGS];
|
||||
};
|
||||
|
||||
int bnxt_ptp_get_current_time(struct bnxt *bp);
|
||||
int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr);
|
||||
int bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr);
|
||||
int bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb);
|
||||
int bnxt_get_tx_ts(struct bnxt *bp, u64 *ts);
|
||||
int bnxt_get_rx_ts(struct bnxt *bp, u64 *ts);
|
||||
int bnxt_get_rx_ts_p5(struct bnxt *bp, u64 *ts, u32 pkt_ts);
|
||||
int bnxt_ptp_start(struct bnxt *bp);
|
||||
int bnxt_ptp_init(struct bnxt *bp);
|
||||
void bnxt_ptp_free(struct bnxt *bp);
|
||||
void bnxt_ptp_ts_task(struct work_struct *work);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -27,6 +27,7 @@
|
|||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_hwrm.h"
|
||||
#include "bnxt_sriov.h"
|
||||
#include "bnxt_tc.h"
|
||||
#include "bnxt_vfr.h"
|
||||
|
|
@ -57,7 +58,7 @@ static u16 bnxt_flow_get_dst_fid(struct bnxt *pf_bp, struct net_device *dev)
|
|||
|
||||
/* check if dev belongs to the same switch */
|
||||
if (!netdev_port_same_parent_id(pf_bp->dev, dev)) {
|
||||
netdev_info(pf_bp->dev, "dev(ifindex=%d) not on same switch",
|
||||
netdev_info(pf_bp->dev, "dev(ifindex=%d) not on same switch\n",
|
||||
dev->ifindex);
|
||||
return BNXT_FID_INVALID;
|
||||
}
|
||||
|
|
@ -80,7 +81,7 @@ static int bnxt_tc_parse_redir(struct bnxt *bp,
|
|||
struct net_device *dev = act->dev;
|
||||
|
||||
if (!dev) {
|
||||
netdev_info(bp->dev, "no dev in mirred action");
|
||||
netdev_info(bp->dev, "no dev in mirred action\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -179,7 +180,7 @@ static int bnxt_tc_parse_tunnel_set(struct bnxt *bp,
|
|||
#endif
|
||||
|
||||
if (ip_tunnel_info_af(tun_info) != AF_INET) {
|
||||
netdev_info(bp->dev, "only IPv4 tunnel-encap is supported");
|
||||
netdev_info(bp->dev, "only IPv4 tunnel-encap is supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
|
@ -355,7 +356,8 @@ bnxt_tc_parse_pedit(struct bnxt *bp, struct bnxt_tc_actions *actions,
|
|||
|
||||
static int bnxt_tc_parse_actions(struct bnxt *bp,
|
||||
struct bnxt_tc_actions *actions,
|
||||
struct flow_action *flow_action)
|
||||
struct flow_action *flow_action,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
/* Used to store the L2 rewrite mask for dmac (6 bytes) followed by
|
||||
* smac (6 bytes) if rewrite of both is specified, otherwise either
|
||||
|
|
@ -371,10 +373,13 @@ static int bnxt_tc_parse_actions(struct bnxt *bp,
|
|||
int i, rc;
|
||||
|
||||
if (!flow_action_has_entries(flow_action)) {
|
||||
netdev_info(bp->dev, "no actions");
|
||||
netdev_info(bp->dev, "no actions\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!flow_action_basic_hw_stats_check(flow_action, extack))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
flow_action_for_each(i, act, flow_action) {
|
||||
switch (act->id) {
|
||||
case FLOW_ACTION_DROP:
|
||||
|
|
@ -660,7 +665,7 @@ static int bnxt_tc_parse_flow(struct bnxt *bp,
|
|||
/* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */
|
||||
if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 ||
|
||||
(dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC)) == 0) {
|
||||
netdev_info(bp->dev, "cannot form TC key: used_keys = 0x%x",
|
||||
netdev_info(bp->dev, "cannot form TC key: used_keys = 0x%x\n",
|
||||
dissector->used_keys);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
|
@ -781,7 +786,8 @@ static int bnxt_tc_parse_flow(struct bnxt *bp,
|
|||
flow->tun_mask.tp_src = match.mask->src;
|
||||
}
|
||||
|
||||
return bnxt_tc_parse_actions(bp, &flow->actions, &rule->action);
|
||||
return bnxt_tc_parse_actions(bp, &flow->actions, &rule->action,
|
||||
tc_flow_cmd->common.extack);
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
@ -949,18 +955,20 @@ static int bnxt_tc_parse_flow(struct bnxt *bp,
|
|||
static int bnxt_hwrm_cfa_flow_free(struct bnxt *bp,
|
||||
struct bnxt_tc_flow_node *flow_node)
|
||||
{
|
||||
struct hwrm_cfa_flow_free_input req = { 0 };
|
||||
struct hwrm_cfa_flow_free_input *req;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_FLOW_FREE, -1, -1);
|
||||
if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE)
|
||||
req.ext_flow_handle = flow_node->ext_flow_handle;
|
||||
else
|
||||
req.flow_handle = flow_node->flow_handle;
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_FLOW_FREE);
|
||||
if (!rc) {
|
||||
if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE)
|
||||
req->ext_flow_handle = flow_node->ext_flow_handle;
|
||||
else
|
||||
req->flow_handle = flow_node->flow_handle;
|
||||
|
||||
rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
}
|
||||
if (rc)
|
||||
netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
|
||||
netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1034,20 +1042,22 @@ static int bnxt_hwrm_cfa_flow_alloc(struct bnxt *bp, struct bnxt_tc_flow *flow,
|
|||
struct bnxt_tc_actions *actions = &flow->actions;
|
||||
struct bnxt_tc_l3_key *l3_mask = &flow->l3_mask;
|
||||
struct bnxt_tc_l3_key *l3_key = &flow->l3_key;
|
||||
struct hwrm_cfa_flow_alloc_input req = { 0 };
|
||||
struct hwrm_cfa_flow_alloc_output *resp;
|
||||
struct hwrm_cfa_flow_alloc_input *req;
|
||||
u16 flow_flags = 0, action_flags = 0;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_FLOW_ALLOC, -1, -1);
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_FLOW_ALLOC);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
req.src_fid = cpu_to_le16(flow->src_fid);
|
||||
req.ref_flow_handle = ref_flow_handle;
|
||||
req->src_fid = cpu_to_le16(flow->src_fid);
|
||||
req->ref_flow_handle = ref_flow_handle;
|
||||
|
||||
if (actions->flags & BNXT_TC_ACTION_FLAG_L2_REWRITE) {
|
||||
memcpy(req.l2_rewrite_dmac, actions->l2_rewrite_dmac,
|
||||
memcpy(req->l2_rewrite_dmac, actions->l2_rewrite_dmac,
|
||||
ETH_ALEN);
|
||||
memcpy(req.l2_rewrite_smac, actions->l2_rewrite_smac,
|
||||
memcpy(req->l2_rewrite_smac, actions->l2_rewrite_smac,
|
||||
ETH_ALEN);
|
||||
action_flags |=
|
||||
CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_L2_HEADER_REWRITE;
|
||||
|
|
@ -1062,71 +1072,71 @@ static int bnxt_hwrm_cfa_flow_alloc(struct bnxt *bp, struct bnxt_tc_flow *flow,
|
|||
action_flags |=
|
||||
CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_NAT_SRC;
|
||||
/* L3 source rewrite */
|
||||
req.nat_ip_address[0] =
|
||||
req->nat_ip_address[0] =
|
||||
actions->nat.l3.ipv4.saddr.s_addr;
|
||||
/* L4 source port */
|
||||
if (actions->nat.l4.ports.sport)
|
||||
req.nat_port =
|
||||
req->nat_port =
|
||||
actions->nat.l4.ports.sport;
|
||||
} else {
|
||||
action_flags |=
|
||||
CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_NAT_DEST;
|
||||
/* L3 destination rewrite */
|
||||
req.nat_ip_address[0] =
|
||||
req->nat_ip_address[0] =
|
||||
actions->nat.l3.ipv4.daddr.s_addr;
|
||||
/* L4 destination port */
|
||||
if (actions->nat.l4.ports.dport)
|
||||
req.nat_port =
|
||||
req->nat_port =
|
||||
actions->nat.l4.ports.dport;
|
||||
}
|
||||
netdev_dbg(bp->dev,
|
||||
"req.nat_ip_address: %pI4 src_xlate: %d req.nat_port: %x\n",
|
||||
req.nat_ip_address, actions->nat.src_xlate,
|
||||
req.nat_port);
|
||||
req->nat_ip_address, actions->nat.src_xlate,
|
||||
req->nat_port);
|
||||
} else {
|
||||
if (actions->nat.src_xlate) {
|
||||
action_flags |=
|
||||
CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_NAT_SRC;
|
||||
/* L3 source rewrite */
|
||||
memcpy(req.nat_ip_address,
|
||||
memcpy(req->nat_ip_address,
|
||||
actions->nat.l3.ipv6.saddr.s6_addr32,
|
||||
sizeof(req.nat_ip_address));
|
||||
sizeof(req->nat_ip_address));
|
||||
/* L4 source port */
|
||||
if (actions->nat.l4.ports.sport)
|
||||
req.nat_port =
|
||||
req->nat_port =
|
||||
actions->nat.l4.ports.sport;
|
||||
} else {
|
||||
action_flags |=
|
||||
CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_NAT_DEST;
|
||||
/* L3 destination rewrite */
|
||||
memcpy(req.nat_ip_address,
|
||||
memcpy(req->nat_ip_address,
|
||||
actions->nat.l3.ipv6.daddr.s6_addr32,
|
||||
sizeof(req.nat_ip_address));
|
||||
sizeof(req->nat_ip_address));
|
||||
/* L4 destination port */
|
||||
if (actions->nat.l4.ports.dport)
|
||||
req.nat_port =
|
||||
req->nat_port =
|
||||
actions->nat.l4.ports.dport;
|
||||
}
|
||||
netdev_dbg(bp->dev,
|
||||
"req.nat_ip_address: %pI6 src_xlate: %d req.nat_port: %x\n",
|
||||
req.nat_ip_address, actions->nat.src_xlate,
|
||||
req.nat_port);
|
||||
req->nat_ip_address, actions->nat.src_xlate,
|
||||
req->nat_port);
|
||||
}
|
||||
}
|
||||
|
||||
if (actions->flags & BNXT_TC_ACTION_FLAG_TUNNEL_DECAP ||
|
||||
actions->flags & BNXT_TC_ACTION_FLAG_TUNNEL_ENCAP) {
|
||||
req.tunnel_handle = tunnel_handle;
|
||||
req->tunnel_handle = tunnel_handle;
|
||||
flow_flags |= CFA_FLOW_ALLOC_REQ_FLAGS_TUNNEL;
|
||||
action_flags |= CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_TUNNEL;
|
||||
}
|
||||
|
||||
req.ethertype = flow->l2_key.ether_type;
|
||||
req.ip_proto = flow->l4_key.ip_proto;
|
||||
req->ethertype = flow->l2_key.ether_type;
|
||||
req->ip_proto = flow->l4_key.ip_proto;
|
||||
|
||||
if (flow->flags & BNXT_TC_FLOW_FLAGS_ETH_ADDRS) {
|
||||
memcpy(req.dmac, flow->l2_key.dmac, ETH_ALEN);
|
||||
memcpy(req.smac, flow->l2_key.smac, ETH_ALEN);
|
||||
memcpy(req->dmac, flow->l2_key.dmac, ETH_ALEN);
|
||||
memcpy(req->smac, flow->l2_key.smac, ETH_ALEN);
|
||||
}
|
||||
|
||||
if (flow->l2_key.num_vlans > 0) {
|
||||
|
|
@ -1135,7 +1145,7 @@ static int bnxt_hwrm_cfa_flow_alloc(struct bnxt *bp, struct bnxt_tc_flow *flow,
|
|||
* in outer_vlan_tci when num_vlans is 1 (which is
|
||||
* always the case in TC.)
|
||||
*/
|
||||
req.outer_vlan_tci = flow->l2_key.inner_vlan_tci;
|
||||
req->outer_vlan_tci = flow->l2_key.inner_vlan_tci;
|
||||
}
|
||||
|
||||
/* If all IP and L4 fields are wildcarded then this is an L2 flow */
|
||||
|
|
@ -1148,68 +1158,67 @@ static int bnxt_hwrm_cfa_flow_alloc(struct bnxt *bp, struct bnxt_tc_flow *flow,
|
|||
CFA_FLOW_ALLOC_REQ_FLAGS_FLOWTYPE_IPV6;
|
||||
|
||||
if (flow->flags & BNXT_TC_FLOW_FLAGS_IPV4_ADDRS) {
|
||||
req.ip_dst[0] = l3_key->ipv4.daddr.s_addr;
|
||||
req.ip_dst_mask_len =
|
||||
req->ip_dst[0] = l3_key->ipv4.daddr.s_addr;
|
||||
req->ip_dst_mask_len =
|
||||
inet_mask_len(l3_mask->ipv4.daddr.s_addr);
|
||||
req.ip_src[0] = l3_key->ipv4.saddr.s_addr;
|
||||
req.ip_src_mask_len =
|
||||
req->ip_src[0] = l3_key->ipv4.saddr.s_addr;
|
||||
req->ip_src_mask_len =
|
||||
inet_mask_len(l3_mask->ipv4.saddr.s_addr);
|
||||
} else if (flow->flags & BNXT_TC_FLOW_FLAGS_IPV6_ADDRS) {
|
||||
memcpy(req.ip_dst, l3_key->ipv6.daddr.s6_addr32,
|
||||
sizeof(req.ip_dst));
|
||||
req.ip_dst_mask_len =
|
||||
memcpy(req->ip_dst, l3_key->ipv6.daddr.s6_addr32,
|
||||
sizeof(req->ip_dst));
|
||||
req->ip_dst_mask_len =
|
||||
ipv6_mask_len(&l3_mask->ipv6.daddr);
|
||||
memcpy(req.ip_src, l3_key->ipv6.saddr.s6_addr32,
|
||||
sizeof(req.ip_src));
|
||||
req.ip_src_mask_len =
|
||||
memcpy(req->ip_src, l3_key->ipv6.saddr.s6_addr32,
|
||||
sizeof(req->ip_src));
|
||||
req->ip_src_mask_len =
|
||||
ipv6_mask_len(&l3_mask->ipv6.saddr);
|
||||
}
|
||||
}
|
||||
|
||||
if (flow->flags & BNXT_TC_FLOW_FLAGS_PORTS) {
|
||||
req.l4_src_port = flow->l4_key.ports.sport;
|
||||
req.l4_src_port_mask = flow->l4_mask.ports.sport;
|
||||
req.l4_dst_port = flow->l4_key.ports.dport;
|
||||
req.l4_dst_port_mask = flow->l4_mask.ports.dport;
|
||||
req->l4_src_port = flow->l4_key.ports.sport;
|
||||
req->l4_src_port_mask = flow->l4_mask.ports.sport;
|
||||
req->l4_dst_port = flow->l4_key.ports.dport;
|
||||
req->l4_dst_port_mask = flow->l4_mask.ports.dport;
|
||||
} else if (flow->flags & BNXT_TC_FLOW_FLAGS_ICMP) {
|
||||
/* l4 ports serve as type/code when ip_proto is ICMP */
|
||||
req.l4_src_port = htons(flow->l4_key.icmp.type);
|
||||
req.l4_src_port_mask = htons(flow->l4_mask.icmp.type);
|
||||
req.l4_dst_port = htons(flow->l4_key.icmp.code);
|
||||
req.l4_dst_port_mask = htons(flow->l4_mask.icmp.code);
|
||||
req->l4_src_port = htons(flow->l4_key.icmp.type);
|
||||
req->l4_src_port_mask = htons(flow->l4_mask.icmp.type);
|
||||
req->l4_dst_port = htons(flow->l4_key.icmp.code);
|
||||
req->l4_dst_port_mask = htons(flow->l4_mask.icmp.code);
|
||||
}
|
||||
req.flags = cpu_to_le16(flow_flags);
|
||||
req->flags = cpu_to_le16(flow_flags);
|
||||
|
||||
if (actions->flags & BNXT_TC_ACTION_FLAG_DROP) {
|
||||
action_flags |= CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_DROP;
|
||||
} else {
|
||||
if (actions->flags & BNXT_TC_ACTION_FLAG_FWD) {
|
||||
action_flags |= CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_FWD;
|
||||
req.dst_fid = cpu_to_le16(actions->dst_fid);
|
||||
req->dst_fid = cpu_to_le16(actions->dst_fid);
|
||||
}
|
||||
if (actions->flags & BNXT_TC_ACTION_FLAG_PUSH_VLAN) {
|
||||
action_flags |=
|
||||
CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_L2_HEADER_REWRITE;
|
||||
req.l2_rewrite_vlan_tpid = actions->push_vlan_tpid;
|
||||
req.l2_rewrite_vlan_tci = actions->push_vlan_tci;
|
||||
memcpy(&req.l2_rewrite_dmac, &req.dmac, ETH_ALEN);
|
||||
memcpy(&req.l2_rewrite_smac, &req.smac, ETH_ALEN);
|
||||
req->l2_rewrite_vlan_tpid = actions->push_vlan_tpid;
|
||||
req->l2_rewrite_vlan_tci = actions->push_vlan_tci;
|
||||
memcpy(&req->l2_rewrite_dmac, &req->dmac, ETH_ALEN);
|
||||
memcpy(&req->l2_rewrite_smac, &req->smac, ETH_ALEN);
|
||||
}
|
||||
if (actions->flags & BNXT_TC_ACTION_FLAG_POP_VLAN) {
|
||||
action_flags |=
|
||||
CFA_FLOW_ALLOC_REQ_ACTION_FLAGS_L2_HEADER_REWRITE;
|
||||
/* Rewrite config with tpid = 0 implies vlan pop */
|
||||
req.l2_rewrite_vlan_tpid = 0;
|
||||
memcpy(&req.l2_rewrite_dmac, &req.dmac, ETH_ALEN);
|
||||
memcpy(&req.l2_rewrite_smac, &req.smac, ETH_ALEN);
|
||||
req->l2_rewrite_vlan_tpid = 0;
|
||||
memcpy(&req->l2_rewrite_dmac, &req->dmac, ETH_ALEN);
|
||||
memcpy(&req->l2_rewrite_smac, &req->smac, ETH_ALEN);
|
||||
}
|
||||
}
|
||||
req.action_flags = cpu_to_le16(action_flags);
|
||||
req->action_flags = cpu_to_le16(action_flags);
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
if (!rc) {
|
||||
resp = bnxt_get_hwrm_resp_addr(bp, &req);
|
||||
/* CFA_FLOW_ALLOC response interpretation:
|
||||
* fw with fw with
|
||||
* 16-bit 64-bit
|
||||
|
|
@ -1225,7 +1234,7 @@ static int bnxt_hwrm_cfa_flow_alloc(struct bnxt *bp, struct bnxt_tc_flow *flow,
|
|||
flow_node->flow_id = resp->flow_id;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -1235,67 +1244,69 @@ static int hwrm_cfa_decap_filter_alloc(struct bnxt *bp,
|
|||
__le32 ref_decap_handle,
|
||||
__le32 *decap_filter_handle)
|
||||
{
|
||||
struct hwrm_cfa_decap_filter_alloc_input req = { 0 };
|
||||
struct hwrm_cfa_decap_filter_alloc_output *resp;
|
||||
struct ip_tunnel_key *tun_key = &flow->tun_key;
|
||||
struct hwrm_cfa_decap_filter_alloc_input *req;
|
||||
u32 enables = 0;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_DECAP_FILTER_ALLOC, -1, -1);
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_DECAP_FILTER_ALLOC);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
req.flags = cpu_to_le32(CFA_DECAP_FILTER_ALLOC_REQ_FLAGS_OVS_TUNNEL);
|
||||
req->flags = cpu_to_le32(CFA_DECAP_FILTER_ALLOC_REQ_FLAGS_OVS_TUNNEL);
|
||||
enables |= CFA_DECAP_FILTER_ALLOC_REQ_ENABLES_TUNNEL_TYPE |
|
||||
CFA_DECAP_FILTER_ALLOC_REQ_ENABLES_IP_PROTOCOL;
|
||||
req.tunnel_type = CFA_DECAP_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN;
|
||||
req.ip_protocol = CFA_DECAP_FILTER_ALLOC_REQ_IP_PROTOCOL_UDP;
|
||||
req->tunnel_type = CFA_DECAP_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN;
|
||||
req->ip_protocol = CFA_DECAP_FILTER_ALLOC_REQ_IP_PROTOCOL_UDP;
|
||||
|
||||
if (flow->flags & BNXT_TC_FLOW_FLAGS_TUNL_ID) {
|
||||
enables |= CFA_DECAP_FILTER_ALLOC_REQ_ENABLES_TUNNEL_ID;
|
||||
/* tunnel_id is wrongly defined in hsi defn. as __le32 */
|
||||
req.tunnel_id = tunnel_id_to_key32(tun_key->tun_id);
|
||||
req->tunnel_id = tunnel_id_to_key32(tun_key->tun_id);
|
||||
}
|
||||
|
||||
if (flow->flags & BNXT_TC_FLOW_FLAGS_TUNL_ETH_ADDRS) {
|
||||
enables |= CFA_DECAP_FILTER_ALLOC_REQ_ENABLES_DST_MACADDR;
|
||||
ether_addr_copy(req.dst_macaddr, l2_info->dmac);
|
||||
ether_addr_copy(req->dst_macaddr, l2_info->dmac);
|
||||
}
|
||||
if (l2_info->num_vlans) {
|
||||
enables |= CFA_DECAP_FILTER_ALLOC_REQ_ENABLES_T_IVLAN_VID;
|
||||
req.t_ivlan_vid = l2_info->inner_vlan_tci;
|
||||
req->t_ivlan_vid = l2_info->inner_vlan_tci;
|
||||
}
|
||||
|
||||
enables |= CFA_DECAP_FILTER_ALLOC_REQ_ENABLES_ETHERTYPE;
|
||||
req.ethertype = htons(ETH_P_IP);
|
||||
req->ethertype = htons(ETH_P_IP);
|
||||
|
||||
if (flow->flags & BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS) {
|
||||
enables |= CFA_DECAP_FILTER_ALLOC_REQ_ENABLES_SRC_IPADDR |
|
||||
CFA_DECAP_FILTER_ALLOC_REQ_ENABLES_DST_IPADDR |
|
||||
CFA_DECAP_FILTER_ALLOC_REQ_ENABLES_IPADDR_TYPE;
|
||||
req.ip_addr_type = CFA_DECAP_FILTER_ALLOC_REQ_IP_ADDR_TYPE_IPV4;
|
||||
req.dst_ipaddr[0] = tun_key->u.ipv4.dst;
|
||||
req.src_ipaddr[0] = tun_key->u.ipv4.src;
|
||||
req->ip_addr_type =
|
||||
CFA_DECAP_FILTER_ALLOC_REQ_IP_ADDR_TYPE_IPV4;
|
||||
req->dst_ipaddr[0] = tun_key->u.ipv4.dst;
|
||||
req->src_ipaddr[0] = tun_key->u.ipv4.src;
|
||||
}
|
||||
|
||||
if (flow->flags & BNXT_TC_FLOW_FLAGS_TUNL_PORTS) {
|
||||
enables |= CFA_DECAP_FILTER_ALLOC_REQ_ENABLES_DST_PORT;
|
||||
req.dst_port = tun_key->tp_dst;
|
||||
req->dst_port = tun_key->tp_dst;
|
||||
}
|
||||
|
||||
/* Eventhough the decap_handle returned by hwrm_cfa_decap_filter_alloc
|
||||
* is defined as __le32, l2_ctxt_ref_id is defined in HSI as __le16.
|
||||
*/
|
||||
req.l2_ctxt_ref_id = (__force __le16)ref_decap_handle;
|
||||
req.enables = cpu_to_le32(enables);
|
||||
req->l2_ctxt_ref_id = (__force __le16)ref_decap_handle;
|
||||
req->enables = cpu_to_le32(enables);
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
if (!rc) {
|
||||
resp = bnxt_get_hwrm_resp_addr(bp, &req);
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
if (!rc)
|
||||
*decap_filter_handle = resp->decap_filter_id;
|
||||
} else {
|
||||
netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
exit:
|
||||
if (rc)
|
||||
netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1303,15 +1314,16 @@ static int hwrm_cfa_decap_filter_alloc(struct bnxt *bp,
|
|||
static int hwrm_cfa_decap_filter_free(struct bnxt *bp,
|
||||
__le32 decap_filter_handle)
|
||||
{
|
||||
struct hwrm_cfa_decap_filter_free_input req = { 0 };
|
||||
struct hwrm_cfa_decap_filter_free_input *req;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_DECAP_FILTER_FREE, -1, -1);
|
||||
req.decap_filter_id = decap_filter_handle;
|
||||
|
||||
rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_DECAP_FILTER_FREE);
|
||||
if (!rc) {
|
||||
req->decap_filter_id = decap_filter_handle;
|
||||
rc = hwrm_req_send(bp, req);
|
||||
}
|
||||
if (rc)
|
||||
netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
|
||||
netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1321,17 +1333,20 @@ static int hwrm_cfa_encap_record_alloc(struct bnxt *bp,
|
|||
struct bnxt_tc_l2_key *l2_info,
|
||||
__le32 *encap_record_handle)
|
||||
{
|
||||
struct hwrm_cfa_encap_record_alloc_input req = { 0 };
|
||||
struct hwrm_cfa_encap_record_alloc_output *resp;
|
||||
struct hwrm_cfa_encap_data_vxlan *encap =
|
||||
(struct hwrm_cfa_encap_data_vxlan *)&req.encap_data;
|
||||
struct hwrm_vxlan_ipv4_hdr *encap_ipv4 =
|
||||
(struct hwrm_vxlan_ipv4_hdr *)encap->l3;
|
||||
struct hwrm_cfa_encap_record_alloc_input *req;
|
||||
struct hwrm_cfa_encap_data_vxlan *encap;
|
||||
struct hwrm_vxlan_ipv4_hdr *encap_ipv4;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_ENCAP_RECORD_ALLOC, -1, -1);
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_ENCAP_RECORD_ALLOC);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
req.encap_type = CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN;
|
||||
encap = (struct hwrm_cfa_encap_data_vxlan *)&req->encap_data;
|
||||
encap_ipv4 = (struct hwrm_vxlan_ipv4_hdr *)encap->l3;
|
||||
|
||||
req->encap_type = CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN;
|
||||
|
||||
ether_addr_copy(encap->dst_mac_addr, l2_info->dmac);
|
||||
ether_addr_copy(encap->src_mac_addr, l2_info->smac);
|
||||
|
|
@ -1352,15 +1367,14 @@ static int hwrm_cfa_encap_record_alloc(struct bnxt *bp,
|
|||
encap->dst_port = encap_key->tp_dst;
|
||||
encap->vni = tunnel_id_to_key32(encap_key->tun_id);
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
if (!rc) {
|
||||
resp = bnxt_get_hwrm_resp_addr(bp, &req);
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
if (!rc)
|
||||
*encap_record_handle = resp->encap_record_id;
|
||||
} else {
|
||||
netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
exit:
|
||||
if (rc)
|
||||
netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1368,15 +1382,16 @@ static int hwrm_cfa_encap_record_alloc(struct bnxt *bp,
|
|||
static int hwrm_cfa_encap_record_free(struct bnxt *bp,
|
||||
__le32 encap_record_handle)
|
||||
{
|
||||
struct hwrm_cfa_encap_record_free_input req = { 0 };
|
||||
struct hwrm_cfa_encap_record_free_input *req;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_ENCAP_RECORD_FREE, -1, -1);
|
||||
req.encap_record_id = encap_record_handle;
|
||||
|
||||
rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_ENCAP_RECORD_FREE);
|
||||
if (!rc) {
|
||||
req->encap_record_id = encap_record_handle;
|
||||
rc = hwrm_req_send(bp, req);
|
||||
}
|
||||
if (rc)
|
||||
netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
|
||||
netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1395,7 +1410,7 @@ static int bnxt_tc_put_l2_node(struct bnxt *bp,
|
|||
tc_info->l2_ht_params);
|
||||
if (rc)
|
||||
netdev_err(bp->dev,
|
||||
"Error: %s: rhashtable_remove_fast: %d",
|
||||
"Error: %s: rhashtable_remove_fast: %d\n",
|
||||
__func__, rc);
|
||||
kfree_rcu(l2_node, rcu);
|
||||
}
|
||||
|
|
@ -1424,7 +1439,7 @@ bnxt_tc_get_l2_node(struct bnxt *bp, struct rhashtable *l2_table,
|
|||
if (rc) {
|
||||
kfree_rcu(l2_node, rcu);
|
||||
netdev_err(bp->dev,
|
||||
"Error: %s: rhashtable_insert_fast: %d",
|
||||
"Error: %s: rhashtable_insert_fast: %d\n",
|
||||
__func__, rc);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1483,7 +1498,7 @@ static bool bnxt_tc_can_offload(struct bnxt *bp, struct bnxt_tc_flow *flow)
|
|||
if ((flow->flags & BNXT_TC_FLOW_FLAGS_PORTS) &&
|
||||
(flow->l4_key.ip_proto != IPPROTO_TCP &&
|
||||
flow->l4_key.ip_proto != IPPROTO_UDP)) {
|
||||
netdev_info(bp->dev, "Cannot offload non-TCP/UDP (%d) ports",
|
||||
netdev_info(bp->dev, "Cannot offload non-TCP/UDP (%d) ports\n",
|
||||
flow->l4_key.ip_proto);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1548,7 +1563,7 @@ static int bnxt_tc_put_tunnel_node(struct bnxt *bp,
|
|||
rc = rhashtable_remove_fast(tunnel_table, &tunnel_node->node,
|
||||
*ht_params);
|
||||
if (rc) {
|
||||
netdev_err(bp->dev, "rhashtable_remove_fast rc=%d", rc);
|
||||
netdev_err(bp->dev, "rhashtable_remove_fast rc=%d\n", rc);
|
||||
rc = -1;
|
||||
}
|
||||
kfree_rcu(tunnel_node, rcu);
|
||||
|
|
@ -1590,7 +1605,7 @@ bnxt_tc_get_tunnel_node(struct bnxt *bp, struct rhashtable *tunnel_table,
|
|||
tunnel_node->refcount++;
|
||||
return tunnel_node;
|
||||
err:
|
||||
netdev_info(bp->dev, "error rc=%d", rc);
|
||||
netdev_info(bp->dev, "error rc=%d\n", rc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1648,7 +1663,7 @@ static void bnxt_tc_put_decap_l2_node(struct bnxt *bp,
|
|||
&decap_l2_node->node,
|
||||
tc_info->decap_l2_ht_params);
|
||||
if (rc)
|
||||
netdev_err(bp->dev, "rhashtable_remove_fast rc=%d", rc);
|
||||
netdev_err(bp->dev, "rhashtable_remove_fast rc=%d\n", rc);
|
||||
kfree_rcu(decap_l2_node, rcu);
|
||||
}
|
||||
}
|
||||
|
|
@ -1688,7 +1703,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp,
|
|||
|
||||
rt = ip_route_output_key(dev_net(real_dst_dev), &flow);
|
||||
if (IS_ERR(rt)) {
|
||||
netdev_info(bp->dev, "no route to %pI4b", &flow.daddr);
|
||||
netdev_info(bp->dev, "no route to %pI4b\n", &flow.daddr);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
|
@ -1702,7 +1717,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp,
|
|||
|
||||
if (vlan->real_dev != real_dst_dev) {
|
||||
netdev_info(bp->dev,
|
||||
"dst_dev(%s) doesn't use PF-if(%s)",
|
||||
"dst_dev(%s) doesn't use PF-if(%s)\n",
|
||||
netdev_name(dst_dev),
|
||||
netdev_name(real_dst_dev));
|
||||
rc = -EOPNOTSUPP;
|
||||
|
|
@ -1714,7 +1729,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp,
|
|||
#endif
|
||||
} else if (dst_dev != real_dst_dev) {
|
||||
netdev_info(bp->dev,
|
||||
"dst_dev(%s) for %pI4b is not PF-if(%s)",
|
||||
"dst_dev(%s) for %pI4b is not PF-if(%s)\n",
|
||||
netdev_name(dst_dev), &flow.daddr,
|
||||
netdev_name(real_dst_dev));
|
||||
rc = -EOPNOTSUPP;
|
||||
|
|
@ -1723,7 +1738,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp,
|
|||
|
||||
nbr = dst_neigh_lookup(&rt->dst, &flow.daddr);
|
||||
if (!nbr) {
|
||||
netdev_info(bp->dev, "can't lookup neighbor for %pI4b",
|
||||
netdev_info(bp->dev, "can't lookup neighbor for %pI4b\n",
|
||||
&flow.daddr);
|
||||
rc = -EOPNOTSUPP;
|
||||
goto put_rt;
|
||||
|
|
@ -1935,7 +1950,7 @@ static int __bnxt_tc_del_flow(struct bnxt *bp,
|
|||
rc = rhashtable_remove_fast(&tc_info->flow_table, &flow_node->node,
|
||||
tc_info->flow_ht_params);
|
||||
if (rc)
|
||||
netdev_err(bp->dev, "Error: %s: rhashtable_remove_fast rc=%d",
|
||||
netdev_err(bp->dev, "Error: %s: rhashtable_remove_fast rc=%d\n",
|
||||
__func__, rc);
|
||||
|
||||
kfree_rcu(flow_node, rcu);
|
||||
|
|
@ -2071,7 +2086,7 @@ unlock:
|
|||
free_node:
|
||||
kfree_rcu(new_node, rcu);
|
||||
done:
|
||||
netdev_err(bp->dev, "Error: %s: cookie=0x%lx error=%d",
|
||||
netdev_err(bp->dev, "Error: %s: cookie=0x%lx error=%d\n",
|
||||
__func__, tc_flow_cmd->cookie, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -2139,7 +2154,7 @@ static int bnxt_tc_get_flow_stats(struct bnxt *bp,
|
|||
|
||||
#ifdef HAVE_FLOW_OFFLOAD_H
|
||||
flow_stats_update(&tc_flow_cmd->stats, stats.bytes, stats.packets,
|
||||
lastused);
|
||||
lastused, FLOW_ACTION_HW_STATS_DELAYED);
|
||||
#else
|
||||
tcf_exts_stats_update(tc_flow_cmd->exts, stats.bytes, stats.packets,
|
||||
lastused);
|
||||
|
|
@ -2177,14 +2192,20 @@ static int
|
|||
bnxt_hwrm_cfa_flow_stats_get(struct bnxt *bp, int num_flows,
|
||||
struct bnxt_tc_stats_batch stats_batch[])
|
||||
{
|
||||
struct hwrm_cfa_flow_stats_input req = { 0 };
|
||||
struct hwrm_cfa_flow_stats_output *resp;
|
||||
__le16 *req_flow_handles = &req.flow_handle_0;
|
||||
__le32 *req_flow_ids = &req.flow_id_0;
|
||||
struct hwrm_cfa_flow_stats_input *req;
|
||||
__le16 *req_flow_handles;
|
||||
__le32 *req_flow_ids;
|
||||
int rc, i;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_FLOW_STATS, -1, -1);
|
||||
req.num_flows = cpu_to_le16(num_flows);
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_FLOW_STATS);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
req_flow_handles = &req->flow_handle_0;
|
||||
req_flow_ids = &req->flow_id_0;
|
||||
|
||||
req->num_flows = cpu_to_le16(num_flows);
|
||||
for (i = 0; i < num_flows; i++) {
|
||||
struct bnxt_tc_flow_node *flow_node = stats_batch[i].flow_node;
|
||||
|
||||
|
|
@ -2192,13 +2213,12 @@ bnxt_hwrm_cfa_flow_stats_get(struct bnxt *bp, int num_flows,
|
|||
&req_flow_handles[i], &req_flow_ids[i]);
|
||||
}
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
if (!rc) {
|
||||
__le64 *resp_packets;
|
||||
__le64 *resp_bytes;
|
||||
|
||||
resp = bnxt_get_hwrm_resp_addr(bp, &req);
|
||||
resp_packets = &resp->packet_0;
|
||||
resp_bytes = &resp->byte_0;
|
||||
|
||||
|
|
@ -2208,10 +2228,11 @@ bnxt_hwrm_cfa_flow_stats_get(struct bnxt *bp, int num_flows,
|
|||
stats_batch[i].hw_stats.bytes =
|
||||
le64_to_cpu(resp_bytes[i]);
|
||||
}
|
||||
} else {
|
||||
netdev_info(bp->dev, "error rc=%d", rc);
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
exit:
|
||||
if (rc)
|
||||
netdev_info(bp->dev, "error rc=%d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -2517,7 +2538,7 @@ static int bnxt_tc_indr_block_event(struct notifier_block *nb,
|
|||
bp);
|
||||
if (rc)
|
||||
netdev_info(bp->dev,
|
||||
"Failed to register indirect blk: dev: %s",
|
||||
"Failed to register indirect blk: dev: %s\n",
|
||||
netdev->name);
|
||||
break;
|
||||
case NETDEV_UNREGISTER:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_hwrm.h"
|
||||
#include "bnxt_ulp.h"
|
||||
|
||||
static int bnxt_register_dev(struct bnxt_en_dev *edev, int ulp_id,
|
||||
|
|
@ -107,9 +108,13 @@ static void bnxt_fill_msix_vecs(struct bnxt *bp, struct bnxt_msix_entry *ent)
|
|||
ent[i].vector = bp->irq_tbl[idx + i].vector;
|
||||
ent[i].ring_idx = idx + i;
|
||||
if (bp->flags & BNXT_FLAG_CHIP_P5) {
|
||||
ent[i].db_offset = DB_PF_OFFSET_P5;
|
||||
if (BNXT_VF(bp))
|
||||
ent[i].db_offset = DB_VF_OFFSET_P5;
|
||||
if (bp->flags & BNXT_FLAG_CHIP_SR2) {
|
||||
ent[i].db_offset = bp->legacy_db_size;
|
||||
} else {
|
||||
ent[i].db_offset = DB_PF_OFFSET_P5;
|
||||
if (BNXT_VF(bp))
|
||||
ent[i].db_offset = DB_VF_OFFSET_P5;
|
||||
}
|
||||
} else {
|
||||
ent[i].db_offset = (idx + i) * 0x80;
|
||||
}
|
||||
|
|
@ -235,19 +240,25 @@ static int bnxt_send_msg(struct bnxt_en_dev *edev, int ulp_id,
|
|||
{
|
||||
struct net_device *dev = edev->net;
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
struct output *resp;
|
||||
struct input *req;
|
||||
int rc;
|
||||
|
||||
if ((ulp_id != BNXT_ROCE_ULP) && bp->fw_reset_state)
|
||||
return -EBUSY;
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
req = fw_msg->msg;
|
||||
req->resp_addr = cpu_to_le64(bp->hwrm_cmd_resp_dma_addr);
|
||||
rc = _hwrm_send_message(bp, fw_msg->msg, fw_msg->msg_len,
|
||||
fw_msg->timeout);
|
||||
if (rc != -EBUSY && rc != -E2BIG) {
|
||||
struct output *resp = bp->hwrm_cmd_resp_addr;
|
||||
rc = hwrm_req_init(bp, req, 0 /* don't care */);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = hwrm_req_replace(bp, req, fw_msg->msg, fw_msg->msg_len);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
hwrm_req_timeout(bp, req, fw_msg->timeout);
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
if (!rc || rc == -EAGAIN) {
|
||||
u32 len = le16_to_cpu(resp->resp_len);
|
||||
|
||||
if (fw_msg->resp_max_len < len)
|
||||
|
|
@ -255,7 +266,7 @@ static int bnxt_send_msg(struct bnxt_en_dev *edev, int ulp_id,
|
|||
|
||||
memcpy(fw_msg->resp, resp, len);
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -471,6 +482,10 @@ struct bnxt_en_dev *bnxt_ulp_probe(struct net_device *dev)
|
|||
struct bnxt *bp = netdev_priv(dev);
|
||||
struct bnxt_en_dev *edev;
|
||||
|
||||
#if (BITS_PER_LONG == 64)
|
||||
BUILD_BUG_ON(offsetof(struct bnxt, reserved_ulp_kabi_0) != 0x40);
|
||||
BUILD_BUG_ON(offsetof(struct bnxt, reserved_ulp_kabi_1) != 0x80);
|
||||
#endif
|
||||
edev = bp->edev;
|
||||
if (!edev) {
|
||||
edev = kzalloc(sizeof(*edev), GFP_KERNEL);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "bnxt_compat.h"
|
||||
#include "bnxt_hsi.h"
|
||||
#include "bnxt.h"
|
||||
#include "bnxt_hwrm.h"
|
||||
#include "bnxt_vfr.h"
|
||||
#include "bnxt_devlink.h"
|
||||
#include "bnxt_tc.h"
|
||||
|
|
@ -30,57 +31,60 @@
|
|||
static int hwrm_cfa_vfr_alloc(struct bnxt *bp, u16 vf_idx,
|
||||
u16 *tx_cfa_action, u16 *rx_cfa_code)
|
||||
{
|
||||
struct hwrm_cfa_vfr_alloc_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
struct hwrm_cfa_vfr_alloc_input req = { 0 };
|
||||
struct hwrm_cfa_vfr_alloc_output *resp;
|
||||
struct hwrm_cfa_vfr_alloc_input *req;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_VFR_ALLOC, -1, -1);
|
||||
req.vf_id = cpu_to_le16(vf_idx);
|
||||
sprintf(req.vfr_name, "vfr%d", vf_idx);
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_VFR_ALLOC);
|
||||
if (!rc) {
|
||||
*tx_cfa_action = le16_to_cpu(resp->tx_cfa_action);
|
||||
*rx_cfa_code = le16_to_cpu(resp->rx_cfa_code);
|
||||
netdev_dbg(bp->dev, "tx_cfa_action=0x%x, rx_cfa_code=0x%x",
|
||||
*tx_cfa_action, *rx_cfa_code);
|
||||
} else {
|
||||
netdev_info(bp->dev, "%s error rc=%d", __func__, rc);
|
||||
}
|
||||
req->vf_id = cpu_to_le16(vf_idx);
|
||||
sprintf(req->vfr_name, "vfr%d", vf_idx);
|
||||
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
if (!rc) {
|
||||
*tx_cfa_action = le16_to_cpu(resp->tx_cfa_action);
|
||||
*rx_cfa_code = le16_to_cpu(resp->rx_cfa_code);
|
||||
netdev_dbg(bp->dev, "tx_cfa_action=0x%x, rx_cfa_code=0x%x",
|
||||
*tx_cfa_action, *rx_cfa_code);
|
||||
}
|
||||
hwrm_req_drop(bp, req);
|
||||
}
|
||||
if (rc)
|
||||
netdev_info(bp->dev, "%s error rc=%d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int hwrm_cfa_vfr_free(struct bnxt *bp, u16 vf_idx)
|
||||
{
|
||||
struct hwrm_cfa_vfr_free_input req = { 0 };
|
||||
struct hwrm_cfa_vfr_free_input *req;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_VFR_FREE, -1, -1);
|
||||
sprintf(req.vfr_name, "vfr%d", vf_idx);
|
||||
|
||||
rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
rc = hwrm_req_init(bp, req, HWRM_CFA_VFR_FREE);
|
||||
if (!rc) {
|
||||
sprintf(req->vfr_name, "vfr%d", vf_idx);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
}
|
||||
if (rc)
|
||||
netdev_info(bp->dev, "%s error rc=%d", __func__, rc);
|
||||
netdev_info(bp->dev, "%s error rc=%d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_hwrm_vfr_qcfg(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
|
||||
u16 *max_mtu)
|
||||
{
|
||||
struct hwrm_func_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
struct hwrm_func_qcfg_input req = {0};
|
||||
struct hwrm_func_qcfg_output *resp;
|
||||
struct hwrm_func_qcfg_input *req;
|
||||
u16 mtu;
|
||||
int rc;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCFG, -1, -1);
|
||||
req.fid = bp->pf.vf[vf_rep->vf_idx].fw_fid;
|
||||
rc = hwrm_req_init(bp, req, HWRM_FUNC_QCFG);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
|
||||
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||
req->fid = bp->pf.vf[vf_rep->vf_idx].fw_fid;
|
||||
resp = hwrm_req_hold(bp, req);
|
||||
rc = hwrm_req_send(bp, req);
|
||||
if (!rc) {
|
||||
mtu = le16_to_cpu(resp->max_mtu_configured);
|
||||
if (!mtu)
|
||||
|
|
@ -88,7 +92,8 @@ static int bnxt_hwrm_vfr_qcfg(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
|
|||
else
|
||||
*max_mtu = mtu;
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
hwrm_req_drop(bp, req);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -619,7 +624,7 @@ static int bnxt_vf_reps_create(struct bnxt *bp)
|
|||
return 0;
|
||||
|
||||
err:
|
||||
netdev_info(bp->dev, "%s error=%d", __func__, rc);
|
||||
netdev_info(bp->dev, "%s error=%d\n", __func__, rc);
|
||||
kfree(cfa_code_map);
|
||||
__bnxt_vf_reps_destroy(bp);
|
||||
return rc;
|
||||
|
|
@ -646,7 +651,7 @@ int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode)
|
|||
|
||||
mutex_lock(&bp->sriov_lock);
|
||||
if (bp->eswitch_mode == mode) {
|
||||
netdev_info(bp->dev, "already in %s eswitch mode",
|
||||
netdev_info(bp->dev, "already in %s eswitch mode\n",
|
||||
mode == DEVLINK_ESWITCH_MODE_LEGACY ?
|
||||
"legacy" : "switchdev");
|
||||
rc = -EINVAL;
|
||||
|
|
@ -666,7 +671,7 @@ int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode)
|
|||
}
|
||||
|
||||
if (pci_num_vf(bp->pdev) == 0) {
|
||||
netdev_info(bp->dev, "Enable VFs before setting switchdev mode");
|
||||
netdev_info(bp->dev, "Enable VFs before setting switchdev mode\n");
|
||||
rc = -EPERM;
|
||||
goto done;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,6 +153,9 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
|
|||
xdp.data_end = *data_ptr + *len;
|
||||
#ifdef HAVE_XDP_RXQ_INFO
|
||||
xdp.rxq = &rxr->xdp_rxq;
|
||||
#endif
|
||||
#ifdef HAVE_XDP_FRAME_SZ
|
||||
xdp.frame_sz = PAGE_SIZE; /* BNXT_RX_PAGE_MODE(bp) when XDP enabled */
|
||||
#endif
|
||||
orig_data = xdp.data;
|
||||
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk)
|
|||
}
|
||||
|
||||
set_capacity(disk, available_disk_size >> SECTOR_SHIFT);
|
||||
device_add_disk(dev, disk);
|
||||
device_add_disk(dev, disk, NULL);
|
||||
revalidate_disk(disk);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1553,7 +1553,7 @@ static int btt_blk_init(struct btt *btt)
|
|||
}
|
||||
}
|
||||
set_capacity(btt->btt_disk, btt->nlba * btt->sector_size >> 9);
|
||||
device_add_disk(&btt->nd_btt->dev, btt->btt_disk);
|
||||
device_add_disk(&btt->nd_btt->dev, btt->btt_disk, NULL);
|
||||
btt->nd_btt->size = btt->nlba * (u64)btt->sector_size;
|
||||
revalidate_disk(btt->btt_disk);
|
||||
|
||||
|
|
|
|||
|
|
@ -413,7 +413,7 @@ static int pmem_attach_disk(struct device *dev,
|
|||
gendev = disk_to_dev(disk);
|
||||
gendev->groups = pmem_attribute_groups;
|
||||
|
||||
device_add_disk(dev, disk);
|
||||
device_add_disk(dev, disk, NULL);
|
||||
if (devm_add_action_or_reset(dev, pmem_release_disk, pmem))
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -2165,6 +2165,14 @@ static const struct attribute_group nvme_ns_attr_group = {
|
|||
.is_visible = nvme_ns_attrs_are_visible,
|
||||
};
|
||||
|
||||
const struct attribute_group *nvme_ns_id_attr_groups[] = {
|
||||
&nvme_ns_attr_group,
|
||||
#ifdef CONFIG_NVM
|
||||
&nvme_nvm_attr_group,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
#define nvme_show_str_function(field) \
|
||||
static ssize_t field##_show(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
|
|
@ -2415,14 +2423,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
|
|||
|
||||
kfree(id);
|
||||
|
||||
device_add_disk(ctrl->device, ns->disk);
|
||||
if (sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
|
||||
&nvme_ns_attr_group))
|
||||
pr_warn("%s: failed to create sysfs group for identification\n",
|
||||
ns->disk->disk_name);
|
||||
if (ns->ndev && nvme_nvm_register_sysfs(ns))
|
||||
pr_warn("%s: failed to register lightnvm sysfs group for identification\n",
|
||||
ns->disk->disk_name);
|
||||
device_add_disk(ctrl->device, ns->disk, nvme_ns_id_attr_groups);
|
||||
return;
|
||||
out_free_id:
|
||||
kfree(id);
|
||||
|
|
@ -2442,10 +2443,6 @@ static void nvme_ns_remove(struct nvme_ns *ns)
|
|||
if (ns->disk && ns->disk->flags & GENHD_FL_UP) {
|
||||
if (blk_get_integrity(ns->disk))
|
||||
blk_integrity_unregister(ns->disk);
|
||||
sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
|
||||
&nvme_ns_attr_group);
|
||||
if (ns->ndev)
|
||||
nvme_nvm_unregister_sysfs(ns);
|
||||
del_gendisk(ns->disk);
|
||||
blk_cleanup_queue(ns->queue);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -939,19 +939,27 @@ static struct attribute *nvm_dev_attrs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group nvm_dev_attr_group = {
|
||||
.name = "lightnvm",
|
||||
.attrs = nvm_dev_attrs,
|
||||
static umode_t nvm_dev_attrs_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int index)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
struct nvme_ns *ns = disk->private_data;
|
||||
struct nvm_dev *ndev = ns->ndev;
|
||||
struct device_attribute *dev_attr =
|
||||
container_of(attr, typeof(*dev_attr), attr);
|
||||
|
||||
if (!ndev)
|
||||
return 0;
|
||||
|
||||
if (dev_attr->show == nvm_dev_attr_show)
|
||||
return attr->mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct attribute_group nvme_nvm_attr_group = {
|
||||
.name = "lightnvm",
|
||||
.attrs = nvm_dev_attrs,
|
||||
.is_visible = nvm_dev_attrs_visible,
|
||||
};
|
||||
|
||||
int nvme_nvm_register_sysfs(struct nvme_ns *ns)
|
||||
{
|
||||
return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
|
||||
&nvm_dev_attr_group);
|
||||
}
|
||||
|
||||
void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
|
||||
{
|
||||
sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
|
||||
&nvm_dev_attr_group);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -336,8 +336,7 @@ int nvme_reset_ctrl(struct nvme_ctrl *ctrl);
|
|||
#ifdef CONFIG_NVM
|
||||
int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node);
|
||||
void nvme_nvm_unregister(struct nvme_ns *ns);
|
||||
int nvme_nvm_register_sysfs(struct nvme_ns *ns);
|
||||
void nvme_nvm_unregister_sysfs(struct nvme_ns *ns);
|
||||
extern const struct attribute_group nvme_nvm_attr_group;
|
||||
int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg);
|
||||
#else
|
||||
static inline int nvme_nvm_register(struct nvme_ns *ns, char *disk_name,
|
||||
|
|
@ -347,11 +346,6 @@ static inline int nvme_nvm_register(struct nvme_ns *ns, char *disk_name,
|
|||
}
|
||||
|
||||
static inline void nvme_nvm_unregister(struct nvme_ns *ns) {};
|
||||
static inline int nvme_nvm_register_sysfs(struct nvme_ns *ns)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void nvme_nvm_unregister_sysfs(struct nvme_ns *ns) {};
|
||||
static inline int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2158,8 +2158,10 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
|
|||
if (dev->ctrl.queue_count)
|
||||
nvme_suspend_queue(&dev->queues[0]);
|
||||
} else {
|
||||
nvme_disable_io_queues(dev, queues);
|
||||
nvme_disable_admin_queue(dev, shutdown);
|
||||
if (dev->ctrl.queue_count) {
|
||||
nvme_disable_io_queues(dev, queues);
|
||||
nvme_disable_admin_queue(dev, shutdown);
|
||||
}
|
||||
}
|
||||
nvme_pci_disable(dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ int dasd_gendisk_alloc(struct dasd_block *block)
|
|||
gdp->queue = block->request_queue;
|
||||
block->gdp = gdp;
|
||||
set_capacity(block->gdp, 0);
|
||||
device_add_disk(&base->cdev->dev, block->gdp);
|
||||
device_add_disk(&base->cdev->dev, block->gdp, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -677,7 +677,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
|
|||
}
|
||||
|
||||
get_device(&dev_info->dev);
|
||||
device_add_disk(&dev_info->dev, dev_info->gd);
|
||||
device_add_disk(&dev_info->dev, dev_info->gd, NULL);
|
||||
|
||||
switch (dev_info->segment_type) {
|
||||
case SEG_TYPE_SR:
|
||||
|
|
|
|||
|
|
@ -499,7 +499,7 @@ int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev)
|
|||
|
||||
/* 512 byte sectors */
|
||||
set_capacity(bdev->gendisk, scmdev->size >> 9);
|
||||
device_add_disk(&scmdev->dev, bdev->gendisk);
|
||||
device_add_disk(&scmdev->dev, bdev->gendisk, NULL);
|
||||
return 0;
|
||||
|
||||
out_queue:
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ config SCSI_MPT3SAS
|
|||
depends on PCI && SCSI
|
||||
select SCSI_SAS_ATTRS
|
||||
select RAID_ATTRS
|
||||
select IRQ_POLL
|
||||
---help---
|
||||
This driver supports PCI-Express SAS 12Gb/s Host Adapters.
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
EXTRA_CFLAGS := -DCPQ_CIM
|
||||
|
||||
# comment out this line so driver can compile for kernels not having mpt3sas
|
||||
#obj-$(CONFIG_SCSI_MPT3SAS) += mpt3sas.o
|
||||
obj-m += mpt3sas.o
|
||||
obj-$(CONFIG_SCSI_MPT3SAS) += mpt3sas.o
|
||||
mpt3sas-y += mpt3sas_base.o \
|
||||
mpt3sas_config.o \
|
||||
mpt3sas_warpdrive.o \
|
||||
|
|
@ -13,4 +12,5 @@ mpt3sas-y += mpt3sas_base.o \
|
|||
mpt3sas_transport.o \
|
||||
mpt3sas_ctl.o \
|
||||
mpt3sas_trigger_diag.o \
|
||||
mpt3sas_debugfs.o \
|
||||
|
||||
|
|
|
|||
|
|
@ -639,6 +639,7 @@ _csmisas_get_cntlr_status(struct MPT3SAS_ADAPTER *ioc,
|
|||
break;
|
||||
|
||||
case MPI2_IOC_STATE_FAULT:
|
||||
case MPI2_IOC_STATE_COREDUMP:
|
||||
karg->Status.uStatus = CSMI_SAS_CNTLR_STATUS_FAILED;
|
||||
karg->Status.uOfflineReason = 0;
|
||||
break;
|
||||
|
|
@ -2194,7 +2195,7 @@ _csmisas_ssp_passthru(struct MPT3SAS_ADAPTER *ioc,
|
|||
printk(MPT3SAS_INFO_FMT "issue target reset: handle"
|
||||
"(0x%04x)\n", ioc->name, sas_device.handle);
|
||||
mpt3sas_scsih_issue_locked_tm(ioc, sas_device.handle, 0, 0, 0,
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30, 0);
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, smid, 30, 0);
|
||||
if (ioc->scsih_cmds.status & MPT3_CMD_COMPLETE) {
|
||||
printk(MPT3SAS_INFO_FMT "target reset completed: handle"
|
||||
"(0x%04x)\n", ioc->name, sas_device.handle);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,122 +1,122 @@
|
|||
/*
|
||||
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_hbd.h
|
||||
* Title: MPI Host Based Discovery messages and structures
|
||||
* Creation Date: October 21, 2009
|
||||
*
|
||||
* mpi2_hbd.h Version: 02.00.04
|
||||
*
|
||||
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
|
||||
* prefix are for use only on MPI v2.5 products, and must not be used
|
||||
* with MPI v2.0 products. Unless otherwise noted, names beginning with
|
||||
* MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 10-28-09 02.00.00 Initial version.
|
||||
* 08-11-10 02.00.01 Removed PortGroups, DmaGroup, and ControlGroup from
|
||||
* HBD Action request, replaced by AdditionalInfo field.
|
||||
* 11-18-11 02.00.02 Incorporating additions for MPI v2.5.
|
||||
* 11-18-14 02.00.03 Updated copyright information.
|
||||
* 02-17-16 02.00.04 Added SAS 4 22.5 gbs speed support.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_HBD_H
|
||||
#define MPI2_HBD_H
|
||||
|
||||
/****************************************************************************
|
||||
* Host Based Discovery Action messages
|
||||
****************************************************************************/
|
||||
|
||||
/* Host Based Discovery Action Request Message */
|
||||
typedef struct _MPI2_HBD_ACTION_REQUEST
|
||||
{
|
||||
U8 Operation; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 DevHandle; /* 0x04 */
|
||||
U8 Reserved2; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U32 Reserved4; /* 0x0C */
|
||||
U64 SASAddress; /* 0x10 */
|
||||
U32 Reserved5; /* 0x18 */
|
||||
U32 HbdDeviceInfo; /* 0x1C */
|
||||
U16 ParentDevHandle; /* 0x20 */
|
||||
U16 MaxQDepth; /* 0x22 */
|
||||
U8 FirstPhyIdentifier; /* 0x24 */
|
||||
U8 Port; /* 0x25 */
|
||||
U8 MaxConnections; /* 0x26 */
|
||||
U8 MaxRate; /* 0x27 */
|
||||
U32 AdditionalInfo; /* 0x28 */
|
||||
U16 InitialAWT; /* 0x2C */
|
||||
U16 Reserved7; /* 0x2E */
|
||||
U32 Reserved8; /* 0x30 */
|
||||
} MPI2_HBD_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_HBD_ACTION_REQUEST,
|
||||
Mpi2HbdActionRequest_t, MPI2_POINTER pMpi2HbdActionRequest_t;
|
||||
|
||||
/* values for the Operation field */
|
||||
#define MPI2_HBD_OP_ADD_DEVICE (0x01)
|
||||
#define MPI2_HBD_OP_REMOVE_DEVICE (0x02)
|
||||
#define MPI2_HBD_OP_UPDATE_DEVICE (0x03)
|
||||
|
||||
/* values for the HbdDeviceInfo field */
|
||||
#define MPI2_HBD_DEVICE_INFO_VIRTUAL_DEVICE (0x00004000)
|
||||
#define MPI2_HBD_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
|
||||
#define MPI2_HBD_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
|
||||
#define MPI2_HBD_DEVICE_INFO_SSP_TARGET (0x00000400)
|
||||
#define MPI2_HBD_DEVICE_INFO_STP_TARGET (0x00000200)
|
||||
#define MPI2_HBD_DEVICE_INFO_SMP_TARGET (0x00000100)
|
||||
#define MPI2_HBD_DEVICE_INFO_SATA_DEVICE (0x00000080)
|
||||
#define MPI2_HBD_DEVICE_INFO_SSP_INITIATOR (0x00000040)
|
||||
#define MPI2_HBD_DEVICE_INFO_STP_INITIATOR (0x00000020)
|
||||
#define MPI2_HBD_DEVICE_INFO_SMP_INITIATOR (0x00000010)
|
||||
#define MPI2_HBD_DEVICE_INFO_SATA_HOST (0x00000008)
|
||||
|
||||
#define MPI2_HBD_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007)
|
||||
#define MPI2_HBD_DEVICE_INFO_NO_DEVICE (0x00000000)
|
||||
#define MPI2_HBD_DEVICE_INFO_END_DEVICE (0x00000001)
|
||||
#define MPI2_HBD_DEVICE_INFO_EDGE_EXPANDER (0x00000002)
|
||||
#define MPI2_HBD_DEVICE_INFO_FANOUT_EXPANDER (0x00000003)
|
||||
|
||||
/* values for the MaxRate field */
|
||||
#define MPI2_HBD_MAX_RATE_MASK (0x0F)
|
||||
#define MPI2_HBD_MAX_RATE_1_5 (0x08)
|
||||
#define MPI2_HBD_MAX_RATE_3_0 (0x09)
|
||||
#define MPI2_HBD_MAX_RATE_6_0 (0x0A)
|
||||
#define MPI25_HBD_MAX_RATE_12_0 (0x0B)
|
||||
#define MPI26_HBD_MAX_RATE_22_5 (0x0C)
|
||||
|
||||
|
||||
/* Host Based Discovery Action Reply Message */
|
||||
typedef struct _MPI2_HBD_ACTION_REPLY
|
||||
{
|
||||
U8 Operation; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 DevHandle; /* 0x04 */
|
||||
U8 Reserved2; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U16 Reserved4; /* 0x0C */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
} MPI2_HBD_ACTION_REPLY, MPI2_POINTER PTR_MPI2_HBD_ACTION_REPLY,
|
||||
Mpi2HbdActionReply_t, MPI2_POINTER pMpi2HbdActionReply_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_hbd.h
|
||||
* Title: MPI Host Based Discovery messages and structures
|
||||
* Creation Date: October 21, 2009
|
||||
*
|
||||
* mpi2_hbd.h Version: 02.00.04
|
||||
*
|
||||
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
|
||||
* prefix are for use only on MPI v2.5 products, and must not be used
|
||||
* with MPI v2.0 products. Unless otherwise noted, names beginning with
|
||||
* MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 10-28-09 02.00.00 Initial version.
|
||||
* 08-11-10 02.00.01 Removed PortGroups, DmaGroup, and ControlGroup from
|
||||
* HBD Action request, replaced by AdditionalInfo field.
|
||||
* 11-18-11 02.00.02 Incorporating additions for MPI v2.5.
|
||||
* 11-18-14 02.00.03 Updated copyright information.
|
||||
* 02-17-16 02.00.04 Added SAS 4 22.5 gbs speed support.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_HBD_H
|
||||
#define MPI2_HBD_H
|
||||
|
||||
/****************************************************************************
|
||||
* Host Based Discovery Action messages
|
||||
****************************************************************************/
|
||||
|
||||
/* Host Based Discovery Action Request Message */
|
||||
typedef struct _MPI2_HBD_ACTION_REQUEST
|
||||
{
|
||||
U8 Operation; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 DevHandle; /* 0x04 */
|
||||
U8 Reserved2; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U32 Reserved4; /* 0x0C */
|
||||
U64 SASAddress; /* 0x10 */
|
||||
U32 Reserved5; /* 0x18 */
|
||||
U32 HbdDeviceInfo; /* 0x1C */
|
||||
U16 ParentDevHandle; /* 0x20 */
|
||||
U16 MaxQDepth; /* 0x22 */
|
||||
U8 FirstPhyIdentifier; /* 0x24 */
|
||||
U8 Port; /* 0x25 */
|
||||
U8 MaxConnections; /* 0x26 */
|
||||
U8 MaxRate; /* 0x27 */
|
||||
U32 AdditionalInfo; /* 0x28 */
|
||||
U16 InitialAWT; /* 0x2C */
|
||||
U16 Reserved7; /* 0x2E */
|
||||
U32 Reserved8; /* 0x30 */
|
||||
} MPI2_HBD_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_HBD_ACTION_REQUEST,
|
||||
Mpi2HbdActionRequest_t, MPI2_POINTER pMpi2HbdActionRequest_t;
|
||||
|
||||
/* values for the Operation field */
|
||||
#define MPI2_HBD_OP_ADD_DEVICE (0x01)
|
||||
#define MPI2_HBD_OP_REMOVE_DEVICE (0x02)
|
||||
#define MPI2_HBD_OP_UPDATE_DEVICE (0x03)
|
||||
|
||||
/* values for the HbdDeviceInfo field */
|
||||
#define MPI2_HBD_DEVICE_INFO_VIRTUAL_DEVICE (0x00004000)
|
||||
#define MPI2_HBD_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
|
||||
#define MPI2_HBD_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
|
||||
#define MPI2_HBD_DEVICE_INFO_SSP_TARGET (0x00000400)
|
||||
#define MPI2_HBD_DEVICE_INFO_STP_TARGET (0x00000200)
|
||||
#define MPI2_HBD_DEVICE_INFO_SMP_TARGET (0x00000100)
|
||||
#define MPI2_HBD_DEVICE_INFO_SATA_DEVICE (0x00000080)
|
||||
#define MPI2_HBD_DEVICE_INFO_SSP_INITIATOR (0x00000040)
|
||||
#define MPI2_HBD_DEVICE_INFO_STP_INITIATOR (0x00000020)
|
||||
#define MPI2_HBD_DEVICE_INFO_SMP_INITIATOR (0x00000010)
|
||||
#define MPI2_HBD_DEVICE_INFO_SATA_HOST (0x00000008)
|
||||
|
||||
#define MPI2_HBD_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007)
|
||||
#define MPI2_HBD_DEVICE_INFO_NO_DEVICE (0x00000000)
|
||||
#define MPI2_HBD_DEVICE_INFO_END_DEVICE (0x00000001)
|
||||
#define MPI2_HBD_DEVICE_INFO_EDGE_EXPANDER (0x00000002)
|
||||
#define MPI2_HBD_DEVICE_INFO_FANOUT_EXPANDER (0x00000003)
|
||||
|
||||
/* values for the MaxRate field */
|
||||
#define MPI2_HBD_MAX_RATE_MASK (0x0F)
|
||||
#define MPI2_HBD_MAX_RATE_1_5 (0x08)
|
||||
#define MPI2_HBD_MAX_RATE_3_0 (0x09)
|
||||
#define MPI2_HBD_MAX_RATE_6_0 (0x0A)
|
||||
#define MPI25_HBD_MAX_RATE_12_0 (0x0B)
|
||||
#define MPI26_HBD_MAX_RATE_22_5 (0x0C)
|
||||
|
||||
|
||||
/* Host Based Discovery Action Reply Message */
|
||||
typedef struct _MPI2_HBD_ACTION_REPLY
|
||||
{
|
||||
U8 Operation; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 DevHandle; /* 0x04 */
|
||||
U8 Reserved2; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U16 Reserved4; /* 0x0C */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
} MPI2_HBD_ACTION_REPLY, MPI2_POINTER PTR_MPI2_HBD_ACTION_REPLY,
|
||||
Mpi2HbdActionReply_t, MPI2_POINTER pMpi2HbdActionReply_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,118 +1,118 @@
|
|||
/*
|
||||
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_pci.h
|
||||
* Title: MPI PCIe Attached Devices structures and definitions.
|
||||
* Creation Date: October 9, 2012
|
||||
*
|
||||
* mpi2_pci.h Version: 02.00.04
|
||||
*
|
||||
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
|
||||
* prefix are for use only on MPI v2.5 products, and must not be used
|
||||
* with MPI v2.0 products. Unless otherwise noted, names beginning with
|
||||
* MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 03-16-15 02.00.00 Initial version.
|
||||
* 02-17-16 02.00.01 Removed AHCI support.
|
||||
* Removed SOP support.
|
||||
* 07-01-16 02.00.02 Added MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP to
|
||||
* NVME Encapsulated Request.
|
||||
* 07-22-18 02.00.03 Updated flags field for NVME Encapsulated req
|
||||
* 12-17-18 02.00.04 Added MPI26_PCIE_DEVINFO_SCSI
|
||||
* Shortten some defines to be compatible with DOS
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_PCI_H
|
||||
#define MPI2_PCI_H
|
||||
|
||||
|
||||
/*
|
||||
* Values for the PCIe DeviceInfo field used in PCIe Device Status Change Event
|
||||
* data and PCIe Configuration pages.
|
||||
*/
|
||||
#define MPI26_PCIE_DEVINFO_DIRECT_ATTACH (0x00000010)
|
||||
|
||||
#define MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE (0x0000000F)
|
||||
#define MPI26_PCIE_DEVINFO_NO_DEVICE (0x00000000)
|
||||
#define MPI26_PCIE_DEVINFO_PCI_SWITCH (0x00000001)
|
||||
#define MPI26_PCIE_DEVINFO_NVME (0x00000003)
|
||||
#define MPI26_PCIE_DEVINFO_SCSI (0x00000004)
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* NVMe Encapsulated message
|
||||
****************************************************************************/
|
||||
|
||||
/* NVME Encapsulated Request Message */
|
||||
typedef struct _MPI26_NVME_ENCAPSULATED_REQUEST
|
||||
{
|
||||
U16 DevHandle; /* 0x00 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 EncapsulatedCommandLength; /* 0x04 */
|
||||
U8 Reserved1; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U32 Reserved3; /* 0x0C */
|
||||
U64 ErrorResponseBaseAddress; /* 0x10 */
|
||||
U16 ErrorResponseAllocationLength; /* 0x18 */
|
||||
U16 Flags; /* 0x1A */
|
||||
U32 DataLength; /* 0x1C */
|
||||
U8 NVMe_Command[4]; /* 0x20 */ /* variable length */
|
||||
|
||||
} MPI26_NVME_ENCAPSULATED_REQUEST, MPI2_POINTER PTR_MPI26_NVME_ENCAPSULATED_REQUEST,
|
||||
Mpi26NVMeEncapsulatedRequest_t, MPI2_POINTER pMpi26NVMeEncapsulatedRequest_t;
|
||||
|
||||
/* defines for the Flags field */
|
||||
#define MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP (0x0020)
|
||||
/* Submission Queue Type*/
|
||||
#define MPI26_NVME_FLAGS_SUBMISSIONQ_MASK (0x0010)
|
||||
#define MPI26_NVME_FLAGS_SUBMISSIONQ_IO (0x0000)
|
||||
#define MPI26_NVME_FLAGS_SUBMISSIONQ_ADMIN (0x0010)
|
||||
/* Error Response Address Space */
|
||||
#define MPI26_NVME_FLAGS_ERR_RSP_ADDR_MASK (0x000C)
|
||||
#define MPI26_NVME_FLAGS_ERR_RSP_ADDR_SYSTEM (0x0000)
|
||||
#define MPI26_NVME_FLAGS_ERR_RSP_ADDR_IOCTL (0x0008)
|
||||
/* Data Direction*/
|
||||
#define MPI26_NVME_FLAGS_DATADIRECTION_MASK (0x0003)
|
||||
#define MPI26_NVME_FLAGS_NODATATRANSFER (0x0000)
|
||||
#define MPI26_NVME_FLAGS_WRITE (0x0001)
|
||||
#define MPI26_NVME_FLAGS_READ (0x0002)
|
||||
#define MPI26_NVME_FLAGS_BIDIRECTIONAL (0x0003)
|
||||
|
||||
|
||||
/* NVMe Encapuslated Reply Message */
|
||||
typedef struct _MPI26_NVME_ENCAPSULATED_ERROR_REPLY
|
||||
{
|
||||
U16 DevHandle; /* 0x00 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 EncapsulatedCommandLength; /* 0x04 */
|
||||
U8 Reserved1; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U16 Reserved3; /* 0x0C */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
U16 ErrorResponseCount; /* 0x14 */
|
||||
U16 Reserved4; /* 0x16 */
|
||||
} MPI26_NVME_ENCAPSULATED_ERROR_REPLY,
|
||||
MPI2_POINTER PTR_MPI26_NVME_ENCAPSULATED_ERROR_REPLY,
|
||||
Mpi26NVMeEncapsulatedErrorReply_t,
|
||||
MPI2_POINTER pMpi26NVMeEncapsulatedErrorReply_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_pci.h
|
||||
* Title: MPI PCIe Attached Devices structures and definitions.
|
||||
* Creation Date: October 9, 2012
|
||||
*
|
||||
* mpi2_pci.h Version: 02.00.04
|
||||
*
|
||||
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
|
||||
* prefix are for use only on MPI v2.5 products, and must not be used
|
||||
* with MPI v2.0 products. Unless otherwise noted, names beginning with
|
||||
* MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 03-16-15 02.00.00 Initial version.
|
||||
* 02-17-16 02.00.01 Removed AHCI support.
|
||||
* Removed SOP support.
|
||||
* 07-01-16 02.00.02 Added MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP to
|
||||
* NVME Encapsulated Request.
|
||||
* 07-22-18 02.00.03 Updated flags field for NVME Encapsulated req
|
||||
* 12-17-18 02.00.04 Added MPI26_PCIE_DEVINFO_SCSI
|
||||
* Shortten some defines to be compatible with DOS
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_PCI_H
|
||||
#define MPI2_PCI_H
|
||||
|
||||
|
||||
/*
|
||||
* Values for the PCIe DeviceInfo field used in PCIe Device Status Change Event
|
||||
* data and PCIe Configuration pages.
|
||||
*/
|
||||
#define MPI26_PCIE_DEVINFO_DIRECT_ATTACH (0x00000010)
|
||||
|
||||
#define MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE (0x0000000F)
|
||||
#define MPI26_PCIE_DEVINFO_NO_DEVICE (0x00000000)
|
||||
#define MPI26_PCIE_DEVINFO_PCI_SWITCH (0x00000001)
|
||||
#define MPI26_PCIE_DEVINFO_NVME (0x00000003)
|
||||
#define MPI26_PCIE_DEVINFO_SCSI (0x00000004)
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* NVMe Encapsulated message
|
||||
****************************************************************************/
|
||||
|
||||
/* NVME Encapsulated Request Message */
|
||||
typedef struct _MPI26_NVME_ENCAPSULATED_REQUEST
|
||||
{
|
||||
U16 DevHandle; /* 0x00 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 EncapsulatedCommandLength; /* 0x04 */
|
||||
U8 Reserved1; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U32 Reserved3; /* 0x0C */
|
||||
U64 ErrorResponseBaseAddress; /* 0x10 */
|
||||
U16 ErrorResponseAllocationLength; /* 0x18 */
|
||||
U16 Flags; /* 0x1A */
|
||||
U32 DataLength; /* 0x1C */
|
||||
U8 NVMe_Command[4]; /* 0x20 */ /* variable length */
|
||||
|
||||
} MPI26_NVME_ENCAPSULATED_REQUEST, MPI2_POINTER PTR_MPI26_NVME_ENCAPSULATED_REQUEST,
|
||||
Mpi26NVMeEncapsulatedRequest_t, MPI2_POINTER pMpi26NVMeEncapsulatedRequest_t;
|
||||
|
||||
/* defines for the Flags field */
|
||||
#define MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP (0x0020)
|
||||
/* Submission Queue Type*/
|
||||
#define MPI26_NVME_FLAGS_SUBMISSIONQ_MASK (0x0010)
|
||||
#define MPI26_NVME_FLAGS_SUBMISSIONQ_IO (0x0000)
|
||||
#define MPI26_NVME_FLAGS_SUBMISSIONQ_ADMIN (0x0010)
|
||||
/* Error Response Address Space */
|
||||
#define MPI26_NVME_FLAGS_ERR_RSP_ADDR_MASK (0x000C)
|
||||
#define MPI26_NVME_FLAGS_ERR_RSP_ADDR_SYSTEM (0x0000)
|
||||
#define MPI26_NVME_FLAGS_ERR_RSP_ADDR_IOCTL (0x0008)
|
||||
/* Data Direction*/
|
||||
#define MPI26_NVME_FLAGS_DATADIRECTION_MASK (0x0003)
|
||||
#define MPI26_NVME_FLAGS_NODATATRANSFER (0x0000)
|
||||
#define MPI26_NVME_FLAGS_WRITE (0x0001)
|
||||
#define MPI26_NVME_FLAGS_READ (0x0002)
|
||||
#define MPI26_NVME_FLAGS_BIDIRECTIONAL (0x0003)
|
||||
|
||||
|
||||
/* NVMe Encapuslated Reply Message */
|
||||
typedef struct _MPI26_NVME_ENCAPSULATED_ERROR_REPLY
|
||||
{
|
||||
U16 DevHandle; /* 0x00 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 EncapsulatedCommandLength; /* 0x04 */
|
||||
U8 Reserved1; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U16 Reserved3; /* 0x0C */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
U16 ErrorResponseCount; /* 0x14 */
|
||||
U16 Reserved4; /* 0x16 */
|
||||
} MPI26_NVME_ENCAPSULATED_ERROR_REPLY,
|
||||
MPI2_POINTER PTR_MPI26_NVME_ENCAPSULATED_ERROR_REPLY,
|
||||
Mpi26NVMeEncapsulatedErrorReply_t,
|
||||
MPI2_POINTER pMpi26NVMeEncapsulatedErrorReply_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,86 +1,86 @@
|
|||
/*
|
||||
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_ra.h
|
||||
* Title: MPI RAID Accelerator messages and structures
|
||||
* Creation Date: April 13, 2009
|
||||
*
|
||||
* mpi2_ra.h Version: 02.00.01
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 05-06-09 02.00.00 Initial version.
|
||||
* 11-18-14 02.00.01 Updated copyright information.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_RA_H
|
||||
#define MPI2_RA_H
|
||||
|
||||
/* generic structure for RAID Accelerator Control Block */
|
||||
typedef struct _MPI2_RAID_ACCELERATOR_CONTROL_BLOCK
|
||||
{
|
||||
U32 Reserved[8]; /* 0x00 */
|
||||
U32 RaidAcceleratorCDB[1]; /* 0x20 */
|
||||
} MPI2_RAID_ACCELERATOR_CONTROL_BLOCK,
|
||||
MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_CONTROL_BLOCK,
|
||||
Mpi2RAIDAcceleratorControlBlock_t,
|
||||
MPI2_POINTER pMpi2RAIDAcceleratorControlBlock_t;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* RAID Accelerator Messages
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/* RAID Accelerator Request Message */
|
||||
typedef struct _MPI2_RAID_ACCELERATOR_REQUEST
|
||||
{
|
||||
U16 Reserved0; /* 0x00 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 Reserved1; /* 0x04 */
|
||||
U8 Reserved2; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U64 RaidAcceleratorControlBlockAddress; /* 0x0C */
|
||||
U8 DmaEngineNumber; /* 0x14 */
|
||||
U8 Reserved4; /* 0x15 */
|
||||
U16 Reserved5; /* 0x16 */
|
||||
U32 Reserved6; /* 0x18 */
|
||||
U32 Reserved7; /* 0x1C */
|
||||
U32 Reserved8; /* 0x20 */
|
||||
} MPI2_RAID_ACCELERATOR_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_REQUEST,
|
||||
Mpi2RAIDAcceleratorRequest_t, MPI2_POINTER pMpi2RAIDAcceleratorRequest_t;
|
||||
|
||||
|
||||
/* RAID Accelerator Error Reply Message */
|
||||
typedef struct _MPI2_RAID_ACCELERATOR_REPLY
|
||||
{
|
||||
U16 Reserved0; /* 0x00 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 Reserved1; /* 0x04 */
|
||||
U8 Reserved2; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U16 Reserved4; /* 0x0C */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
U32 ProductSpecificData[3]; /* 0x14 */
|
||||
} MPI2_RAID_ACCELERATOR_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_REPLY,
|
||||
Mpi2RAIDAcceleratorReply_t, MPI2_POINTER pMpi2RAIDAcceleratorReply_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_ra.h
|
||||
* Title: MPI RAID Accelerator messages and structures
|
||||
* Creation Date: April 13, 2009
|
||||
*
|
||||
* mpi2_ra.h Version: 02.00.01
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 05-06-09 02.00.00 Initial version.
|
||||
* 11-18-14 02.00.01 Updated copyright information.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_RA_H
|
||||
#define MPI2_RA_H
|
||||
|
||||
/* generic structure for RAID Accelerator Control Block */
|
||||
typedef struct _MPI2_RAID_ACCELERATOR_CONTROL_BLOCK
|
||||
{
|
||||
U32 Reserved[8]; /* 0x00 */
|
||||
U32 RaidAcceleratorCDB[1]; /* 0x20 */
|
||||
} MPI2_RAID_ACCELERATOR_CONTROL_BLOCK,
|
||||
MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_CONTROL_BLOCK,
|
||||
Mpi2RAIDAcceleratorControlBlock_t,
|
||||
MPI2_POINTER pMpi2RAIDAcceleratorControlBlock_t;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* RAID Accelerator Messages
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
/* RAID Accelerator Request Message */
|
||||
typedef struct _MPI2_RAID_ACCELERATOR_REQUEST
|
||||
{
|
||||
U16 Reserved0; /* 0x00 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 Reserved1; /* 0x04 */
|
||||
U8 Reserved2; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U64 RaidAcceleratorControlBlockAddress; /* 0x0C */
|
||||
U8 DmaEngineNumber; /* 0x14 */
|
||||
U8 Reserved4; /* 0x15 */
|
||||
U16 Reserved5; /* 0x16 */
|
||||
U32 Reserved6; /* 0x18 */
|
||||
U32 Reserved7; /* 0x1C */
|
||||
U32 Reserved8; /* 0x20 */
|
||||
} MPI2_RAID_ACCELERATOR_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_REQUEST,
|
||||
Mpi2RAIDAcceleratorRequest_t, MPI2_POINTER pMpi2RAIDAcceleratorRequest_t;
|
||||
|
||||
|
||||
/* RAID Accelerator Error Reply Message */
|
||||
typedef struct _MPI2_RAID_ACCELERATOR_REPLY
|
||||
{
|
||||
U16 Reserved0; /* 0x00 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 Reserved1; /* 0x04 */
|
||||
U8 Reserved2; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U16 Reserved4; /* 0x0C */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
U32 ProductSpecificData[3]; /* 0x14 */
|
||||
} MPI2_RAID_ACCELERATOR_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_REPLY,
|
||||
Mpi2RAIDAcceleratorReply_t, MPI2_POINTER pMpi2RAIDAcceleratorReply_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,374 +1,374 @@
|
|||
/*
|
||||
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_raid.h
|
||||
* Title: MPI Integrated RAID messages and structures
|
||||
* Creation Date: April 26, 2007
|
||||
*
|
||||
* mpi2_raid.h Version: 02.00.11
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
|
||||
* 08-31-07 02.00.01 Modifications to RAID Action request and reply,
|
||||
* including the Actions and ActionData.
|
||||
* 02-29-08 02.00.02 Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD.
|
||||
* 05-21-08 02.00.03 Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that
|
||||
* the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT
|
||||
* can be sized by the build environment.
|
||||
* 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of
|
||||
* VolumeCreationFlags and marked the old one as obsolete.
|
||||
* 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
|
||||
* 08-24-10 02.00.06 Added MPI2_RAID_ACTION_COMPATIBILITY_CHECK along with
|
||||
* related structures and defines.
|
||||
* Added product-specific range to RAID Action values.
|
||||
* 11-18-11 02.00.07 Incorporating additions for MPI v2.5.
|
||||
* 02-06-12 02.00.08 Added MPI2_RAID_ACTION_PHYSDISK_HIDDEN.
|
||||
* 07-26-12 02.00.09 Added ElapsedSeconds field to MPI2_RAID_VOL_INDICATOR.
|
||||
* Added MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID define.
|
||||
* 04-17-13 02.00.10 Added MPI25_RAID_ACTION_ADATA_ALLOW_PI.
|
||||
* 11-18-14 02.00.11 Updated copyright information.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_RAID_H
|
||||
#define MPI2_RAID_H
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Integrated RAID Messages
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* RAID Action messages
|
||||
****************************************************************************/
|
||||
|
||||
/* ActionDataWord defines for use with MPI2_RAID_ACTION_CREATE_VOLUME action */
|
||||
#define MPI25_RAID_ACTION_ADATA_ALLOW_PI (0x80000000)
|
||||
|
||||
/* ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */
|
||||
#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000)
|
||||
#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000001)
|
||||
|
||||
/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
|
||||
|
||||
/* ActionDataWord defines for use with MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */
|
||||
#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD (0x00000001)
|
||||
|
||||
/* ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */
|
||||
typedef struct _MPI2_RAID_ACTION_RATE_DATA
|
||||
{
|
||||
U8 RateToChange; /* 0x00 */
|
||||
U8 RateOrMode; /* 0x01 */
|
||||
U16 DataScrubDuration; /* 0x02 */
|
||||
} MPI2_RAID_ACTION_RATE_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_RATE_DATA,
|
||||
Mpi2RaidActionRateData_t, MPI2_POINTER pMpi2RaidActionRateData_t;
|
||||
|
||||
#define MPI2_RAID_ACTION_SET_RATE_RESYNC (0x00)
|
||||
#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB (0x01)
|
||||
#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE (0x02)
|
||||
|
||||
/* ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */
|
||||
typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION
|
||||
{
|
||||
U8 RAIDFunction; /* 0x00 */
|
||||
U8 Flags; /* 0x01 */
|
||||
U16 Reserved1; /* 0x02 */
|
||||
} MPI2_RAID_ACTION_START_RAID_FUNCTION,
|
||||
MPI2_POINTER PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION,
|
||||
Mpi2RaidActionStartRaidFunction_t,
|
||||
MPI2_POINTER pMpi2RaidActionStartRaidFunction_t;
|
||||
|
||||
/* defines for the RAIDFunction field */
|
||||
#define MPI2_RAID_ACTION_START_BACKGROUND_INIT (0x00)
|
||||
#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01)
|
||||
#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK (0x02)
|
||||
|
||||
/* defines for the Flags field */
|
||||
#define MPI2_RAID_ACTION_START_NEW (0x00)
|
||||
#define MPI2_RAID_ACTION_START_RESUME (0x01)
|
||||
|
||||
/* ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */
|
||||
typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION
|
||||
{
|
||||
U8 RAIDFunction; /* 0x00 */
|
||||
U8 Flags; /* 0x01 */
|
||||
U16 Reserved1; /* 0x02 */
|
||||
} MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
|
||||
MPI2_POINTER PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
|
||||
Mpi2RaidActionStopRaidFunction_t,
|
||||
MPI2_POINTER pMpi2RaidActionStopRaidFunction_t;
|
||||
|
||||
/* defines for the RAIDFunction field */
|
||||
#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT (0x00)
|
||||
#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION (0x01)
|
||||
#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK (0x02)
|
||||
|
||||
/* defines for the Flags field */
|
||||
#define MPI2_RAID_ACTION_STOP_ABORT (0x00)
|
||||
#define MPI2_RAID_ACTION_STOP_PAUSE (0x01)
|
||||
|
||||
/* ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */
|
||||
typedef struct _MPI2_RAID_ACTION_HOT_SPARE
|
||||
{
|
||||
U8 HotSparePool; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U16 DevHandle; /* 0x02 */
|
||||
} MPI2_RAID_ACTION_HOT_SPARE, MPI2_POINTER PTR_MPI2_RAID_ACTION_HOT_SPARE,
|
||||
Mpi2RaidActionHotSpare_t, MPI2_POINTER pMpi2RaidActionHotSpare_t;
|
||||
|
||||
/* ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */
|
||||
typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE
|
||||
{
|
||||
U8 Flags; /* 0x00 */
|
||||
U8 DeviceFirmwareUpdateModeTimeout; /* 0x01 */
|
||||
U16 Reserved1; /* 0x02 */
|
||||
} MPI2_RAID_ACTION_FW_UPDATE_MODE,
|
||||
MPI2_POINTER PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE,
|
||||
Mpi2RaidActionFwUpdateMode_t, MPI2_POINTER pMpi2RaidActionFwUpdateMode_t;
|
||||
|
||||
/* ActionDataWord defines for use with MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */
|
||||
#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE (0x00)
|
||||
#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE (0x01)
|
||||
|
||||
typedef union _MPI2_RAID_ACTION_DATA
|
||||
{
|
||||
U32 Word;
|
||||
MPI2_RAID_ACTION_RATE_DATA Rates;
|
||||
MPI2_RAID_ACTION_START_RAID_FUNCTION StartRaidFunction;
|
||||
MPI2_RAID_ACTION_STOP_RAID_FUNCTION StopRaidFunction;
|
||||
MPI2_RAID_ACTION_HOT_SPARE HotSpare;
|
||||
MPI2_RAID_ACTION_FW_UPDATE_MODE FwUpdateMode;
|
||||
} MPI2_RAID_ACTION_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_DATA,
|
||||
Mpi2RaidActionData_t, MPI2_POINTER pMpi2RaidActionData_t;
|
||||
|
||||
|
||||
/* RAID Action Request Message */
|
||||
typedef struct _MPI2_RAID_ACTION_REQUEST
|
||||
{
|
||||
U8 Action; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 VolDevHandle; /* 0x04 */
|
||||
U8 PhysDiskNum; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U32 Reserved3; /* 0x0C */
|
||||
MPI2_RAID_ACTION_DATA ActionDataWord; /* 0x10 */
|
||||
MPI2_SGE_SIMPLE_UNION ActionDataSGE; /* 0x14 */
|
||||
} MPI2_RAID_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACTION_REQUEST,
|
||||
Mpi2RaidActionRequest_t, MPI2_POINTER pMpi2RaidActionRequest_t;
|
||||
|
||||
/* RAID Action request Action values */
|
||||
|
||||
#define MPI2_RAID_ACTION_INDICATOR_STRUCT (0x01)
|
||||
#define MPI2_RAID_ACTION_CREATE_VOLUME (0x02)
|
||||
#define MPI2_RAID_ACTION_DELETE_VOLUME (0x03)
|
||||
#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES (0x04)
|
||||
#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES (0x05)
|
||||
#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE (0x0A)
|
||||
#define MPI2_RAID_ACTION_PHYSDISK_ONLINE (0x0B)
|
||||
#define MPI2_RAID_ACTION_FAIL_PHYSDISK (0x0F)
|
||||
#define MPI2_RAID_ACTION_ACTIVATE_VOLUME (0x11)
|
||||
#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15)
|
||||
#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE (0x17)
|
||||
#define MPI2_RAID_ACTION_SET_VOLUME_NAME (0x18)
|
||||
#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE (0x19)
|
||||
#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME (0x1C)
|
||||
#define MPI2_RAID_ACTION_CREATE_HOT_SPARE (0x1D)
|
||||
#define MPI2_RAID_ACTION_DELETE_HOT_SPARE (0x1E)
|
||||
#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED (0x20)
|
||||
#define MPI2_RAID_ACTION_START_RAID_FUNCTION (0x21)
|
||||
#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION (0x22)
|
||||
#define MPI2_RAID_ACTION_COMPATIBILITY_CHECK (0x23)
|
||||
#define MPI2_RAID_ACTION_PHYSDISK_HIDDEN (0x24)
|
||||
#define MPI2_RAID_ACTION_MIN_PRODUCT_SPECIFIC (0x80)
|
||||
#define MPI2_RAID_ACTION_MAX_PRODUCT_SPECIFIC (0xFF)
|
||||
|
||||
|
||||
/* RAID Volume Creation Structure */
|
||||
|
||||
/*
|
||||
* The following define can be customized for the targeted product.
|
||||
*/
|
||||
#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS
|
||||
#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_RAID_VOLUME_PHYSDISK
|
||||
{
|
||||
U8 RAIDSetNum; /* 0x00 */
|
||||
U8 PhysDiskMap; /* 0x01 */
|
||||
U16 PhysDiskDevHandle; /* 0x02 */
|
||||
} MPI2_RAID_VOLUME_PHYSDISK, MPI2_POINTER PTR_MPI2_RAID_VOLUME_PHYSDISK,
|
||||
Mpi2RaidVolumePhysDisk_t, MPI2_POINTER pMpi2RaidVolumePhysDisk_t;
|
||||
|
||||
/* defines for the PhysDiskMap field */
|
||||
#define MPI2_RAIDACTION_PHYSDISK_PRIMARY (0x01)
|
||||
#define MPI2_RAIDACTION_PHYSDISK_SECONDARY (0x02)
|
||||
|
||||
typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT
|
||||
{
|
||||
U8 NumPhysDisks; /* 0x00 */
|
||||
U8 VolumeType; /* 0x01 */
|
||||
U16 Reserved1; /* 0x02 */
|
||||
U32 VolumeCreationFlags; /* 0x04 */
|
||||
U32 VolumeSettings; /* 0x08 */
|
||||
U8 Reserved2; /* 0x0C */
|
||||
U8 ResyncRate; /* 0x0D */
|
||||
U16 DataScrubDuration; /* 0x0E */
|
||||
U64 VolumeMaxLBA; /* 0x10 */
|
||||
U32 StripeSize; /* 0x18 */
|
||||
U8 Name[16]; /* 0x1C */
|
||||
MPI2_RAID_VOLUME_PHYSDISK PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS];/* 0x2C */
|
||||
} MPI2_RAID_VOLUME_CREATION_STRUCT,
|
||||
MPI2_POINTER PTR_MPI2_RAID_VOLUME_CREATION_STRUCT,
|
||||
Mpi2RaidVolumeCreationStruct_t, MPI2_POINTER pMpi2RaidVolumeCreationStruct_t;
|
||||
|
||||
/* use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */
|
||||
|
||||
/* defines for the VolumeCreationFlags field */
|
||||
#define MPI2_RAID_VOL_CREATION_DEFAULT_SETTINGS (0x80000000)
|
||||
#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT (0x00000004) /* MPI 2.0 only */
|
||||
#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT (0x00000002)
|
||||
#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA (0x00000001)
|
||||
/* The following is an obsolete define.
|
||||
* It must be shifted left 24 bits in order to set the proper bit.
|
||||
*/
|
||||
#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80)
|
||||
|
||||
|
||||
/* RAID Online Capacity Expansion Structure */
|
||||
|
||||
typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION
|
||||
{
|
||||
U32 Flags; /* 0x00 */
|
||||
U16 DevHandle0; /* 0x04 */
|
||||
U16 Reserved1; /* 0x06 */
|
||||
U16 DevHandle1; /* 0x08 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
} MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
|
||||
MPI2_POINTER PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
|
||||
Mpi2RaidOnlineCapacityExpansion_t,
|
||||
MPI2_POINTER pMpi2RaidOnlineCapacityExpansion_t;
|
||||
|
||||
|
||||
/* RAID Compatibility Input Structure */
|
||||
|
||||
typedef struct _MPI2_RAID_COMPATIBILITY_INPUT_STRUCT
|
||||
{
|
||||
U16 SourceDevHandle; /* 0x00 */
|
||||
U16 CandidateDevHandle; /* 0x02 */
|
||||
U32 Flags; /* 0x04 */
|
||||
U32 Reserved1; /* 0x08 */
|
||||
U32 Reserved2; /* 0x0C */
|
||||
} MPI2_RAID_COMPATIBILITY_INPUT_STRUCT,
|
||||
MPI2_POINTER PTR_MPI2_RAID_COMPATIBILITY_INPUT_STRUCT,
|
||||
Mpi2RaidCompatibilityInputStruct_t,
|
||||
MPI2_POINTER pMpi2RaidCompatibilityInputStruct_t;
|
||||
|
||||
/* defines for RAID Compatibility Structure Flags field */
|
||||
#define MPI2_RAID_COMPAT_SOURCE_IS_VOLUME_FLAG (0x00000002)
|
||||
#define MPI2_RAID_COMPAT_REPORT_SOURCE_INFO_FLAG (0x00000001)
|
||||
|
||||
|
||||
/* RAID Volume Indicator Structure */
|
||||
|
||||
typedef struct _MPI2_RAID_VOL_INDICATOR
|
||||
{
|
||||
U64 TotalBlocks; /* 0x00 */
|
||||
U64 BlocksRemaining; /* 0x08 */
|
||||
U32 Flags; /* 0x10 */
|
||||
U32 ElapsedSeconds; /* 0x14 */
|
||||
} MPI2_RAID_VOL_INDICATOR, MPI2_POINTER PTR_MPI2_RAID_VOL_INDICATOR,
|
||||
Mpi2RaidVolIndicator_t, MPI2_POINTER pMpi2RaidVolIndicator_t;
|
||||
|
||||
/* defines for RAID Volume Indicator Flags field */
|
||||
#define MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID (0x80000000)
|
||||
|
||||
#define MPI2_RAID_VOL_FLAGS_OP_MASK (0x0000000F)
|
||||
#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT (0x00000000)
|
||||
#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001)
|
||||
#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002)
|
||||
#define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003)
|
||||
#define MPI2_RAID_VOL_FLAGS_OP_MDC (0x00000004)
|
||||
|
||||
|
||||
/* RAID Compatibility Result Structure */
|
||||
|
||||
typedef struct _MPI2_RAID_COMPATIBILITY_RESULT_STRUCT
|
||||
{
|
||||
U8 State; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U16 Reserved2; /* 0x02 */
|
||||
U32 GenericAttributes; /* 0x04 */
|
||||
U32 OEMSpecificAttributes; /* 0x08 */
|
||||
U32 Reserved3; /* 0x0C */
|
||||
U32 Reserved4; /* 0x10 */
|
||||
} MPI2_RAID_COMPATIBILITY_RESULT_STRUCT,
|
||||
MPI2_POINTER PTR_MPI2_RAID_COMPATIBILITY_RESULT_STRUCT,
|
||||
Mpi2RaidCompatibilityResultStruct_t,
|
||||
MPI2_POINTER pMpi2RaidCompatibilityResultStruct_t;
|
||||
|
||||
/* defines for RAID Compatibility Result Structure State field */
|
||||
#define MPI2_RAID_COMPAT_STATE_COMPATIBLE (0x00)
|
||||
#define MPI2_RAID_COMPAT_STATE_NOT_COMPATIBLE (0x01)
|
||||
|
||||
/* defines for RAID Compatibility Result Structure GenericAttributes field */
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_4K_SECTOR (0x00000010)
|
||||
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_MEDIA_MASK (0x0000000C)
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_SOLID_STATE_DRIVE (0x00000008)
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_HARD_DISK_DRIVE (0x00000004)
|
||||
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_PROTOCOL_MASK (0x00000003)
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_SAS_PROTOCOL (0x00000002)
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_SATA_PROTOCOL (0x00000001)
|
||||
|
||||
|
||||
/* RAID Action Reply ActionData union */
|
||||
typedef union _MPI2_RAID_ACTION_REPLY_DATA
|
||||
{
|
||||
U32 Word[6];
|
||||
MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator;
|
||||
U16 VolDevHandle;
|
||||
U8 VolumeState;
|
||||
U8 PhysDiskNum;
|
||||
MPI2_RAID_COMPATIBILITY_RESULT_STRUCT RaidCompatibilityResult;
|
||||
} MPI2_RAID_ACTION_REPLY_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY_DATA,
|
||||
Mpi2RaidActionReplyData_t, MPI2_POINTER pMpi2RaidActionReplyData_t;
|
||||
|
||||
/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
|
||||
|
||||
|
||||
/* RAID Action Reply Message */
|
||||
typedef struct _MPI2_RAID_ACTION_REPLY
|
||||
{
|
||||
U8 Action; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 VolDevHandle; /* 0x04 */
|
||||
U8 PhysDiskNum; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U16 Reserved3; /* 0x0C */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
MPI2_RAID_ACTION_REPLY_DATA ActionData; /* 0x14 */
|
||||
} MPI2_RAID_ACTION_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY,
|
||||
Mpi2RaidActionReply_t, MPI2_POINTER pMpi2RaidActionReply_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_raid.h
|
||||
* Title: MPI Integrated RAID messages and structures
|
||||
* Creation Date: April 26, 2007
|
||||
*
|
||||
* mpi2_raid.h Version: 02.00.11
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
|
||||
* 08-31-07 02.00.01 Modifications to RAID Action request and reply,
|
||||
* including the Actions and ActionData.
|
||||
* 02-29-08 02.00.02 Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD.
|
||||
* 05-21-08 02.00.03 Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that
|
||||
* the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT
|
||||
* can be sized by the build environment.
|
||||
* 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of
|
||||
* VolumeCreationFlags and marked the old one as obsolete.
|
||||
* 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
|
||||
* 08-24-10 02.00.06 Added MPI2_RAID_ACTION_COMPATIBILITY_CHECK along with
|
||||
* related structures and defines.
|
||||
* Added product-specific range to RAID Action values.
|
||||
* 11-18-11 02.00.07 Incorporating additions for MPI v2.5.
|
||||
* 02-06-12 02.00.08 Added MPI2_RAID_ACTION_PHYSDISK_HIDDEN.
|
||||
* 07-26-12 02.00.09 Added ElapsedSeconds field to MPI2_RAID_VOL_INDICATOR.
|
||||
* Added MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID define.
|
||||
* 04-17-13 02.00.10 Added MPI25_RAID_ACTION_ADATA_ALLOW_PI.
|
||||
* 11-18-14 02.00.11 Updated copyright information.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_RAID_H
|
||||
#define MPI2_RAID_H
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Integrated RAID Messages
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* RAID Action messages
|
||||
****************************************************************************/
|
||||
|
||||
/* ActionDataWord defines for use with MPI2_RAID_ACTION_CREATE_VOLUME action */
|
||||
#define MPI25_RAID_ACTION_ADATA_ALLOW_PI (0x80000000)
|
||||
|
||||
/* ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */
|
||||
#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000)
|
||||
#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000001)
|
||||
|
||||
/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
|
||||
|
||||
/* ActionDataWord defines for use with MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */
|
||||
#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD (0x00000001)
|
||||
|
||||
/* ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */
|
||||
typedef struct _MPI2_RAID_ACTION_RATE_DATA
|
||||
{
|
||||
U8 RateToChange; /* 0x00 */
|
||||
U8 RateOrMode; /* 0x01 */
|
||||
U16 DataScrubDuration; /* 0x02 */
|
||||
} MPI2_RAID_ACTION_RATE_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_RATE_DATA,
|
||||
Mpi2RaidActionRateData_t, MPI2_POINTER pMpi2RaidActionRateData_t;
|
||||
|
||||
#define MPI2_RAID_ACTION_SET_RATE_RESYNC (0x00)
|
||||
#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB (0x01)
|
||||
#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE (0x02)
|
||||
|
||||
/* ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */
|
||||
typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION
|
||||
{
|
||||
U8 RAIDFunction; /* 0x00 */
|
||||
U8 Flags; /* 0x01 */
|
||||
U16 Reserved1; /* 0x02 */
|
||||
} MPI2_RAID_ACTION_START_RAID_FUNCTION,
|
||||
MPI2_POINTER PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION,
|
||||
Mpi2RaidActionStartRaidFunction_t,
|
||||
MPI2_POINTER pMpi2RaidActionStartRaidFunction_t;
|
||||
|
||||
/* defines for the RAIDFunction field */
|
||||
#define MPI2_RAID_ACTION_START_BACKGROUND_INIT (0x00)
|
||||
#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01)
|
||||
#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK (0x02)
|
||||
|
||||
/* defines for the Flags field */
|
||||
#define MPI2_RAID_ACTION_START_NEW (0x00)
|
||||
#define MPI2_RAID_ACTION_START_RESUME (0x01)
|
||||
|
||||
/* ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */
|
||||
typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION
|
||||
{
|
||||
U8 RAIDFunction; /* 0x00 */
|
||||
U8 Flags; /* 0x01 */
|
||||
U16 Reserved1; /* 0x02 */
|
||||
} MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
|
||||
MPI2_POINTER PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
|
||||
Mpi2RaidActionStopRaidFunction_t,
|
||||
MPI2_POINTER pMpi2RaidActionStopRaidFunction_t;
|
||||
|
||||
/* defines for the RAIDFunction field */
|
||||
#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT (0x00)
|
||||
#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION (0x01)
|
||||
#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK (0x02)
|
||||
|
||||
/* defines for the Flags field */
|
||||
#define MPI2_RAID_ACTION_STOP_ABORT (0x00)
|
||||
#define MPI2_RAID_ACTION_STOP_PAUSE (0x01)
|
||||
|
||||
/* ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */
|
||||
typedef struct _MPI2_RAID_ACTION_HOT_SPARE
|
||||
{
|
||||
U8 HotSparePool; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U16 DevHandle; /* 0x02 */
|
||||
} MPI2_RAID_ACTION_HOT_SPARE, MPI2_POINTER PTR_MPI2_RAID_ACTION_HOT_SPARE,
|
||||
Mpi2RaidActionHotSpare_t, MPI2_POINTER pMpi2RaidActionHotSpare_t;
|
||||
|
||||
/* ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */
|
||||
typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE
|
||||
{
|
||||
U8 Flags; /* 0x00 */
|
||||
U8 DeviceFirmwareUpdateModeTimeout; /* 0x01 */
|
||||
U16 Reserved1; /* 0x02 */
|
||||
} MPI2_RAID_ACTION_FW_UPDATE_MODE,
|
||||
MPI2_POINTER PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE,
|
||||
Mpi2RaidActionFwUpdateMode_t, MPI2_POINTER pMpi2RaidActionFwUpdateMode_t;
|
||||
|
||||
/* ActionDataWord defines for use with MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */
|
||||
#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE (0x00)
|
||||
#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE (0x01)
|
||||
|
||||
typedef union _MPI2_RAID_ACTION_DATA
|
||||
{
|
||||
U32 Word;
|
||||
MPI2_RAID_ACTION_RATE_DATA Rates;
|
||||
MPI2_RAID_ACTION_START_RAID_FUNCTION StartRaidFunction;
|
||||
MPI2_RAID_ACTION_STOP_RAID_FUNCTION StopRaidFunction;
|
||||
MPI2_RAID_ACTION_HOT_SPARE HotSpare;
|
||||
MPI2_RAID_ACTION_FW_UPDATE_MODE FwUpdateMode;
|
||||
} MPI2_RAID_ACTION_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_DATA,
|
||||
Mpi2RaidActionData_t, MPI2_POINTER pMpi2RaidActionData_t;
|
||||
|
||||
|
||||
/* RAID Action Request Message */
|
||||
typedef struct _MPI2_RAID_ACTION_REQUEST
|
||||
{
|
||||
U8 Action; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 VolDevHandle; /* 0x04 */
|
||||
U8 PhysDiskNum; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U32 Reserved3; /* 0x0C */
|
||||
MPI2_RAID_ACTION_DATA ActionDataWord; /* 0x10 */
|
||||
MPI2_SGE_SIMPLE_UNION ActionDataSGE; /* 0x14 */
|
||||
} MPI2_RAID_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACTION_REQUEST,
|
||||
Mpi2RaidActionRequest_t, MPI2_POINTER pMpi2RaidActionRequest_t;
|
||||
|
||||
/* RAID Action request Action values */
|
||||
|
||||
#define MPI2_RAID_ACTION_INDICATOR_STRUCT (0x01)
|
||||
#define MPI2_RAID_ACTION_CREATE_VOLUME (0x02)
|
||||
#define MPI2_RAID_ACTION_DELETE_VOLUME (0x03)
|
||||
#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES (0x04)
|
||||
#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES (0x05)
|
||||
#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE (0x0A)
|
||||
#define MPI2_RAID_ACTION_PHYSDISK_ONLINE (0x0B)
|
||||
#define MPI2_RAID_ACTION_FAIL_PHYSDISK (0x0F)
|
||||
#define MPI2_RAID_ACTION_ACTIVATE_VOLUME (0x11)
|
||||
#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15)
|
||||
#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE (0x17)
|
||||
#define MPI2_RAID_ACTION_SET_VOLUME_NAME (0x18)
|
||||
#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE (0x19)
|
||||
#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME (0x1C)
|
||||
#define MPI2_RAID_ACTION_CREATE_HOT_SPARE (0x1D)
|
||||
#define MPI2_RAID_ACTION_DELETE_HOT_SPARE (0x1E)
|
||||
#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED (0x20)
|
||||
#define MPI2_RAID_ACTION_START_RAID_FUNCTION (0x21)
|
||||
#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION (0x22)
|
||||
#define MPI2_RAID_ACTION_COMPATIBILITY_CHECK (0x23)
|
||||
#define MPI2_RAID_ACTION_PHYSDISK_HIDDEN (0x24)
|
||||
#define MPI2_RAID_ACTION_MIN_PRODUCT_SPECIFIC (0x80)
|
||||
#define MPI2_RAID_ACTION_MAX_PRODUCT_SPECIFIC (0xFF)
|
||||
|
||||
|
||||
/* RAID Volume Creation Structure */
|
||||
|
||||
/*
|
||||
* The following define can be customized for the targeted product.
|
||||
*/
|
||||
#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS
|
||||
#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI2_RAID_VOLUME_PHYSDISK
|
||||
{
|
||||
U8 RAIDSetNum; /* 0x00 */
|
||||
U8 PhysDiskMap; /* 0x01 */
|
||||
U16 PhysDiskDevHandle; /* 0x02 */
|
||||
} MPI2_RAID_VOLUME_PHYSDISK, MPI2_POINTER PTR_MPI2_RAID_VOLUME_PHYSDISK,
|
||||
Mpi2RaidVolumePhysDisk_t, MPI2_POINTER pMpi2RaidVolumePhysDisk_t;
|
||||
|
||||
/* defines for the PhysDiskMap field */
|
||||
#define MPI2_RAIDACTION_PHYSDISK_PRIMARY (0x01)
|
||||
#define MPI2_RAIDACTION_PHYSDISK_SECONDARY (0x02)
|
||||
|
||||
typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT
|
||||
{
|
||||
U8 NumPhysDisks; /* 0x00 */
|
||||
U8 VolumeType; /* 0x01 */
|
||||
U16 Reserved1; /* 0x02 */
|
||||
U32 VolumeCreationFlags; /* 0x04 */
|
||||
U32 VolumeSettings; /* 0x08 */
|
||||
U8 Reserved2; /* 0x0C */
|
||||
U8 ResyncRate; /* 0x0D */
|
||||
U16 DataScrubDuration; /* 0x0E */
|
||||
U64 VolumeMaxLBA; /* 0x10 */
|
||||
U32 StripeSize; /* 0x18 */
|
||||
U8 Name[16]; /* 0x1C */
|
||||
MPI2_RAID_VOLUME_PHYSDISK PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS];/* 0x2C */
|
||||
} MPI2_RAID_VOLUME_CREATION_STRUCT,
|
||||
MPI2_POINTER PTR_MPI2_RAID_VOLUME_CREATION_STRUCT,
|
||||
Mpi2RaidVolumeCreationStruct_t, MPI2_POINTER pMpi2RaidVolumeCreationStruct_t;
|
||||
|
||||
/* use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */
|
||||
|
||||
/* defines for the VolumeCreationFlags field */
|
||||
#define MPI2_RAID_VOL_CREATION_DEFAULT_SETTINGS (0x80000000)
|
||||
#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT (0x00000004) /* MPI 2.0 only */
|
||||
#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT (0x00000002)
|
||||
#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA (0x00000001)
|
||||
/* The following is an obsolete define.
|
||||
* It must be shifted left 24 bits in order to set the proper bit.
|
||||
*/
|
||||
#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80)
|
||||
|
||||
|
||||
/* RAID Online Capacity Expansion Structure */
|
||||
|
||||
typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION
|
||||
{
|
||||
U32 Flags; /* 0x00 */
|
||||
U16 DevHandle0; /* 0x04 */
|
||||
U16 Reserved1; /* 0x06 */
|
||||
U16 DevHandle1; /* 0x08 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
} MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
|
||||
MPI2_POINTER PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
|
||||
Mpi2RaidOnlineCapacityExpansion_t,
|
||||
MPI2_POINTER pMpi2RaidOnlineCapacityExpansion_t;
|
||||
|
||||
|
||||
/* RAID Compatibility Input Structure */
|
||||
|
||||
typedef struct _MPI2_RAID_COMPATIBILITY_INPUT_STRUCT
|
||||
{
|
||||
U16 SourceDevHandle; /* 0x00 */
|
||||
U16 CandidateDevHandle; /* 0x02 */
|
||||
U32 Flags; /* 0x04 */
|
||||
U32 Reserved1; /* 0x08 */
|
||||
U32 Reserved2; /* 0x0C */
|
||||
} MPI2_RAID_COMPATIBILITY_INPUT_STRUCT,
|
||||
MPI2_POINTER PTR_MPI2_RAID_COMPATIBILITY_INPUT_STRUCT,
|
||||
Mpi2RaidCompatibilityInputStruct_t,
|
||||
MPI2_POINTER pMpi2RaidCompatibilityInputStruct_t;
|
||||
|
||||
/* defines for RAID Compatibility Structure Flags field */
|
||||
#define MPI2_RAID_COMPAT_SOURCE_IS_VOLUME_FLAG (0x00000002)
|
||||
#define MPI2_RAID_COMPAT_REPORT_SOURCE_INFO_FLAG (0x00000001)
|
||||
|
||||
|
||||
/* RAID Volume Indicator Structure */
|
||||
|
||||
typedef struct _MPI2_RAID_VOL_INDICATOR
|
||||
{
|
||||
U64 TotalBlocks; /* 0x00 */
|
||||
U64 BlocksRemaining; /* 0x08 */
|
||||
U32 Flags; /* 0x10 */
|
||||
U32 ElapsedSeconds; /* 0x14 */
|
||||
} MPI2_RAID_VOL_INDICATOR, MPI2_POINTER PTR_MPI2_RAID_VOL_INDICATOR,
|
||||
Mpi2RaidVolIndicator_t, MPI2_POINTER pMpi2RaidVolIndicator_t;
|
||||
|
||||
/* defines for RAID Volume Indicator Flags field */
|
||||
#define MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID (0x80000000)
|
||||
|
||||
#define MPI2_RAID_VOL_FLAGS_OP_MASK (0x0000000F)
|
||||
#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT (0x00000000)
|
||||
#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001)
|
||||
#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002)
|
||||
#define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003)
|
||||
#define MPI2_RAID_VOL_FLAGS_OP_MDC (0x00000004)
|
||||
|
||||
|
||||
/* RAID Compatibility Result Structure */
|
||||
|
||||
typedef struct _MPI2_RAID_COMPATIBILITY_RESULT_STRUCT
|
||||
{
|
||||
U8 State; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U16 Reserved2; /* 0x02 */
|
||||
U32 GenericAttributes; /* 0x04 */
|
||||
U32 OEMSpecificAttributes; /* 0x08 */
|
||||
U32 Reserved3; /* 0x0C */
|
||||
U32 Reserved4; /* 0x10 */
|
||||
} MPI2_RAID_COMPATIBILITY_RESULT_STRUCT,
|
||||
MPI2_POINTER PTR_MPI2_RAID_COMPATIBILITY_RESULT_STRUCT,
|
||||
Mpi2RaidCompatibilityResultStruct_t,
|
||||
MPI2_POINTER pMpi2RaidCompatibilityResultStruct_t;
|
||||
|
||||
/* defines for RAID Compatibility Result Structure State field */
|
||||
#define MPI2_RAID_COMPAT_STATE_COMPATIBLE (0x00)
|
||||
#define MPI2_RAID_COMPAT_STATE_NOT_COMPATIBLE (0x01)
|
||||
|
||||
/* defines for RAID Compatibility Result Structure GenericAttributes field */
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_4K_SECTOR (0x00000010)
|
||||
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_MEDIA_MASK (0x0000000C)
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_SOLID_STATE_DRIVE (0x00000008)
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_HARD_DISK_DRIVE (0x00000004)
|
||||
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_PROTOCOL_MASK (0x00000003)
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_SAS_PROTOCOL (0x00000002)
|
||||
#define MPI2_RAID_COMPAT_GENATTRIB_SATA_PROTOCOL (0x00000001)
|
||||
|
||||
|
||||
/* RAID Action Reply ActionData union */
|
||||
typedef union _MPI2_RAID_ACTION_REPLY_DATA
|
||||
{
|
||||
U32 Word[6];
|
||||
MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator;
|
||||
U16 VolDevHandle;
|
||||
U8 VolumeState;
|
||||
U8 PhysDiskNum;
|
||||
MPI2_RAID_COMPATIBILITY_RESULT_STRUCT RaidCompatibilityResult;
|
||||
} MPI2_RAID_ACTION_REPLY_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY_DATA,
|
||||
Mpi2RaidActionReplyData_t, MPI2_POINTER pMpi2RaidActionReplyData_t;
|
||||
|
||||
/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
|
||||
|
||||
|
||||
/* RAID Action Reply Message */
|
||||
typedef struct _MPI2_RAID_ACTION_REPLY
|
||||
{
|
||||
U8 Action; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 VolDevHandle; /* 0x04 */
|
||||
U8 PhysDiskNum; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U16 Reserved3; /* 0x0C */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
MPI2_RAID_ACTION_REPLY_DATA ActionData; /* 0x14 */
|
||||
} MPI2_RAID_ACTION_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY,
|
||||
Mpi2RaidActionReply_t, MPI2_POINTER pMpi2RaidActionReply_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1,319 +1,319 @@
|
|||
/*
|
||||
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_sas.h
|
||||
* Title: MPI Serial Attached SCSI structures and definitions
|
||||
* Creation Date: February 9, 2007
|
||||
*
|
||||
* mpi2_sas.h Version: 02.00.10
|
||||
*
|
||||
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
|
||||
* prefix are for use only on MPI v2.5 products, and must not be used
|
||||
* with MPI v2.0 products. Unless otherwise noted, names beginning with
|
||||
* MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
|
||||
* 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit
|
||||
* Control Request.
|
||||
* 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control
|
||||
* Request.
|
||||
* 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
|
||||
* to MPI2_SGE_IO_UNION since it supports chained SGLs.
|
||||
* 05-12-10 02.00.04 Modified some comments.
|
||||
* 08-11-10 02.00.05 Added NCQ operations to SAS IO Unit Control.
|
||||
* 11-18-11 02.00.06 Incorporating additions for MPI v2.5.
|
||||
* 07-10-12 02.00.07 Added MPI2_SATA_PT_SGE_UNION for use in the SATA
|
||||
* Passthrough Request message.
|
||||
* 08-19-13 02.00.08 Made MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL obsolete
|
||||
* for anything newer than MPI v2.0.
|
||||
* 11-18-14 02.00.09 Updated copyright information.
|
||||
* 03-16-15 02.00.10 Updated for MPI v2.6.
|
||||
* Added MPI2_SATA_PT_REQ_PT_FLAGS_FPDMA.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_SAS_H
|
||||
#define MPI2_SAS_H
|
||||
|
||||
/*
|
||||
* Values for SASStatus.
|
||||
*/
|
||||
#define MPI2_SASSTATUS_SUCCESS (0x00)
|
||||
#define MPI2_SASSTATUS_UNKNOWN_ERROR (0x01)
|
||||
#define MPI2_SASSTATUS_INVALID_FRAME (0x02)
|
||||
#define MPI2_SASSTATUS_UTC_BAD_DEST (0x03)
|
||||
#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED (0x04)
|
||||
#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05)
|
||||
#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06)
|
||||
#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07)
|
||||
#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08)
|
||||
#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION (0x09)
|
||||
#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A)
|
||||
#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT (0x0B)
|
||||
#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C)
|
||||
#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D)
|
||||
#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E)
|
||||
#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F)
|
||||
#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10)
|
||||
#define MPI2_SASSTATUS_DATA_OFFSET_ERROR (0x11)
|
||||
#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED (0x12)
|
||||
#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED (0x13)
|
||||
#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14)
|
||||
|
||||
|
||||
/*
|
||||
* Values for the SAS DeviceInfo field used in SAS Device Status Change Event
|
||||
* data and SAS Configuration pages.
|
||||
*/
|
||||
#define MPI2_SAS_DEVICE_INFO_SEP (0x00004000)
|
||||
#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
|
||||
#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
|
||||
#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
|
||||
#define MPI2_SAS_DEVICE_INFO_SSP_TARGET (0x00000400)
|
||||
#define MPI2_SAS_DEVICE_INFO_STP_TARGET (0x00000200)
|
||||
#define MPI2_SAS_DEVICE_INFO_SMP_TARGET (0x00000100)
|
||||
#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080)
|
||||
#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040)
|
||||
#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020)
|
||||
#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010)
|
||||
#define MPI2_SAS_DEVICE_INFO_SATA_HOST (0x00000008)
|
||||
|
||||
#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007)
|
||||
#define MPI2_SAS_DEVICE_INFO_NO_DEVICE (0x00000000)
|
||||
#define MPI2_SAS_DEVICE_INFO_END_DEVICE (0x00000001)
|
||||
#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002)
|
||||
#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003)
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* SAS Messages
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* SMP Passthrough messages
|
||||
****************************************************************************/
|
||||
|
||||
/* SMP Passthrough Request Message */
|
||||
typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST
|
||||
{
|
||||
U8 PassthroughFlags; /* 0x00 */
|
||||
U8 PhysicalPort; /* 0x01 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 RequestDataLength; /* 0x04 */
|
||||
U8 SGLFlags; /* 0x06 */ /* MPI v2.0 only. Reserved on MPI v2.5. */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved1; /* 0x0A */
|
||||
U32 Reserved2; /* 0x0C */
|
||||
U64 SASAddress; /* 0x10 */
|
||||
U32 Reserved3; /* 0x18 */
|
||||
U32 Reserved4; /* 0x1C */
|
||||
MPI2_SIMPLE_SGE_UNION SGL; /* 0x20 */ /* MPI v2.5: IEEE Simple 64 elements only */
|
||||
} MPI2_SMP_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REQUEST,
|
||||
Mpi2SmpPassthroughRequest_t, MPI2_POINTER pMpi2SmpPassthroughRequest_t;
|
||||
|
||||
/* values for PassthroughFlags field */
|
||||
#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80)
|
||||
|
||||
/* MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
|
||||
|
||||
|
||||
/* SMP Passthrough Reply Message */
|
||||
typedef struct _MPI2_SMP_PASSTHROUGH_REPLY
|
||||
{
|
||||
U8 PassthroughFlags; /* 0x00 */
|
||||
U8 PhysicalPort; /* 0x01 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 ResponseDataLength; /* 0x04 */
|
||||
U8 SGLFlags; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved1; /* 0x0A */
|
||||
U8 Reserved2; /* 0x0C */
|
||||
U8 SASStatus; /* 0x0D */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
U32 Reserved3; /* 0x14 */
|
||||
U8 ResponseData[4]; /* 0x18 */
|
||||
} MPI2_SMP_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REPLY,
|
||||
Mpi2SmpPassthroughReply_t, MPI2_POINTER pMpi2SmpPassthroughReply_t;
|
||||
|
||||
/* values for PassthroughFlags field */
|
||||
#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80)
|
||||
|
||||
/* values for SASStatus field are at the top of this file */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* SATA Passthrough messages
|
||||
****************************************************************************/
|
||||
|
||||
typedef union _MPI2_SATA_PT_SGE_UNION
|
||||
{
|
||||
MPI2_SGE_SIMPLE_UNION MpiSimple; /* MPI v2.0 only */
|
||||
MPI2_SGE_CHAIN_UNION MpiChain; /* MPI v2.0 only */
|
||||
MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
|
||||
MPI2_IEEE_SGE_CHAIN_UNION IeeeChain; /* MPI v2.0 only */
|
||||
MPI25_IEEE_SGE_CHAIN64 IeeeChain64; /* MPI v2.5 only */
|
||||
} MPI2_SATA_PT_SGE_UNION, MPI2_POINTER PTR_MPI2_SATA_PT_SGE_UNION,
|
||||
Mpi2SataPTSGEUnion_t, MPI2_POINTER pMpi2SataPTSGEUnion_t;
|
||||
|
||||
|
||||
/* SATA Passthrough Request Message */
|
||||
typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST
|
||||
{
|
||||
U16 DevHandle; /* 0x00 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 PassthroughFlags; /* 0x04 */
|
||||
U8 SGLFlags; /* 0x06 */ /* MPI v2.0 only. Reserved on MPI v2.5. */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved1; /* 0x0A */
|
||||
U32 Reserved2; /* 0x0C */
|
||||
U32 Reserved3; /* 0x10 */
|
||||
U32 Reserved4; /* 0x14 */
|
||||
U32 DataLength; /* 0x18 */
|
||||
U8 CommandFIS[20]; /* 0x1C */
|
||||
MPI2_SATA_PT_SGE_UNION SGL; /* 0x30 */ /* MPI v2.5: IEEE 64 elements only */
|
||||
} MPI2_SATA_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REQUEST,
|
||||
Mpi2SataPassthroughRequest_t, MPI2_POINTER pMpi2SataPassthroughRequest_t;
|
||||
|
||||
/* values for PassthroughFlags field */
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100)
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_FPDMA (0x0040) /* MPI v2.6 and newer */
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020)
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010)
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004)
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002)
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001)
|
||||
|
||||
/* MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
|
||||
|
||||
|
||||
/* SATA Passthrough Reply Message */
|
||||
typedef struct _MPI2_SATA_PASSTHROUGH_REPLY
|
||||
{
|
||||
U16 DevHandle; /* 0x00 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 PassthroughFlags; /* 0x04 */
|
||||
U8 SGLFlags; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved1; /* 0x0A */
|
||||
U8 Reserved2; /* 0x0C */
|
||||
U8 SASStatus; /* 0x0D */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
U8 StatusFIS[20]; /* 0x14 */
|
||||
U32 StatusControlRegisters; /* 0x28 */
|
||||
U32 TransferCount; /* 0x2C */
|
||||
} MPI2_SATA_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REPLY,
|
||||
Mpi2SataPassthroughReply_t, MPI2_POINTER pMpi2SataPassthroughReply_t;
|
||||
|
||||
/* values for SASStatus field are at the top of this file */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* SAS IO Unit Control messages
|
||||
* (MPI v2.5 and earlier only.
|
||||
* Replaced by IO Unit Control messages in MPI v2.6 and later.)
|
||||
****************************************************************************/
|
||||
|
||||
/* SAS IO Unit Control Request Message */
|
||||
typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST
|
||||
{
|
||||
U8 Operation; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 DevHandle; /* 0x04 */
|
||||
U8 IOCParameter; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U16 Reserved4; /* 0x0C */
|
||||
U8 PhyNum; /* 0x0E */
|
||||
U8 PrimFlags; /* 0x0F */
|
||||
U32 Primitive; /* 0x10 */
|
||||
U8 LookupMethod; /* 0x14 */
|
||||
U8 Reserved5; /* 0x15 */
|
||||
U16 SlotNumber; /* 0x16 */
|
||||
U64 LookupAddress; /* 0x18 */
|
||||
U32 IOCParameterValue; /* 0x20 */
|
||||
U32 Reserved7; /* 0x24 */
|
||||
U32 Reserved8; /* 0x28 */
|
||||
} MPI2_SAS_IOUNIT_CONTROL_REQUEST,
|
||||
MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST,
|
||||
Mpi2SasIoUnitControlRequest_t, MPI2_POINTER pMpi2SasIoUnitControlRequest_t;
|
||||
|
||||
/* values for the Operation field */
|
||||
#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
|
||||
#define MPI2_SAS_OP_PHY_LINK_RESET (0x06)
|
||||
#define MPI2_SAS_OP_PHY_HARD_RESET (0x07)
|
||||
#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
|
||||
#define MPI2_SAS_OP_SEND_PRIMITIVE (0x0A)
|
||||
#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY (0x0B)
|
||||
#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C) /* MPI v2.0 only */
|
||||
#define MPI2_SAS_OP_REMOVE_DEVICE (0x0D)
|
||||
#define MPI2_SAS_OP_LOOKUP_MAPPING (0x0E)
|
||||
#define MPI2_SAS_OP_SET_IOC_PARAMETER (0x0F)
|
||||
#define MPI25_SAS_OP_ENABLE_FP_DEVICE (0x10)
|
||||
#define MPI25_SAS_OP_DISABLE_FP_DEVICE (0x11)
|
||||
#define MPI25_SAS_OP_ENABLE_FP_ALL (0x12)
|
||||
#define MPI25_SAS_OP_DISABLE_FP_ALL (0x13)
|
||||
#define MPI2_SAS_OP_DEV_ENABLE_NCQ (0x14)
|
||||
#define MPI2_SAS_OP_DEV_DISABLE_NCQ (0x15)
|
||||
#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80)
|
||||
|
||||
/* values for the PrimFlags field */
|
||||
#define MPI2_SAS_PRIMFLAGS_SINGLE (0x08)
|
||||
#define MPI2_SAS_PRIMFLAGS_TRIPLE (0x02)
|
||||
#define MPI2_SAS_PRIMFLAGS_REDUNDANT (0x01)
|
||||
|
||||
/* values for the LookupMethod field */
|
||||
#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS (0x01)
|
||||
#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT (0x02)
|
||||
#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03)
|
||||
|
||||
|
||||
/* SAS IO Unit Control Reply Message */
|
||||
typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY
|
||||
{
|
||||
U8 Operation; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 DevHandle; /* 0x04 */
|
||||
U8 IOCParameter; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U16 Reserved4; /* 0x0C */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
} MPI2_SAS_IOUNIT_CONTROL_REPLY,
|
||||
MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY,
|
||||
Mpi2SasIoUnitControlReply_t, MPI2_POINTER pMpi2SasIoUnitControlReply_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_sas.h
|
||||
* Title: MPI Serial Attached SCSI structures and definitions
|
||||
* Creation Date: February 9, 2007
|
||||
*
|
||||
* mpi2_sas.h Version: 02.00.10
|
||||
*
|
||||
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
|
||||
* prefix are for use only on MPI v2.5 products, and must not be used
|
||||
* with MPI v2.0 products. Unless otherwise noted, names beginning with
|
||||
* MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
|
||||
* 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit
|
||||
* Control Request.
|
||||
* 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control
|
||||
* Request.
|
||||
* 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
|
||||
* to MPI2_SGE_IO_UNION since it supports chained SGLs.
|
||||
* 05-12-10 02.00.04 Modified some comments.
|
||||
* 08-11-10 02.00.05 Added NCQ operations to SAS IO Unit Control.
|
||||
* 11-18-11 02.00.06 Incorporating additions for MPI v2.5.
|
||||
* 07-10-12 02.00.07 Added MPI2_SATA_PT_SGE_UNION for use in the SATA
|
||||
* Passthrough Request message.
|
||||
* 08-19-13 02.00.08 Made MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL obsolete
|
||||
* for anything newer than MPI v2.0.
|
||||
* 11-18-14 02.00.09 Updated copyright information.
|
||||
* 03-16-15 02.00.10 Updated for MPI v2.6.
|
||||
* Added MPI2_SATA_PT_REQ_PT_FLAGS_FPDMA.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_SAS_H
|
||||
#define MPI2_SAS_H
|
||||
|
||||
/*
|
||||
* Values for SASStatus.
|
||||
*/
|
||||
#define MPI2_SASSTATUS_SUCCESS (0x00)
|
||||
#define MPI2_SASSTATUS_UNKNOWN_ERROR (0x01)
|
||||
#define MPI2_SASSTATUS_INVALID_FRAME (0x02)
|
||||
#define MPI2_SASSTATUS_UTC_BAD_DEST (0x03)
|
||||
#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED (0x04)
|
||||
#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05)
|
||||
#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06)
|
||||
#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07)
|
||||
#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08)
|
||||
#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION (0x09)
|
||||
#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A)
|
||||
#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT (0x0B)
|
||||
#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C)
|
||||
#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D)
|
||||
#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E)
|
||||
#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F)
|
||||
#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10)
|
||||
#define MPI2_SASSTATUS_DATA_OFFSET_ERROR (0x11)
|
||||
#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED (0x12)
|
||||
#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED (0x13)
|
||||
#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14)
|
||||
|
||||
|
||||
/*
|
||||
* Values for the SAS DeviceInfo field used in SAS Device Status Change Event
|
||||
* data and SAS Configuration pages.
|
||||
*/
|
||||
#define MPI2_SAS_DEVICE_INFO_SEP (0x00004000)
|
||||
#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
|
||||
#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
|
||||
#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
|
||||
#define MPI2_SAS_DEVICE_INFO_SSP_TARGET (0x00000400)
|
||||
#define MPI2_SAS_DEVICE_INFO_STP_TARGET (0x00000200)
|
||||
#define MPI2_SAS_DEVICE_INFO_SMP_TARGET (0x00000100)
|
||||
#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080)
|
||||
#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040)
|
||||
#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020)
|
||||
#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010)
|
||||
#define MPI2_SAS_DEVICE_INFO_SATA_HOST (0x00000008)
|
||||
|
||||
#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007)
|
||||
#define MPI2_SAS_DEVICE_INFO_NO_DEVICE (0x00000000)
|
||||
#define MPI2_SAS_DEVICE_INFO_END_DEVICE (0x00000001)
|
||||
#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002)
|
||||
#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003)
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* SAS Messages
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* SMP Passthrough messages
|
||||
****************************************************************************/
|
||||
|
||||
/* SMP Passthrough Request Message */
|
||||
typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST
|
||||
{
|
||||
U8 PassthroughFlags; /* 0x00 */
|
||||
U8 PhysicalPort; /* 0x01 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 RequestDataLength; /* 0x04 */
|
||||
U8 SGLFlags; /* 0x06 */ /* MPI v2.0 only. Reserved on MPI v2.5. */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved1; /* 0x0A */
|
||||
U32 Reserved2; /* 0x0C */
|
||||
U64 SASAddress; /* 0x10 */
|
||||
U32 Reserved3; /* 0x18 */
|
||||
U32 Reserved4; /* 0x1C */
|
||||
MPI2_SIMPLE_SGE_UNION SGL; /* 0x20 */ /* MPI v2.5: IEEE Simple 64 elements only */
|
||||
} MPI2_SMP_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REQUEST,
|
||||
Mpi2SmpPassthroughRequest_t, MPI2_POINTER pMpi2SmpPassthroughRequest_t;
|
||||
|
||||
/* values for PassthroughFlags field */
|
||||
#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80)
|
||||
|
||||
/* MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
|
||||
|
||||
|
||||
/* SMP Passthrough Reply Message */
|
||||
typedef struct _MPI2_SMP_PASSTHROUGH_REPLY
|
||||
{
|
||||
U8 PassthroughFlags; /* 0x00 */
|
||||
U8 PhysicalPort; /* 0x01 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 ResponseDataLength; /* 0x04 */
|
||||
U8 SGLFlags; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved1; /* 0x0A */
|
||||
U8 Reserved2; /* 0x0C */
|
||||
U8 SASStatus; /* 0x0D */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
U32 Reserved3; /* 0x14 */
|
||||
U8 ResponseData[4]; /* 0x18 */
|
||||
} MPI2_SMP_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REPLY,
|
||||
Mpi2SmpPassthroughReply_t, MPI2_POINTER pMpi2SmpPassthroughReply_t;
|
||||
|
||||
/* values for PassthroughFlags field */
|
||||
#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80)
|
||||
|
||||
/* values for SASStatus field are at the top of this file */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* SATA Passthrough messages
|
||||
****************************************************************************/
|
||||
|
||||
typedef union _MPI2_SATA_PT_SGE_UNION
|
||||
{
|
||||
MPI2_SGE_SIMPLE_UNION MpiSimple; /* MPI v2.0 only */
|
||||
MPI2_SGE_CHAIN_UNION MpiChain; /* MPI v2.0 only */
|
||||
MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
|
||||
MPI2_IEEE_SGE_CHAIN_UNION IeeeChain; /* MPI v2.0 only */
|
||||
MPI25_IEEE_SGE_CHAIN64 IeeeChain64; /* MPI v2.5 only */
|
||||
} MPI2_SATA_PT_SGE_UNION, MPI2_POINTER PTR_MPI2_SATA_PT_SGE_UNION,
|
||||
Mpi2SataPTSGEUnion_t, MPI2_POINTER pMpi2SataPTSGEUnion_t;
|
||||
|
||||
|
||||
/* SATA Passthrough Request Message */
|
||||
typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST
|
||||
{
|
||||
U16 DevHandle; /* 0x00 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 PassthroughFlags; /* 0x04 */
|
||||
U8 SGLFlags; /* 0x06 */ /* MPI v2.0 only. Reserved on MPI v2.5. */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved1; /* 0x0A */
|
||||
U32 Reserved2; /* 0x0C */
|
||||
U32 Reserved3; /* 0x10 */
|
||||
U32 Reserved4; /* 0x14 */
|
||||
U32 DataLength; /* 0x18 */
|
||||
U8 CommandFIS[20]; /* 0x1C */
|
||||
MPI2_SATA_PT_SGE_UNION SGL; /* 0x30 */ /* MPI v2.5: IEEE 64 elements only */
|
||||
} MPI2_SATA_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REQUEST,
|
||||
Mpi2SataPassthroughRequest_t, MPI2_POINTER pMpi2SataPassthroughRequest_t;
|
||||
|
||||
/* values for PassthroughFlags field */
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100)
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_FPDMA (0x0040) /* MPI v2.6 and newer */
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020)
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010)
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004)
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002)
|
||||
#define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001)
|
||||
|
||||
/* MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
|
||||
|
||||
|
||||
/* SATA Passthrough Reply Message */
|
||||
typedef struct _MPI2_SATA_PASSTHROUGH_REPLY
|
||||
{
|
||||
U16 DevHandle; /* 0x00 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 PassthroughFlags; /* 0x04 */
|
||||
U8 SGLFlags; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved1; /* 0x0A */
|
||||
U8 Reserved2; /* 0x0C */
|
||||
U8 SASStatus; /* 0x0D */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
U8 StatusFIS[20]; /* 0x14 */
|
||||
U32 StatusControlRegisters; /* 0x28 */
|
||||
U32 TransferCount; /* 0x2C */
|
||||
} MPI2_SATA_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REPLY,
|
||||
Mpi2SataPassthroughReply_t, MPI2_POINTER pMpi2SataPassthroughReply_t;
|
||||
|
||||
/* values for SASStatus field are at the top of this file */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* SAS IO Unit Control messages
|
||||
* (MPI v2.5 and earlier only.
|
||||
* Replaced by IO Unit Control messages in MPI v2.6 and later.)
|
||||
****************************************************************************/
|
||||
|
||||
/* SAS IO Unit Control Request Message */
|
||||
typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST
|
||||
{
|
||||
U8 Operation; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 DevHandle; /* 0x04 */
|
||||
U8 IOCParameter; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U16 Reserved4; /* 0x0C */
|
||||
U8 PhyNum; /* 0x0E */
|
||||
U8 PrimFlags; /* 0x0F */
|
||||
U32 Primitive; /* 0x10 */
|
||||
U8 LookupMethod; /* 0x14 */
|
||||
U8 Reserved5; /* 0x15 */
|
||||
U16 SlotNumber; /* 0x16 */
|
||||
U64 LookupAddress; /* 0x18 */
|
||||
U32 IOCParameterValue; /* 0x20 */
|
||||
U32 Reserved7; /* 0x24 */
|
||||
U32 Reserved8; /* 0x28 */
|
||||
} MPI2_SAS_IOUNIT_CONTROL_REQUEST,
|
||||
MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST,
|
||||
Mpi2SasIoUnitControlRequest_t, MPI2_POINTER pMpi2SasIoUnitControlRequest_t;
|
||||
|
||||
/* values for the Operation field */
|
||||
#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
|
||||
#define MPI2_SAS_OP_PHY_LINK_RESET (0x06)
|
||||
#define MPI2_SAS_OP_PHY_HARD_RESET (0x07)
|
||||
#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
|
||||
#define MPI2_SAS_OP_SEND_PRIMITIVE (0x0A)
|
||||
#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY (0x0B)
|
||||
#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C) /* MPI v2.0 only */
|
||||
#define MPI2_SAS_OP_REMOVE_DEVICE (0x0D)
|
||||
#define MPI2_SAS_OP_LOOKUP_MAPPING (0x0E)
|
||||
#define MPI2_SAS_OP_SET_IOC_PARAMETER (0x0F)
|
||||
#define MPI25_SAS_OP_ENABLE_FP_DEVICE (0x10)
|
||||
#define MPI25_SAS_OP_DISABLE_FP_DEVICE (0x11)
|
||||
#define MPI25_SAS_OP_ENABLE_FP_ALL (0x12)
|
||||
#define MPI25_SAS_OP_DISABLE_FP_ALL (0x13)
|
||||
#define MPI2_SAS_OP_DEV_ENABLE_NCQ (0x14)
|
||||
#define MPI2_SAS_OP_DEV_DISABLE_NCQ (0x15)
|
||||
#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80)
|
||||
|
||||
/* values for the PrimFlags field */
|
||||
#define MPI2_SAS_PRIMFLAGS_SINGLE (0x08)
|
||||
#define MPI2_SAS_PRIMFLAGS_TRIPLE (0x02)
|
||||
#define MPI2_SAS_PRIMFLAGS_REDUNDANT (0x01)
|
||||
|
||||
/* values for the LookupMethod field */
|
||||
#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS (0x01)
|
||||
#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT (0x02)
|
||||
#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03)
|
||||
|
||||
|
||||
/* SAS IO Unit Control Reply Message */
|
||||
typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY
|
||||
{
|
||||
U8 Operation; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 DevHandle; /* 0x04 */
|
||||
U8 IOCParameter; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U16 Reserved4; /* 0x0C */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
} MPI2_SAS_IOUNIT_CONTROL_REPLY,
|
||||
MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY,
|
||||
Mpi2SasIoUnitControlReply_t, MPI2_POINTER pMpi2SasIoUnitControlReply_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,119 +1,119 @@
|
|||
/*
|
||||
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_type.h
|
||||
* Title: MPI basic type definitions
|
||||
* Creation Date: August 16, 2006
|
||||
*
|
||||
* mpi2_type.h Version: 02.00.01
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
|
||||
* 11-18-14 02.00.01 Updated copyright information.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_TYPE_H
|
||||
#define MPI2_TYPE_H
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Define MPI2_POINTER if it hasn't already been defined. By default
|
||||
* MPI2_POINTER is defined to be a near pointer. MPI2_POINTER can be defined as
|
||||
* a far pointer by defining MPI2_POINTER as "far *" before this header file is
|
||||
* included.
|
||||
*/
|
||||
#ifndef MPI2_POINTER
|
||||
#define MPI2_POINTER *
|
||||
#endif
|
||||
|
||||
#ifdef MPT3SAS_BASE_H_INCLUDED
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Basic Types
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
typedef u8 U8;
|
||||
typedef __le16 U16;
|
||||
typedef __le32 U32;
|
||||
typedef __le64 U64 __attribute__((aligned(4)));
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Pointer Types
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
typedef U8 *PU8;
|
||||
typedef U16 *PU16;
|
||||
typedef U32 *PU32;
|
||||
typedef U64 *PU64;
|
||||
|
||||
#endif
|
||||
|
||||
/* the basic types may have already been included by mpi_type.h */
|
||||
#if !defined(MPI_TYPE_H) && !defined(MPT3SAS_BASE_H_INCLUDED)
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Basic Types
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
typedef signed char S8;
|
||||
typedef unsigned char U8;
|
||||
typedef signed short S16;
|
||||
typedef unsigned short U16;
|
||||
|
||||
|
||||
#if defined(unix) || defined(__arm) || defined(ALPHA) || defined(__PPC__) || defined(__ppc)
|
||||
|
||||
typedef signed int S32;
|
||||
typedef unsigned int U32;
|
||||
|
||||
#else
|
||||
|
||||
typedef signed long S32;
|
||||
typedef unsigned long U32;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct _S64
|
||||
{
|
||||
U32 Low;
|
||||
S32 High;
|
||||
} S64;
|
||||
|
||||
typedef struct _U64
|
||||
{
|
||||
U32 Low;
|
||||
U32 High;
|
||||
} U64;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Pointer Types
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
typedef S8 *PS8;
|
||||
typedef U8 *PU8;
|
||||
typedef S16 *PS16;
|
||||
typedef U16 *PU16;
|
||||
typedef S32 *PS32;
|
||||
typedef U32 *PU32;
|
||||
typedef S64 *PS64;
|
||||
typedef U64 *PU64;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_type.h
|
||||
* Title: MPI basic type definitions
|
||||
* Creation Date: August 16, 2006
|
||||
*
|
||||
* mpi2_type.h Version: 02.00.01
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
|
||||
* 11-18-14 02.00.01 Updated copyright information.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_TYPE_H
|
||||
#define MPI2_TYPE_H
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Define MPI2_POINTER if it hasn't already been defined. By default
|
||||
* MPI2_POINTER is defined to be a near pointer. MPI2_POINTER can be defined as
|
||||
* a far pointer by defining MPI2_POINTER as "far *" before this header file is
|
||||
* included.
|
||||
*/
|
||||
#ifndef MPI2_POINTER
|
||||
#define MPI2_POINTER *
|
||||
#endif
|
||||
|
||||
#ifdef MPT3SAS_BASE_H_INCLUDED
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Basic Types
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
typedef u8 U8;
|
||||
typedef __le16 U16;
|
||||
typedef __le32 U32;
|
||||
typedef __le64 U64 __attribute__((aligned(4)));
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Pointer Types
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
typedef U8 *PU8;
|
||||
typedef U16 *PU16;
|
||||
typedef U32 *PU32;
|
||||
typedef U64 *PU64;
|
||||
|
||||
#endif
|
||||
|
||||
/* the basic types may have already been included by mpi_type.h */
|
||||
#if !defined(MPI_TYPE_H) && !defined(MPT3SAS_BASE_H_INCLUDED)
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Basic Types
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
typedef signed char S8;
|
||||
typedef unsigned char U8;
|
||||
typedef signed short S16;
|
||||
typedef unsigned short U16;
|
||||
|
||||
|
||||
#if defined(unix) || defined(__arm) || defined(ALPHA) || defined(__PPC__) || defined(__ppc)
|
||||
|
||||
typedef signed int S32;
|
||||
typedef unsigned int U32;
|
||||
|
||||
#else
|
||||
|
||||
typedef signed long S32;
|
||||
typedef unsigned long U32;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct _S64
|
||||
{
|
||||
U32 Low;
|
||||
S32 High;
|
||||
} S64;
|
||||
|
||||
typedef struct _U64
|
||||
{
|
||||
U32 Low;
|
||||
U32 High;
|
||||
} U64;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Pointer Types
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
typedef S8 *PS8;
|
||||
typedef U8 *PU8;
|
||||
typedef S16 *PS16;
|
||||
typedef U16 *PU16;
|
||||
typedef S32 *PS32;
|
||||
typedef U32 *PU32;
|
||||
typedef S64 *PS64;
|
||||
typedef U64 *PU64;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -73,13 +73,14 @@
|
|||
#include "mpt3sas_compatibility.h"
|
||||
#include "mpt3sas_debug.h"
|
||||
#include "mpt3sas_trigger_diag.h"
|
||||
#include "mpt3sas_trigger_pages.h"
|
||||
|
||||
/* mpt3sas driver versioning info */
|
||||
#define MPT3SAS_DRIVER_NAME "mpt3sas"
|
||||
#define MPT3SAS_AUTHOR "Broadcom Inc. <MPT-FusionLinux.pdl@broadcom.com>"
|
||||
#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 & SAS 3.5 Device Driver"
|
||||
#define MPT3SAS_DRIVER_VERSION "32.00.00.00"
|
||||
#define MPT3SAS_MAJOR_VERSION 32
|
||||
#define MPT3SAS_DRIVER_VERSION "37.00.00.00"
|
||||
#define MPT3SAS_MAJOR_VERSION 37
|
||||
#define MPT3SAS_MINOR_VERSION 00
|
||||
#define MPT3SAS_BUILD_VERSION 0
|
||||
#define MPT3SAS_RELEASE_VERSION 0
|
||||
|
|
@ -93,6 +94,17 @@
|
|||
#define MPT2SAS_BUILD_VERSION 3
|
||||
#define MPT2SAS_RELEASE_VERSION 0
|
||||
|
||||
/* CoreDump: Default timeout */
|
||||
#define MPT3SAS_DEFAULT_COREDUMP_TIMEOUT_SECONDS (15) /* 15 seconds */
|
||||
#define MPT3SAS_TIMESYNC_TIMEOUT_SECONDS (10) /* 10 seconds */
|
||||
#define MPT3SAS_TIMESYNC_UPDATE_INTERVAL (900) /* 15 minutes */
|
||||
#define MPT3SAS_TIMESYNC_UNIT_MASK (0x80) /* bit 7 */
|
||||
#define MPT3SAS_TIMESYNC_MASK (0x7F) /* 0 - 6 bits */
|
||||
#define SECONDS_PER_MIN (60)
|
||||
#define SECONDS_PER_HOUR (3600)
|
||||
#define MPT3SAS_COREDUMP_LOOP_DONE (0xFF)
|
||||
#define MPI26_SET_IOC_PARAMETER_SYNC_TIMESTAMP (0x81)
|
||||
|
||||
/*
|
||||
* Set MPT3SAS_SG_DEPTH value based on user input.
|
||||
*/
|
||||
|
|
@ -478,6 +490,7 @@ struct read_cap_parameter {
|
|||
#define MPT3SAS_HIGH_IOPS_REPLY_QUEUES 8
|
||||
#define MPT3SAS_HIGH_IOPS_BATCH_COUNT 16
|
||||
#define MPT3SAS_GEN35_MAX_MSIX_QUEUES 128
|
||||
#define RDPQ_MAX_INDEX_IN_ONE_CHUNK 16
|
||||
|
||||
/* Get status code type(bits 27-25) with status code(bits 24-17)
|
||||
* value from status field.
|
||||
|
|
@ -659,7 +672,10 @@ struct Mpi2ManufacturingPage11_t {
|
|||
u8 HostTraceBufferFlags; /* 4Fh */
|
||||
u16 HostTraceBufferMaxSizeKB; /* 50h */
|
||||
u16 HostTraceBufferMinSizeKB; /* 52h */
|
||||
__le32 Reserved10[2]; /* 54h - 5Bh */
|
||||
u8 CoreDumpTOSec; /* 54h */
|
||||
u8 TimeSyncInterval; /* 55h */
|
||||
u16 Reserved9; /* 56h */
|
||||
__le32 Reserved10; /* 58h */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -940,6 +956,7 @@ struct _pcie_device {
|
|||
u8 *serial_number;
|
||||
u8 reset_timeout;
|
||||
u8 access_status;
|
||||
u16 shutdown_latency;
|
||||
struct kref refcount;
|
||||
};
|
||||
|
||||
|
|
@ -1076,6 +1093,7 @@ struct _sas_port {
|
|||
* @handle: device handle for this phy
|
||||
* @attached_handle: device handle for attached device
|
||||
* @phy_belongs_to_port: port has been created for this phy
|
||||
* @hba_vphy: flag to identify HBA vSES device phy
|
||||
* @port: hba port entry
|
||||
*/
|
||||
struct _sas_phy {
|
||||
|
|
@ -1087,6 +1105,7 @@ struct _sas_phy {
|
|||
u16 handle;
|
||||
u16 attached_handle;
|
||||
u8 phy_belongs_to_port;
|
||||
u8 hba_vphy;
|
||||
struct hba_port *port;
|
||||
};
|
||||
|
||||
|
|
@ -1104,6 +1123,7 @@ struct _sas_phy {
|
|||
* @port: hba port entry
|
||||
* @phy: a list of phys that make up this sas_host/expander
|
||||
* @sas_port_list: list of ports attached to this sas_host/expander
|
||||
* @rphy: sas_rphy object of this expander
|
||||
*/
|
||||
struct _sas_node {
|
||||
struct list_head list;
|
||||
|
|
@ -1118,6 +1138,7 @@ struct _sas_node {
|
|||
struct hba_port *port;
|
||||
struct _sas_phy *phy;
|
||||
struct list_head sas_port_list;
|
||||
struct sas_rphy *rphy;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1353,25 +1374,87 @@ struct mpt3sas_port_facts {
|
|||
struct reply_post_struct {
|
||||
Mpi2ReplyDescriptorsUnion_t *reply_post_free;
|
||||
dma_addr_t reply_post_free_dma;
|
||||
struct dma_pool *dma_pool;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct virtual_phy - vSES phy structure
|
||||
* sas_address: SAS Address of vSES device
|
||||
* phy_mask: vSES device's phy number
|
||||
* flags: flags used to manage this structure
|
||||
*/
|
||||
struct virtual_phy {
|
||||
struct list_head list;
|
||||
u64 sas_address;
|
||||
u32 phy_mask;
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
#define MPT_VPHY_FLAG_DIRTY_PHY 0x01
|
||||
|
||||
/**
|
||||
* struct hba_port - Saves each HBA's Wide/Narrow port info
|
||||
* @port_id: port number
|
||||
* @sas_address: sas address of this wide/narrow port's attached device
|
||||
* @phy_mask: HBA PHY's belonging to this port
|
||||
* @flags: hba port flags
|
||||
* @vphys_mask : mask of vSES devices Phy number
|
||||
* @vphys_list : list containing vSES device structures
|
||||
*/
|
||||
struct hba_port {
|
||||
struct list_head list;
|
||||
u8 port_id;
|
||||
u64 sas_address;
|
||||
u32 phy_mask;
|
||||
u8 port_id;
|
||||
u8 flags;
|
||||
u32 vphys_mask;
|
||||
struct list_head vphys_list;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct htb_rel_query - diagnostic buffer release reason
|
||||
* @unique_id - unique id associated with this buffer.
|
||||
* @buffer_rel_condition - Release condition ioctl/sysfs/reset
|
||||
* @reserved
|
||||
* @trigger_type - Master/Event/scsi/MPI
|
||||
* @trigger_info_dwords - Data Correspondig to trigger type
|
||||
*/
|
||||
struct htb_rel_query
|
||||
{
|
||||
u16 buffer_rel_condition;
|
||||
u16 reserved;
|
||||
u32 trigger_type;
|
||||
u32 trigger_info_dwords[2];
|
||||
};
|
||||
|
||||
/* Buffer_rel_condition bit fields */
|
||||
|
||||
/* Bit 0 - Diag Buffer not Released */
|
||||
#define MPT3_DIAG_BUFFER_NOT_RELEASED (0x00)
|
||||
/* Bit 0 - Diag Buffer Released */
|
||||
#define MPT3_DIAG_BUFFER_RELEASED (0x01)
|
||||
|
||||
/*
|
||||
* Bit 1 - Diag Buffer Released by IOCTL,
|
||||
* This bit is valid only if Bit 0 is one
|
||||
*/
|
||||
#define MPT3_DIAG_BUFFER_REL_IOCTL (0x02 | MPT3_DIAG_BUFFER_RELEASED)
|
||||
|
||||
/*
|
||||
* Bit 2 - Diag Buffer Released by Trigger,
|
||||
* This bit is valid only if Bit 0 is one
|
||||
*/
|
||||
#define MPT3_DIAG_BUFFER_REL_TRIGGER (0x04 | MPT3_DIAG_BUFFER_RELEASED)
|
||||
|
||||
/*
|
||||
* Bit 3 - Diag Buffer Released by SysFs,
|
||||
* This bit is valid only if Bit 0 is one
|
||||
*/
|
||||
#define MPT3_DIAG_BUFFER_REL_SYSFS (0x08 | MPT3_DIAG_BUFFER_RELEASED)
|
||||
|
||||
/* DIAG RESET Master trigger flags */
|
||||
#define MPT_DIAG_RESET_ISSUED_BY_DRIVER 0x00000000
|
||||
#define MPT_DIAG_RESET_ISSUED_BY_USER 0x00000001
|
||||
|
||||
/* hba port flags */
|
||||
#define HBA_PORT_FLAG_DIRTY_PORT 0x01
|
||||
#define HBA_PORT_FLAG_NEW_PORT 0x02
|
||||
|
|
@ -1405,6 +1488,8 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
|
|||
* @firmware_event_thread: ""
|
||||
* @fw_event_lock:
|
||||
* @fw_event_list: list of fw events
|
||||
* @current_evet: current processing firmware event
|
||||
* @fw_event_cleanup: set to one while cleaning up the fw events
|
||||
* @aen_event_read_flag: event log was read
|
||||
* @broadcast_aen_busy: broadcast aen waiting to be serviced
|
||||
* @shost_recovery: host reset in progress
|
||||
|
|
@ -1428,10 +1513,13 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
|
|||
* @total_io_cnt: Gives total IO count, used to load balance the interrupts
|
||||
* @high_iops_outstanding: used to load balance the interrupts within high iops reply queues
|
||||
* @high_iops_queues: high iops reply queues count
|
||||
* @drv_internal_flags: Bit map internal to driver
|
||||
* @drv_support_bitmap: driver's supported feature bit map
|
||||
* @msix_load_balance: Enables load balancing of interrupts across the multiple MSIXs
|
||||
* @thresh_hold: Max number of reply descriptors processed before updating Host Index
|
||||
* @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands
|
||||
* @timestamp_update_count: Counter to fire timeSync command
|
||||
* time_sync_interval: Time sync interval read from man page 11
|
||||
* @scsi_io_cb_idx: shost generated commands
|
||||
* @tm_cb_idx: task management commands
|
||||
* @scsih_cb_idx: scsih internal commands
|
||||
|
|
@ -1617,6 +1705,8 @@ struct MPT3SAS_ADAPTER {
|
|||
struct workqueue_struct *firmware_event_thread;
|
||||
spinlock_t fw_event_lock;
|
||||
struct list_head fw_event_list;
|
||||
struct fw_event_work *current_event;
|
||||
u8 fw_events_cleanup;
|
||||
|
||||
/* misc flags */
|
||||
int aen_event_read_flag;
|
||||
|
|
@ -1654,13 +1744,20 @@ struct MPT3SAS_ADAPTER {
|
|||
u32 ioc_reset_count;
|
||||
MPT3SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
|
||||
u32 non_operational_loop;
|
||||
u8 ioc_coredump_loop;
|
||||
u32 timestamp_update_count;
|
||||
u32 time_sync_interval;
|
||||
u8 multipath_on_hba;
|
||||
atomic64_t total_io_cnt;
|
||||
atomic64_t high_iops_outstanding;
|
||||
bool msix_load_balance;
|
||||
u16 thresh_hold;
|
||||
u8 high_iops_queues;
|
||||
u32 drv_internal_flags;
|
||||
u32 drv_support_bitmap;
|
||||
u32 dma_mask;
|
||||
bool enable_sdev_max_qd;
|
||||
bool use_32bit_dma;
|
||||
|
||||
/* internal commands, callback index */
|
||||
u8 scsi_io_cb_idx;
|
||||
|
|
@ -1713,6 +1810,7 @@ struct MPT3SAS_ADAPTER {
|
|||
u8 disable_eedp_support;
|
||||
u8 tm_custom_handling;
|
||||
u8 nvme_abort_timeout;
|
||||
u16 max_shutdown_latency;
|
||||
|
||||
/* static config pages */
|
||||
struct mpt3sas_facts facts;
|
||||
|
|
@ -1846,9 +1944,6 @@ struct MPT3SAS_ADAPTER {
|
|||
u16 reply_post_queue_depth;
|
||||
struct reply_post_struct *reply_post;
|
||||
struct dma_pool *reply_post_free_dma_pool;
|
||||
struct dma_pool *reply_post_free_dma_pool_align;
|
||||
struct dma_pool *reply_post_free_dma_pool_mod_rdpq_set;
|
||||
struct dma_pool *reply_post_free_dma_pool_mod_rdpq_set_align;
|
||||
struct dma_pool *reply_post_free_array_dma_pool;
|
||||
Mpi2IOCInitRDPQArrayEntry *reply_post_free_array;
|
||||
dma_addr_t reply_post_free_array_dma;
|
||||
|
|
@ -1884,6 +1979,8 @@ struct MPT3SAS_ADAPTER {
|
|||
u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
|
||||
u32 ring_buffer_offset;
|
||||
u32 ring_buffer_sz;
|
||||
struct htb_rel_query htb_rel;
|
||||
u8 reset_from_user;
|
||||
#if defined(TARGET_MODE)
|
||||
char stm_name[MPT_NAME_LENGTH];
|
||||
u8 stm_io_cb_idx; /* normal io */
|
||||
|
|
@ -1922,6 +2019,7 @@ struct MPT3SAS_ADAPTER {
|
|||
struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event;
|
||||
struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi;
|
||||
struct SL_WH_MPI_TRIGGERS_T diag_trigger_mpi;
|
||||
u8 supports_trigger_pages;
|
||||
void *device_remove_in_progress;
|
||||
u16 device_remove_in_progress_sz;
|
||||
u8 *tm_tr_retry;
|
||||
|
|
@ -1929,10 +2027,22 @@ struct MPT3SAS_ADAPTER {
|
|||
u8 temp_sensors_count;
|
||||
u8 is_gen35_ioc;
|
||||
u8 is_aero_ioc;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs_root;
|
||||
struct dentry *ioc_dump;
|
||||
#endif
|
||||
struct list_head port_table_list;
|
||||
};
|
||||
|
||||
#define MPT_DRV_SUPPORT_BITMAP_MEMMOVE 0x00000001
|
||||
struct mpt3sas_debugfs_buffer {
|
||||
void *buf;
|
||||
u32 len;
|
||||
};
|
||||
|
||||
#define MPT_DRV_SUPPORT_BITMAP_MEMMOVE 0x00000001
|
||||
#define MPT_DRV_SUPPORT_BITMAP_ADDNLQUERY 0x00000002
|
||||
|
||||
#define MPT_DRV_INTERNAL_BITMAP_BLK_MQ 0x00000001
|
||||
|
||||
typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
|
||||
u32 reply);
|
||||
|
|
@ -1983,7 +2093,7 @@ __le64 mpt3sas_base_get_sense_buffer_dma_64(struct MPT3SAS_ADAPTER *ioc,
|
|||
u16 smid);
|
||||
void *mpt3sas_base_get_pcie_sgl(struct MPT3SAS_ADAPTER *ioc, u16 smid);
|
||||
dma_addr_t mpt3sas_base_get_pcie_sgl_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid);
|
||||
void mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc);
|
||||
void mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc, u8 poll);
|
||||
|
||||
/* hi-priority queue */
|
||||
u16 mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx);
|
||||
|
|
@ -2007,6 +2117,13 @@ u32 mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked);
|
|||
int _base_check_and_get_msix_vectors(struct pci_dev *pdev);
|
||||
|
||||
void mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code);
|
||||
#define mpt3sas_print_fault_code(ioc, fault_code) \
|
||||
printk(MPT3SAS_ERR_FMT "fault info from func: %s\n", ioc->name, __func__); \
|
||||
mpt3sas_base_fault_info (ioc, fault_code)
|
||||
|
||||
void mpt3sas_base_coredump_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code);
|
||||
int mpt3sas_base_wait_for_coredump_completion(struct MPT3SAS_ADAPTER *ioc,
|
||||
const char *caller);
|
||||
int mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2SasIoUnitControlReply_t *mpi_reply,
|
||||
Mpi2SasIoUnitControlRequest_t *mpi_request);
|
||||
|
|
@ -2038,7 +2155,9 @@ void mpt3sas_base_disable_msix(struct MPT3SAS_ADAPTER *ioc);
|
|||
void mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc);
|
||||
u8 mpt3sas_base_check_cmd_timeout(struct MPT3SAS_ADAPTER *ioc,
|
||||
u8 status, void *mpi_request, int sz);
|
||||
|
||||
#define mpt3sas_check_cmd_timeout(ioc, status, mpi_request, sz, issue_reset) \
|
||||
printk(MPT3SAS_ERR_FMT "In func: %s\n", ioc->name, __func__); \
|
||||
issue_reset = mpt3sas_base_check_cmd_timeout(ioc, status, mpi_request, sz)
|
||||
|
||||
int mpt3sas_wait_for_ioc_to_operational(struct MPT3SAS_ADAPTER *ioc,
|
||||
int wait_count);
|
||||
|
|
@ -2046,6 +2165,7 @@ void mpt3sas_base_start_hba_unplug_watchdog(struct MPT3SAS_ADAPTER *ioc);
|
|||
void mpt3sas_base_stop_hba_unplug_watchdog(struct MPT3SAS_ADAPTER *ioc);
|
||||
int mpt3sas_base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, enum reset_type type);
|
||||
void mpt3sas_base_mask_interrupts(struct MPT3SAS_ADAPTER *ioc);
|
||||
void mpt3sas_base_unmask_interrupts(struct MPT3SAS_ADAPTER *ioc);
|
||||
|
||||
/* scsih shared API */
|
||||
extern char driver_name[MPT_NAME_LENGTH];
|
||||
|
|
@ -2070,7 +2190,9 @@ void mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
|
|||
u8 mpt3sas_check_for_pending_internal_cmds(struct MPT3SAS_ADAPTER *ioc,
|
||||
u16 smid);
|
||||
struct hba_port *
|
||||
mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port);
|
||||
mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port, u8 skip_dirty_flag);
|
||||
struct virtual_phy *
|
||||
mpt3sas_get_vphy_by_phy(struct MPT3SAS_ADAPTER *ioc, struct hba_port *port, u32 phy);
|
||||
|
||||
struct _sas_node *mpt3sas_scsih_expander_find_by_handle(
|
||||
struct MPT3SAS_ADAPTER *ioc, u16 handle);
|
||||
|
|
@ -2098,6 +2220,8 @@ _scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc,
|
|||
void
|
||||
mpt3sas_scsih_clear_outstanding_scsi_tm_commands(struct MPT3SAS_ADAPTER *ioc);
|
||||
u32 base_mod64(u64 dividend, u32 divisor);
|
||||
void
|
||||
mpt3sas_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
|
||||
|
||||
/**
|
||||
* _scsih_is_pcie_scsi_device - determines if device is an pcie scsi device
|
||||
|
|
@ -2214,6 +2338,33 @@ int mpt3sas_config_get_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
|
|||
int
|
||||
mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz);
|
||||
int
|
||||
mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page);
|
||||
int
|
||||
mpt3sas_config_get_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page);
|
||||
int
|
||||
mpt3sas_config_get_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page);
|
||||
int
|
||||
mpt3sas_config_get_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page);
|
||||
int
|
||||
mpt3sas_config_get_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page);
|
||||
int
|
||||
mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set);
|
||||
int
|
||||
mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct SL_WH_EVENT_TRIGGERS_T *event_tg, bool set);
|
||||
int
|
||||
mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct SL_WH_SCSI_TRIGGERS_T *scsi_tg, bool set);
|
||||
int
|
||||
mpt3sas_config_update_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct SL_WH_MPI_TRIGGERS_T *mpi_tg, bool set);
|
||||
|
||||
/* ctl shared API */
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25))
|
||||
|
|
@ -2311,6 +2462,11 @@ mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
|
|||
|
||||
void _scsih_hide_unhide_sas_devices(struct MPT3SAS_ADAPTER *ioc);
|
||||
|
||||
void mpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER *ioc);
|
||||
void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc);
|
||||
void mpt3sas_init_debugfs(void);
|
||||
void mpt3sas_exit_debugfs(void);
|
||||
|
||||
#ifdef MPT2SAS_WD_DDIOCOUNT
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25))
|
||||
ssize_t
|
||||
|
|
|
|||
|
|
@ -103,9 +103,6 @@ _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
|||
Mpi2ConfigRequest_t *mpi_request;
|
||||
char *desc = NULL;
|
||||
|
||||
if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
|
||||
return;
|
||||
|
||||
mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
|
||||
switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
|
||||
case MPI2_CONFIG_PAGETYPE_IO_UNIT:
|
||||
|
|
@ -273,7 +270,8 @@ mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
|
|||
mpi_reply->MsgLength*4);
|
||||
}
|
||||
ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
|
||||
_config_display_some_debug(ioc, smid, "config_done", mpi_reply);
|
||||
if (ioc->logging_level & MPT_DEBUG_CONFIG)
|
||||
_config_display_some_debug(ioc, smid, "config_done", mpi_reply);
|
||||
ioc->config_cmds.smid = USHORT_MAX;
|
||||
complete(&ioc->config_cmds.done);
|
||||
return 1;
|
||||
|
|
@ -309,6 +307,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
|
|||
u8 retry_count, issue_host_reset = 0;
|
||||
struct config_request mem;
|
||||
u32 ioc_status = UINT_MAX;
|
||||
u8 issue_reset;
|
||||
|
||||
mutex_lock(&ioc->config_cmds.mutex);
|
||||
if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
|
||||
|
|
@ -381,19 +380,24 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
|
|||
|
||||
r = 0;
|
||||
memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
|
||||
memset(ioc->config_cmds.reply, 0, sizeof(Mpi2ConfigReply_t));
|
||||
ioc->config_cmds.status = MPT3_CMD_PENDING;
|
||||
config_request = mpt3sas_base_get_msg_frame(ioc, smid);
|
||||
ioc->config_cmds.smid = smid;
|
||||
memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
|
||||
_config_display_some_debug(ioc, smid, "config_request", NULL);
|
||||
if (ioc->logging_level & MPT_DEBUG_CONFIG)
|
||||
_config_display_some_debug(ioc, smid, "config_request", NULL);
|
||||
init_completion(&ioc->config_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->config_cmds.done,
|
||||
timeout*HZ);
|
||||
if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
mpt3sas_base_check_cmd_timeout(ioc,
|
||||
if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
|
||||
_config_display_some_debug(ioc, smid,
|
||||
"config_request no reply", NULL);
|
||||
mpt3sas_check_cmd_timeout(ioc,
|
||||
ioc->config_cmds.status, mpi_request,
|
||||
sizeof(Mpi2ConfigRequest_t)/4);
|
||||
sizeof(Mpi2ConfigRequest_t)/4, issue_reset);
|
||||
retry_count++;
|
||||
if (ioc->config_cmds.smid == smid)
|
||||
mpt3sas_base_free_smid(ioc, smid);
|
||||
|
|
@ -413,8 +417,11 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
|
|||
/* Reply Frame Sanity Checks to workaround FW issues */
|
||||
if ((mpi_request->Header.PageType & 0xF) !=
|
||||
(mpi_reply->Header.PageType & 0xF)) {
|
||||
if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
|
||||
_config_display_some_debug(ioc, smid,
|
||||
"config_request", NULL);
|
||||
_debug_dump_mf(mpi_request, ioc->request_sz/4);
|
||||
_debug_dump_reply(mpi_reply, ioc->request_sz/4);
|
||||
_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
|
||||
panic(MPT3SAS_WARN_FMT "%s: Firmware BUG:"
|
||||
" mpi_reply mismatch: Requested PageType(0x%02x)"
|
||||
" Reply PageType(0x%02x)\n",
|
||||
|
|
@ -426,8 +433,11 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
|
|||
if (((mpi_request->Header.PageType & 0xF) ==
|
||||
MPI2_CONFIG_PAGETYPE_EXTENDED) &&
|
||||
mpi_request->ExtPageType != mpi_reply->ExtPageType) {
|
||||
if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
|
||||
_config_display_some_debug(ioc, smid,
|
||||
"config_request", NULL);
|
||||
_debug_dump_mf(mpi_request, ioc->request_sz/4);
|
||||
_debug_dump_reply(mpi_reply, ioc->request_sz/4);
|
||||
_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
|
||||
panic(MPT3SAS_WARN_FMT "%s: Firmware BUG:"
|
||||
" mpi_reply mismatch: Requested ExtPageType(0x%02x)"
|
||||
" Reply ExtPageType(0x%02x)\n",
|
||||
|
|
@ -451,8 +461,11 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
|
|||
if (p) {
|
||||
if ((mpi_request->Header.PageType & 0xF) !=
|
||||
(p[3] & 0xF)) {
|
||||
if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
|
||||
_config_display_some_debug(ioc, smid,
|
||||
"config_request", NULL);
|
||||
_debug_dump_mf(mpi_request, ioc->request_sz/4);
|
||||
_debug_dump_reply(mpi_reply, ioc->request_sz/4);
|
||||
_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
|
||||
_debug_dump_config(p, min_t(u16, mem.sz,
|
||||
config_page_sz)/4);
|
||||
panic(MPT3SAS_WARN_FMT "%s: Firmware BUG:"
|
||||
|
|
@ -467,8 +480,11 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
|
|||
if (((mpi_request->Header.PageType & 0xF) ==
|
||||
MPI2_CONFIG_PAGETYPE_EXTENDED) &&
|
||||
(mpi_request->ExtPageType != p[6])) {
|
||||
if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
|
||||
_config_display_some_debug(ioc, smid,
|
||||
"config_request", NULL);
|
||||
_debug_dump_mf(mpi_request, ioc->request_sz/4);
|
||||
_debug_dump_reply(mpi_reply, ioc->request_sz/4);
|
||||
_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
|
||||
_debug_dump_config(p, min_t(u16, mem.sz,
|
||||
config_page_sz)/4);
|
||||
panic(MPT3SAS_WARN_FMT "%s: Firmware BUG:"
|
||||
|
|
@ -1753,6 +1769,766 @@ mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
|
|||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_get_driver_trigger_pg0 - obtain driver trigger page 0
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
|
||||
{
|
||||
Mpi2ConfigRequest_t mpi_request;
|
||||
int r;
|
||||
|
||||
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
|
||||
mpi_request.Function = MPI2_FUNCTION_CONFIG;
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
mpi_request.ExtPageType =
|
||||
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
|
||||
mpi_request.Header.PageNumber = 0;
|
||||
mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
|
||||
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_set_driver_trigger_pg0 - write driver trigger page 0
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_config_set_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
|
||||
{
|
||||
Mpi2ConfigRequest_t mpi_request;
|
||||
int r;
|
||||
|
||||
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
|
||||
mpi_request.Function = MPI2_FUNCTION_CONFIG;
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
mpi_request.ExtPageType =
|
||||
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
|
||||
mpi_request.Header.PageNumber = 0;
|
||||
mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
|
||||
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
|
||||
_config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_update_driver_trigger_pg0 - update driver trigger page 0
|
||||
* @ioc: per adapter object
|
||||
* @trigger_flags: trigger type bit map
|
||||
* @set: set ot clear trigger values
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_update_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
|
||||
u16 trigger_flag, bool set)
|
||||
{
|
||||
Mpi26DriverTriggerPage0_t tg_pg0;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
int rc;
|
||||
u16 flags, ioc_status;
|
||||
|
||||
rc = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
|
||||
if (rc)
|
||||
return rc;
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
dcprintk(ioc,
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%s: Failed to get trigger pg0, ioc_status(0x%04x)\n",
|
||||
ioc->name, __func__, ioc_status));
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (set)
|
||||
flags = le16_to_cpu(tg_pg0.TriggerFlags) | trigger_flag;
|
||||
else
|
||||
flags = le16_to_cpu(tg_pg0.TriggerFlags) & ~trigger_flag;
|
||||
|
||||
tg_pg0.TriggerFlags = cpu_to_le16(flags);
|
||||
|
||||
rc = _config_set_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
|
||||
if (rc)
|
||||
return rc;
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
dcprintk(ioc,
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%s: Failed to update trigger pg0, ioc_status(0x%04x)\n",
|
||||
ioc->name, __func__, ioc_status));
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_get_driver_trigger_pg1 - obtain driver trigger page 1
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_get_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
|
||||
{
|
||||
Mpi2ConfigRequest_t mpi_request;
|
||||
int r;
|
||||
|
||||
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
|
||||
mpi_request.Function = MPI2_FUNCTION_CONFIG;
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
mpi_request.ExtPageType =
|
||||
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
|
||||
mpi_request.Header.PageNumber = 1;
|
||||
mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
|
||||
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_set_driver_trigger_pg1 - write driver trigger page 1
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_config_set_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
|
||||
{
|
||||
Mpi2ConfigRequest_t mpi_request;
|
||||
int r;
|
||||
|
||||
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
|
||||
mpi_request.Function = MPI2_FUNCTION_CONFIG;
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
mpi_request.ExtPageType =
|
||||
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
|
||||
mpi_request.Header.PageNumber = 1;
|
||||
mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
|
||||
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
|
||||
_config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_update_driver_trigger_pg1 - update driver trigger page 1
|
||||
* @ioc: per adapter object
|
||||
* @master_tg: Master trigger bit map
|
||||
* @set: set ot clear trigger values
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set)
|
||||
{
|
||||
Mpi26DriverTriggerPage1_t tg_pg1;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
int rc;
|
||||
u16 ioc_status;
|
||||
|
||||
rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
|
||||
MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, set);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
dcprintk(ioc,
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
|
||||
ioc->name, __func__, ioc_status));
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (set) {
|
||||
tg_pg1.NumMasterTrigger = cpu_to_le16(1);
|
||||
tg_pg1.MasterTriggers[0].MasterTriggerFlags = cpu_to_le32(
|
||||
master_tg->MasterData);
|
||||
} else {
|
||||
tg_pg1.NumMasterTrigger = 0;
|
||||
tg_pg1.MasterTriggers[0].MasterTriggerFlags = 0;
|
||||
}
|
||||
|
||||
rc = _config_set_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
dcprintk(ioc,
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
|
||||
ioc->name, __func__, ioc_status));
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
mpt3sas_config_update_driver_trigger_pg0(ioc,
|
||||
MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, !set);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_get_driver_trigger_pg2 - obtain driver trigger page 2
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_get_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
|
||||
{
|
||||
Mpi2ConfigRequest_t mpi_request;
|
||||
int r;
|
||||
|
||||
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
|
||||
mpi_request.Function = MPI2_FUNCTION_CONFIG;
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
mpi_request.ExtPageType =
|
||||
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
|
||||
mpi_request.Header.PageNumber = 2;
|
||||
mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
|
||||
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_set_driver_trigger_pg2 - write driver trigger page 2
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_config_set_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
|
||||
{
|
||||
Mpi2ConfigRequest_t mpi_request;
|
||||
int r;
|
||||
|
||||
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
|
||||
mpi_request.Function = MPI2_FUNCTION_CONFIG;
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
mpi_request.ExtPageType =
|
||||
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
|
||||
mpi_request.Header.PageNumber = 2;
|
||||
mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
|
||||
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
|
||||
_config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_update_driver_trigger_pg2 - update driver trigger page 2
|
||||
* @ioc: per adapter object
|
||||
* @event_tg: list of Event Triggers
|
||||
* @set: set ot clear trigger values
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct SL_WH_EVENT_TRIGGERS_T *event_tg, bool set)
|
||||
{
|
||||
Mpi26DriverTriggerPage2_t tg_pg2;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
int rc, i, count;
|
||||
u16 ioc_status;
|
||||
|
||||
rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
|
||||
MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, set);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = mpt3sas_config_get_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
dcprintk(ioc,
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
|
||||
ioc->name, __func__, ioc_status));
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (set) {
|
||||
count = event_tg->ValidEntries;
|
||||
tg_pg2.NumMPIEventTrigger = cpu_to_le16(count);
|
||||
for (i = 0; i < count; i++) {
|
||||
tg_pg2.MPIEventTriggers[i].MPIEventCode =
|
||||
cpu_to_le16(
|
||||
event_tg->EventTriggerEntry[i].EventValue);
|
||||
tg_pg2.MPIEventTriggers[i].MPIEventCodeSpecific =
|
||||
cpu_to_le16(
|
||||
event_tg->EventTriggerEntry[i].LogEntryQualifier);
|
||||
}
|
||||
} else {
|
||||
tg_pg2.NumMPIEventTrigger = 0;
|
||||
memset(&tg_pg2.MPIEventTriggers[0], 0,
|
||||
NUM_VALID_ENTRIES * sizeof(
|
||||
MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY));
|
||||
}
|
||||
|
||||
rc = _config_set_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
dcprintk(ioc,
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
|
||||
ioc->name, __func__, ioc_status));
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
mpt3sas_config_update_driver_trigger_pg0(ioc,
|
||||
MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, !set);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_get_driver_trigger_pg3 - obtain driver trigger page 3
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_get_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
|
||||
{
|
||||
Mpi2ConfigRequest_t mpi_request;
|
||||
int r;
|
||||
|
||||
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
|
||||
mpi_request.Function = MPI2_FUNCTION_CONFIG;
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
mpi_request.ExtPageType =
|
||||
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
|
||||
mpi_request.Header.PageNumber = 3;
|
||||
mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
|
||||
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_set_driver_trigger_pg3 - write driver trigger page 3
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_config_set_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
|
||||
{
|
||||
Mpi2ConfigRequest_t mpi_request;
|
||||
int r;
|
||||
|
||||
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
|
||||
mpi_request.Function = MPI2_FUNCTION_CONFIG;
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
mpi_request.ExtPageType =
|
||||
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
|
||||
mpi_request.Header.PageNumber = 3;
|
||||
mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
|
||||
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
|
||||
_config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_update_driver_trigger_pg3 - update driver trigger page 3
|
||||
* @ioc: per adapter object
|
||||
* @scsi_tg: scsi trigger list
|
||||
* @set: set ot clear trigger values
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct SL_WH_SCSI_TRIGGERS_T *scsi_tg, bool set)
|
||||
{
|
||||
Mpi26DriverTriggerPage3_t tg_pg3;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
int rc, i, count;
|
||||
u16 ioc_status;
|
||||
|
||||
rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
|
||||
MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, set);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = mpt3sas_config_get_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
dcprintk(ioc,
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
|
||||
ioc->name, __func__, ioc_status));
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (set) {
|
||||
count = scsi_tg->ValidEntries;
|
||||
tg_pg3.NumSCSISenseTrigger = cpu_to_le16(count);
|
||||
for (i = 0; i < count; i++) {
|
||||
tg_pg3.SCSISenseTriggers[i].ASCQ =
|
||||
scsi_tg->SCSITriggerEntry[i].ASCQ;
|
||||
tg_pg3.SCSISenseTriggers[i].ASC =
|
||||
scsi_tg->SCSITriggerEntry[i].ASC;
|
||||
tg_pg3.SCSISenseTriggers[i].SenseKey =
|
||||
scsi_tg->SCSITriggerEntry[i].SenseKey;
|
||||
}
|
||||
} else {
|
||||
tg_pg3.NumSCSISenseTrigger = 0;
|
||||
memset(&tg_pg3.SCSISenseTriggers[0], 0,
|
||||
NUM_VALID_ENTRIES * sizeof(
|
||||
MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY));
|
||||
}
|
||||
|
||||
rc = _config_set_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
dcprintk(ioc,
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
|
||||
ioc->name, __func__, ioc_status));
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
mpt3sas_config_update_driver_trigger_pg0(ioc,
|
||||
MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, !set);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_get_driver_trigger_pg4 - obtain driver trigger page 4
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_get_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
|
||||
{
|
||||
Mpi2ConfigRequest_t mpi_request;
|
||||
int r;
|
||||
|
||||
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
|
||||
mpi_request.Function = MPI2_FUNCTION_CONFIG;
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
mpi_request.ExtPageType =
|
||||
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
|
||||
mpi_request.Header.PageNumber = 4;
|
||||
mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
|
||||
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_set_driver_trigger_pg4 - write driver trigger page 4
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_config_set_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
|
||||
{
|
||||
Mpi2ConfigRequest_t mpi_request;
|
||||
int r;
|
||||
|
||||
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
|
||||
mpi_request.Function = MPI2_FUNCTION_CONFIG;
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
mpi_request.ExtPageType =
|
||||
MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
|
||||
mpi_request.Header.PageNumber = 4;
|
||||
mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
|
||||
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
|
||||
_config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
|
||||
sizeof(*config_page));
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_update_driver_trigger_pg4 - update driver trigger page 4
|
||||
* @ioc: per adapter object
|
||||
* @mpi_tg: mpi trigger list
|
||||
* @set: set ot clear trigger values
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_update_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct SL_WH_MPI_TRIGGERS_T *mpi_tg, bool set)
|
||||
{
|
||||
Mpi26DriverTriggerPage4_t tg_pg4;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
int rc, i, count;
|
||||
u16 ioc_status;
|
||||
|
||||
rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
|
||||
MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, set);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = mpt3sas_config_get_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
dcprintk(ioc,
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
|
||||
ioc->name, __func__, ioc_status));
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (set) {
|
||||
count = mpi_tg->ValidEntries;
|
||||
tg_pg4.NumIOCStatusLogInfoTrigger = cpu_to_le16(count);
|
||||
for (i = 0; i < count; i++) {
|
||||
tg_pg4.IOCStatusLoginfoTriggers[i].IOCStatus =
|
||||
cpu_to_le16(mpi_tg->MPITriggerEntry[i].IOCStatus);
|
||||
tg_pg4.IOCStatusLoginfoTriggers[i].LogInfo =
|
||||
cpu_to_le32(mpi_tg->MPITriggerEntry[i].IocLogInfo);
|
||||
}
|
||||
} else {
|
||||
tg_pg4.NumIOCStatusLogInfoTrigger = 0;
|
||||
memset(&tg_pg4.IOCStatusLoginfoTriggers[0], 0,
|
||||
NUM_VALID_ENTRIES * sizeof(
|
||||
MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY));
|
||||
}
|
||||
|
||||
rc = _config_set_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK;
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
dcprintk(ioc,
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
|
||||
ioc->name, __func__, ioc_status));
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
mpt3sas_config_update_driver_trigger_pg0(ioc,
|
||||
MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, !set);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_get_volume_handle - returns volume handle for give hidden
|
||||
* raid components
|
||||
|
|
|
|||
|
|
@ -218,6 +218,12 @@ _ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
|||
case MPI2_FUNCTION_SMP_PASSTHROUGH:
|
||||
desc = "smp_passthrough";
|
||||
break;
|
||||
case MPI2_FUNCTION_TOOLBOX:
|
||||
desc = "toolbox";
|
||||
break;
|
||||
case MPI2_FUNCTION_NVME_ENCAPSULATED:
|
||||
desc = "nvme_encapsulated";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!desc)
|
||||
|
|
@ -535,6 +541,8 @@ mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
|
|||
/* add a log message to indicate the release */
|
||||
printk(MPT3SAS_INFO_FMT "%s: Releasing the trace buffer "
|
||||
"due to adapter reset.", ioc->name, __func__);
|
||||
ioc->htb_rel.buffer_rel_condition =
|
||||
MPT3_DIAG_BUFFER_REL_TRIGGER;
|
||||
mpt3sas_send_diag_release(ioc, i, &issue_reset);
|
||||
}
|
||||
break;
|
||||
|
|
@ -960,7 +968,8 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|||
u8 *data;
|
||||
|
||||
/* ioc determines which port to use */
|
||||
smp_request->PhysicalPort = 0xFF;
|
||||
if (!ioc->multipath_on_hba)
|
||||
smp_request->PhysicalPort = 0xFF;
|
||||
if (smp_request->PassthroughFlags &
|
||||
MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE)
|
||||
data = (u8 *)&smp_request->SGL;
|
||||
|
|
@ -1063,6 +1072,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|||
}
|
||||
/* drop to default case for posting the request */
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
|
||||
data_in_dma, data_in_sz);
|
||||
|
|
@ -1088,10 +1098,9 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|||
ioc->ignore_loginfos = 0;
|
||||
}
|
||||
if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
issue_reset =
|
||||
mpt3sas_base_check_cmd_timeout(ioc,
|
||||
ioc->ctl_cmds.status, mpi_request,
|
||||
karg.data_sge_offset);
|
||||
mpt3sas_check_cmd_timeout(ioc,
|
||||
ioc->ctl_cmds.status, mpi_request,
|
||||
karg.data_sge_offset, issue_reset);
|
||||
goto issue_host_reset;
|
||||
}
|
||||
|
||||
|
|
@ -1174,13 +1183,13 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|||
(!(mpt3sas_scsih_is_pcie_scsi_device(pcie_device->device_info))))
|
||||
mpt3sas_scsih_issue_locked_tm(ioc,
|
||||
le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
|
||||
0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
|
||||
0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, smid,
|
||||
pcie_device->reset_timeout,
|
||||
MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE);
|
||||
else
|
||||
mpt3sas_scsih_issue_locked_tm(ioc,
|
||||
le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
|
||||
0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30,
|
||||
0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, smid, 30,
|
||||
MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET);
|
||||
} else
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
|
|
@ -1398,11 +1407,12 @@ _ctl_do_reset(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
|||
|
||||
dctlprintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter\n", ioc->name,
|
||||
__func__));
|
||||
|
||||
|
||||
ioc->reset_from_user = 1;
|
||||
scsi_block_requests(ioc->shost);
|
||||
retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
scsi_unblock_requests(ioc->shost);
|
||||
printk(MPT3SAS_INFO_FMT "host reset: %s\n",
|
||||
printk(MPT3SAS_INFO_FMT "ioctl: host reset: %s\n",
|
||||
ioc->name, ((!retval) ? "SUCCESS" : "FAILED"));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1785,6 +1795,9 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
|
|||
request_data = ioc->diag_buffer[buffer_type];
|
||||
request_data_sz = diag_register->requested_buffer_size;
|
||||
ioc->unique_id[buffer_type] = diag_register->unique_id;
|
||||
/* Reset ioc variables used for additional query commands */
|
||||
ioc->reset_from_user = 0;
|
||||
memset(&ioc->htb_rel, 0, sizeof(struct htb_rel_query));
|
||||
ioc->diag_buffer_status[buffer_type] &= MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
|
||||
memcpy(ioc->product_specific[buffer_type],
|
||||
diag_register->product_specific, MPT3_PRODUCT_SPECIFIC_DWORDS);
|
||||
|
|
@ -1841,10 +1854,9 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
|
|||
MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
|
||||
|
||||
if (!(ioc->ctl_diag_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
issue_reset =
|
||||
mpt3sas_base_check_cmd_timeout(ioc,
|
||||
ioc->ctl_diag_cmds.status, mpi_request,
|
||||
sizeof(Mpi2DiagBufferPostRequest_t)/4);
|
||||
mpt3sas_check_cmd_timeout(ioc,
|
||||
ioc->ctl_diag_cmds.status, mpi_request,
|
||||
sizeof(Mpi2DiagBufferPostRequest_t)/4, issue_reset);
|
||||
goto issue_host_reset;
|
||||
}
|
||||
|
||||
|
|
@ -1912,8 +1924,6 @@ mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, u8 bits_to_register)
|
|||
|
||||
printk(MPT3SAS_INFO_FMT "registering trace buffer support\n",
|
||||
ioc->name);
|
||||
ioc->diag_trigger_master.MasterData =
|
||||
(MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
|
||||
diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
|
||||
diag_register.unique_id =
|
||||
(ioc->hba_mpi_version_belonged == MPI2_VERSION)?
|
||||
|
|
@ -2230,6 +2240,7 @@ mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
|
|||
u16 ioc_status;
|
||||
u32 ioc_state;
|
||||
int rc;
|
||||
u8 reset_needed = 0;
|
||||
|
||||
dctlprintk(ioc, printk(MPT3SAS_INFO_FMT "%s\n", ioc->name,
|
||||
__func__));
|
||||
|
|
@ -2281,9 +2292,10 @@ mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
|
|||
MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
|
||||
|
||||
if (!(ioc->ctl_diag_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
*issue_reset = mpt3sas_base_check_cmd_timeout(ioc,
|
||||
ioc->ctl_diag_cmds.status, mpi_request,
|
||||
sizeof(Mpi2DiagReleaseRequest_t)/4);
|
||||
mpt3sas_check_cmd_timeout(ioc,
|
||||
ioc->ctl_diag_cmds.status, mpi_request,
|
||||
sizeof(Mpi2DiagReleaseRequest_t)/4, reset_needed);
|
||||
*issue_reset = reset_needed;
|
||||
ioc->diag_buffer_status[buffer_type] |=
|
||||
MPT3_DIAG_BUFFER_IS_RELEASED;
|
||||
rc = -EFAULT;
|
||||
|
|
@ -2399,8 +2411,9 @@ _ctl_diag_release(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ioc->htb_rel.buffer_rel_condition = MPT3_DIAG_BUFFER_REL_IOCTL;
|
||||
rc = mpt3sas_send_diag_release(ioc, buffer_type, &issue_reset);
|
||||
|
||||
|
||||
if (issue_reset)
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
|
||||
|
|
@ -2555,10 +2568,9 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
|||
MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
|
||||
|
||||
if (!(ioc->ctl_diag_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
issue_reset =
|
||||
mpt3sas_base_check_cmd_timeout(ioc,
|
||||
ioc->ctl_diag_cmds.status, mpi_request,
|
||||
sizeof(Mpi2DiagBufferPostRequest_t)/4);
|
||||
mpt3sas_check_cmd_timeout(ioc,
|
||||
ioc->ctl_diag_cmds.status, mpi_request,
|
||||
sizeof(Mpi2DiagBufferPostRequest_t)/4, issue_reset);
|
||||
goto issue_host_reset;
|
||||
}
|
||||
|
||||
|
|
@ -2598,6 +2610,62 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* _ctl_addnl_diag_query - query relevant info associated with diag buffers
|
||||
* @ioc: per adapter object
|
||||
* @arg - user space buffer containing ioctl content
|
||||
*
|
||||
* The application will send only unique_id. Driver will
|
||||
* inspect unique_id first, if valid, fill the details related to cause
|
||||
* for diag buffer release.
|
||||
*/
|
||||
static long
|
||||
_ctl_addnl_diag_query(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
||||
{
|
||||
struct mpt3_addnl_diag_query karg;
|
||||
u32 buffer_type = 0;
|
||||
|
||||
if (copy_from_user(&karg, arg, sizeof(karg))) {
|
||||
pr_err("%s: failure at %s:%d/%s()!\n",
|
||||
ioc->name, __FILE__, __LINE__, __func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
dctlprintk(ioc, printk(MPT3SAS_INFO_FMT "%s\n", ioc->name,
|
||||
__func__));
|
||||
if (karg.unique_id == 0) {
|
||||
pr_err("%s: %s: unique_id is(0x%08x) \n",
|
||||
ioc->name, __func__, karg.unique_id);
|
||||
return -EPERM;
|
||||
}
|
||||
buffer_type = _ctl_diag_get_bufftype(ioc, karg.unique_id);
|
||||
if (buffer_type == MPT3_DIAG_UID_NOT_FOUND) {
|
||||
pr_err("%s: %s: buffer with unique_id(0x%08x) not found\n",
|
||||
ioc->name, __func__, karg.unique_id);
|
||||
return -EPERM;
|
||||
}
|
||||
memset(&karg.buffer_rel_condition, 0, sizeof(struct htb_rel_query));
|
||||
if ((ioc->diag_buffer_status[buffer_type] &
|
||||
MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
|
||||
pr_info("%s: %s: buffer_type(0x%02x) is not registered\n",
|
||||
ioc->name, __func__, buffer_type);
|
||||
goto out;
|
||||
}
|
||||
if ((ioc->diag_buffer_status[buffer_type] &
|
||||
MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
|
||||
pr_err("%s: %s: buffer_type(0x%02x) is not released\n",
|
||||
ioc->name, __func__, buffer_type);
|
||||
return -EPERM;
|
||||
}
|
||||
memcpy(&karg.buffer_rel_condition, &ioc->htb_rel,
|
||||
sizeof(struct htb_rel_query));
|
||||
out:
|
||||
if (copy_to_user(arg, &karg, sizeof(struct mpt3_addnl_diag_query))) {
|
||||
pr_err("%s: %s: unable to write mpt3_addnl_diag_query data @ %p\n",
|
||||
ioc->name, __func__, arg);
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
/**
|
||||
|
|
@ -2661,7 +2729,7 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
|
|||
struct MPT3SAS_ADAPTER *ioc;
|
||||
struct mpt3_ioctl_header ioctl_header;
|
||||
enum block_state state;
|
||||
long ret = -EINVAL;
|
||||
long ret = -ENOIOCTLCMD;
|
||||
|
||||
/* get IOCTL header */
|
||||
if (copy_from_user(&ioctl_header, (char __user *)arg,
|
||||
|
|
@ -2777,6 +2845,10 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
|
|||
if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_read_buffer))
|
||||
ret = _ctl_diag_read_buffer(ioc, arg);
|
||||
break;
|
||||
case MPT3ADDNLDIAGQUERY:
|
||||
if (_IOC_SIZE(cmd) == sizeof(struct mpt3_addnl_diag_query))
|
||||
ret = _ctl_addnl_diag_query(ioc, arg);
|
||||
break;
|
||||
default:
|
||||
dctlprintk(ioc, printk(MPT3SAS_INFO_FMT
|
||||
"unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd));
|
||||
|
|
@ -3591,7 +3663,9 @@ mpt3sas_ctl_tm_sysfs(struct MPT3SAS_ADAPTER *ioc, u8 task_type)
|
|||
tm_count++;
|
||||
doorbell = mpt3sas_base_get_iocstate(ioc, 0);
|
||||
if ((doorbell &
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT ||
|
||||
(doorbell &
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_COREDUMP )
|
||||
goto fault_in_progress;
|
||||
ioc->put_smid_hi_priority(ioc, hpr_smid, 0);
|
||||
}
|
||||
|
|
@ -3643,7 +3717,9 @@ mpt3sas_ctl_tm_sysfs(struct MPT3SAS_ADAPTER *ioc, u8 task_type)
|
|||
tm_count++;
|
||||
doorbell = mpt3sas_base_get_iocstate(ioc, 0);
|
||||
if ((doorbell &
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT ||
|
||||
(doorbell &
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_COREDUMP) {
|
||||
spin_unlock_irqrestore(&ioc->sas_device_lock,
|
||||
flags);
|
||||
goto fault_in_progress;
|
||||
|
|
@ -3699,7 +3775,9 @@ mpt3sas_ctl_tm_sysfs(struct MPT3SAS_ADAPTER *ioc, u8 task_type)
|
|||
tm_count++;
|
||||
doorbell = mpt3sas_base_get_iocstate(ioc, 0);
|
||||
if ((doorbell &
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT ||
|
||||
(doorbell &
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_COREDUMP) {
|
||||
spin_unlock_irqrestore(&ioc->pcie_device_lock,
|
||||
flags);
|
||||
goto fault_in_progress;
|
||||
|
|
@ -3750,7 +3828,9 @@ mpt3sas_ctl_tm_sysfs(struct MPT3SAS_ADAPTER *ioc, u8 task_type)
|
|||
tm_count++;
|
||||
doorbell = mpt3sas_base_get_iocstate(ioc, 0);
|
||||
if ((doorbell &
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT ||
|
||||
(doorbell &
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_COREDUMP) {
|
||||
spin_unlock_irqrestore(&ioc->raid_device_lock,
|
||||
flags);
|
||||
goto fault_in_progress;
|
||||
|
|
@ -3821,7 +3901,9 @@ mpt3sas_ctl_tm_sysfs(struct MPT3SAS_ADAPTER *ioc, u8 task_type)
|
|||
tm_count++;
|
||||
doorbell = mpt3sas_base_get_iocstate(ioc, 0);
|
||||
if ((doorbell &
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT ||
|
||||
(doorbell &
|
||||
MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_COREDUMP) {
|
||||
scsi_device_put(sdev);
|
||||
goto fault_in_progress;
|
||||
}
|
||||
|
|
@ -3878,8 +3960,10 @@ _ctl_task_management_store(struct class_device *cdev, const char *buf,
|
|||
switch (opcode) {
|
||||
|
||||
case 1:
|
||||
ioc->reset_from_user = 1;
|
||||
scsi_block_requests(ioc->shost);
|
||||
printk(MPT3SAS_INFO_FMT "diag reset: %s\n", ioc->name,
|
||||
printk(MPT3SAS_INFO_FMT
|
||||
"sysfs: diag reset issued: %s\n", ioc->name,
|
||||
((!mpt3sas_base_hard_reset_handler(ioc,
|
||||
FORCE_BIG_HAMMER)) ? "SUCCESS" : "FAILED"));
|
||||
scsi_unblock_requests(ioc->shost);
|
||||
|
|
@ -3887,8 +3971,10 @@ _ctl_task_management_store(struct class_device *cdev, const char *buf,
|
|||
break;
|
||||
|
||||
case 2:
|
||||
ioc->reset_from_user = 1;
|
||||
scsi_block_requests(ioc->shost);
|
||||
printk(MPT3SAS_INFO_FMT "message unit reset: %s\n", ioc->name,
|
||||
printk(MPT3SAS_INFO_FMT
|
||||
"sysfs: message unit reset issued: %s\n", ioc->name,
|
||||
((!mpt3sas_base_hard_reset_handler(ioc,
|
||||
SOFT_RESET)) ? "SUCCESS" : "FAILED"));
|
||||
scsi_unblock_requests(ioc->shost);
|
||||
|
|
@ -3896,7 +3982,8 @@ _ctl_task_management_store(struct class_device *cdev, const char *buf,
|
|||
break;
|
||||
|
||||
case 3:
|
||||
printk(MPT3SAS_INFO_FMT "TASKTYPE_ABORT_TASK:\n", ioc->name);
|
||||
printk(MPT3SAS_INFO_FMT
|
||||
"sysfs: TASKTYPE_ABORT_TASK :\n", ioc->name);
|
||||
ioc->got_task_abort_from_sysfs = 1;
|
||||
mpt3sas_ctl_tm_sysfs(ioc,
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK);
|
||||
|
|
@ -3904,20 +3991,22 @@ _ctl_task_management_store(struct class_device *cdev, const char *buf,
|
|||
break;
|
||||
|
||||
case 4:
|
||||
printk(MPT3SAS_INFO_FMT "TASKTYPE_TARGET_RESET:\n", ioc->name);
|
||||
printk(MPT3SAS_INFO_FMT
|
||||
"sysfs: TASKTYPE_TARGET_RESET:\n", ioc->name);
|
||||
mpt3sas_ctl_tm_sysfs(ioc,
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
printk(MPT3SAS_INFO_FMT "TASKTYPE_LOGICAL_UNIT_RESET:\n",
|
||||
ioc->name);
|
||||
printk(MPT3SAS_INFO_FMT
|
||||
"sysfs: TASKTYPE_LOGICAL_UNIT_RESET:\n", ioc->name);
|
||||
mpt3sas_ctl_tm_sysfs(ioc,
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
printk(MPT3SAS_INFO_FMT "TASKTYPE_ABRT_TASK_SET\n", ioc->name);
|
||||
printk(MPT3SAS_INFO_FMT "sysfs: TASKTYPE_ABRT_TASK_SET\n",
|
||||
ioc->name);
|
||||
mpt3sas_ctl_tm_sysfs(ioc,
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET);
|
||||
break;
|
||||
|
|
@ -4306,6 +4395,7 @@ _ctl_host_trace_buffer_enable_store(struct class_device *cdev, const char *buf,
|
|||
goto out;
|
||||
printk(MPT3SAS_INFO_FMT "releasing host trace buffer\n",
|
||||
ioc->name);
|
||||
ioc->htb_rel.buffer_rel_condition = MPT3_DIAG_BUFFER_REL_SYSFS;
|
||||
mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
|
||||
&issue_reset);
|
||||
}
|
||||
|
|
@ -4372,17 +4462,38 @@ _ctl_diag_trigger_master_store(struct class_device *cdev, const char *buf,
|
|||
{
|
||||
struct Scsi_Host *shost = class_to_shost(cdev);
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_private(shost);
|
||||
struct SL_WH_MASTER_TRIGGER_T *master_tg;
|
||||
unsigned long flags;
|
||||
ssize_t rc;
|
||||
bool set = 1;
|
||||
|
||||
rc = min(sizeof(struct SL_WH_MASTER_TRIGGER_T), count);
|
||||
|
||||
if (ioc->supports_trigger_pages) {
|
||||
master_tg = kzalloc(sizeof(struct SL_WH_MASTER_TRIGGER_T),
|
||||
GFP_KERNEL);
|
||||
if (!master_tg)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(master_tg, buf, rc);
|
||||
if (!master_tg->MasterData)
|
||||
set = 0;
|
||||
if (mpt3sas_config_update_driver_trigger_pg1(ioc, master_tg,
|
||||
set)) {
|
||||
kfree(master_tg);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
rc = min(sizeof(struct SL_WH_MASTER_TRIGGER_T), count);
|
||||
memset(&ioc->diag_trigger_master, 0,
|
||||
sizeof(struct SL_WH_MASTER_TRIGGER_T));
|
||||
memcpy(&ioc->diag_trigger_master, buf, rc);
|
||||
ioc->diag_trigger_master.MasterData |=
|
||||
(MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
return rc;
|
||||
}
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25))
|
||||
|
|
@ -4440,17 +4551,37 @@ _ctl_diag_trigger_event_store(struct class_device *cdev, const char *buf,
|
|||
{
|
||||
struct Scsi_Host *shost = class_to_shost(cdev);
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_private(shost);
|
||||
struct SL_WH_EVENT_TRIGGERS_T *event_tg;
|
||||
unsigned long flags;
|
||||
ssize_t sz;
|
||||
bool set = 1;
|
||||
|
||||
sz = min(sizeof(struct SL_WH_EVENT_TRIGGERS_T), count);
|
||||
if (ioc->supports_trigger_pages) {
|
||||
event_tg = kzalloc(sizeof(struct SL_WH_EVENT_TRIGGERS_T),
|
||||
GFP_KERNEL);
|
||||
if (!event_tg)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(event_tg, buf, sz);
|
||||
if (!event_tg->ValidEntries)
|
||||
set = 0;
|
||||
if (mpt3sas_config_update_driver_trigger_pg2(ioc, event_tg,
|
||||
set)) {
|
||||
kfree(event_tg);
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
sz = min(sizeof(struct SL_WH_EVENT_TRIGGERS_T), count);
|
||||
|
||||
memset(&ioc->diag_trigger_event, 0,
|
||||
sizeof(struct SL_WH_EVENT_TRIGGERS_T));
|
||||
memcpy(&ioc->diag_trigger_event, buf, sz);
|
||||
if (ioc->diag_trigger_event.ValidEntries > NUM_VALID_ENTRIES)
|
||||
ioc->diag_trigger_event.ValidEntries = NUM_VALID_ENTRIES;
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
return sz;
|
||||
}
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25))
|
||||
|
|
@ -4508,16 +4639,36 @@ _ctl_diag_trigger_scsi_store(struct class_device *cdev, const char *buf,
|
|||
{
|
||||
struct Scsi_Host *shost = class_to_shost(cdev);
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_private(shost);
|
||||
struct SL_WH_SCSI_TRIGGERS_T *scsi_tg;
|
||||
unsigned long flags;
|
||||
ssize_t sz;
|
||||
bool set = 1;
|
||||
|
||||
sz = min(sizeof(struct SL_WH_SCSI_TRIGGERS_T), count);
|
||||
if (ioc->supports_trigger_pages) {
|
||||
scsi_tg = kzalloc(sizeof(struct SL_WH_SCSI_TRIGGERS_T),
|
||||
GFP_KERNEL);
|
||||
if (!scsi_tg)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(scsi_tg, buf, sz);
|
||||
if (!scsi_tg->ValidEntries)
|
||||
set = 0;
|
||||
if (mpt3sas_config_update_driver_trigger_pg3(ioc, scsi_tg,
|
||||
set)) {
|
||||
kfree(scsi_tg);
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
sz = min(sizeof(ioc->diag_trigger_scsi), count);
|
||||
|
||||
memset(&ioc->diag_trigger_scsi, 0, sizeof(ioc->diag_trigger_scsi));
|
||||
memcpy(&ioc->diag_trigger_scsi, buf, sz);
|
||||
if (ioc->diag_trigger_scsi.ValidEntries > NUM_VALID_ENTRIES)
|
||||
ioc->diag_trigger_scsi.ValidEntries = NUM_VALID_ENTRIES;
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
return sz;
|
||||
}
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25))
|
||||
|
|
@ -4576,17 +4727,36 @@ _ctl_diag_trigger_mpi_store(struct class_device *cdev, const char *buf,
|
|||
{
|
||||
struct Scsi_Host *shost = class_to_shost(cdev);
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_private(shost);
|
||||
struct SL_WH_MPI_TRIGGERS_T *mpi_tg;
|
||||
unsigned long flags;
|
||||
ssize_t sz;
|
||||
bool set = 1;
|
||||
|
||||
sz = min(sizeof(struct SL_WH_MPI_TRIGGERS_T), count);
|
||||
if (ioc->supports_trigger_pages) {
|
||||
mpi_tg = kzalloc(sizeof(struct SL_WH_MPI_TRIGGERS_T),
|
||||
GFP_KERNEL);
|
||||
if (!mpi_tg)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(mpi_tg, buf, sz);
|
||||
if (!mpi_tg->ValidEntries)
|
||||
set = 0;
|
||||
if (mpt3sas_config_update_driver_trigger_pg4(ioc, mpi_tg,
|
||||
set)) {
|
||||
kfree(mpi_tg);
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
sz = min(sizeof(struct SL_WH_MPI_TRIGGERS_T), count);
|
||||
memset(&ioc->diag_trigger_mpi, 0,
|
||||
sizeof(struct SL_WH_EVENT_TRIGGERS_T));
|
||||
memcpy(&ioc->diag_trigger_mpi, buf, sz);
|
||||
if (ioc->diag_trigger_mpi.ValidEntries > NUM_VALID_ENTRIES)
|
||||
ioc->diag_trigger_mpi.ValidEntries = NUM_VALID_ENTRIES;
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
return sz;
|
||||
}
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25))
|
||||
|
|
@ -4628,6 +4798,123 @@ static CLASS_DEVICE_ATTR(drv_support_bitmap, S_IRUGO,
|
|||
_ctl_drv_support_bitmap_show, NULL);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* _ctl_enable_sdev_max_qd_show - display whether enable_sdev_max_qd is
|
||||
* enabled/disabled
|
||||
* @cdev - pointer to embedded class device
|
||||
* @buf - the buffer returned
|
||||
*
|
||||
* A sysfs read/write shost attribute. This attribute is used to set the
|
||||
* targets queue depth to HBA IO queue depth if this attribute is enabled.
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25))
|
||||
static ssize_t
|
||||
_ctl_enable_sdev_max_qd_show(struct device *cdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
#else
|
||||
static ssize_t
|
||||
_ctl_enable_sdev_max_qd_show(struct class_device *cdev, char *buf)
|
||||
#endif
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(cdev);
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_private(shost);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ioc->enable_sdev_max_qd);
|
||||
}
|
||||
|
||||
/**
|
||||
* _ctl_enable_sdev_max_qd_store - Enable/disable enable_sdev_max_qd
|
||||
* @cdev - pointer to embedded class device
|
||||
* @buf - the buffer returned
|
||||
*
|
||||
* A sysfs read/write shost attribute. This attribute is used to set the
|
||||
* targets queue depth to HBA IO queue depth if this attribute is enabled.
|
||||
* If this attribute is disabled then targets will have default
|
||||
* queue depth.
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25))
|
||||
static ssize_t
|
||||
_ctl_enable_sdev_max_qd_store(struct device *cdev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
#else
|
||||
static ssize_t
|
||||
_ctl_enable_sdev_max_qd_store(struct class_device *cdev, const char *buf,
|
||||
size_t count)
|
||||
#endif
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(cdev);
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_private(shost);
|
||||
struct MPT3SAS_DEVICE *sas_device_priv_data;
|
||||
struct MPT3SAS_TARGET *sas_target_priv_data;
|
||||
int val = 0;
|
||||
struct scsi_device *sdev;
|
||||
struct _raid_device *raid_device;
|
||||
int qdepth;
|
||||
|
||||
if (sscanf(buf, "%d", &val) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
switch (val) {
|
||||
case 0:
|
||||
ioc->enable_sdev_max_qd = 0;
|
||||
shost_for_each_device(sdev, ioc->shost) {
|
||||
sas_device_priv_data = sdev->hostdata;
|
||||
if (!sas_device_priv_data)
|
||||
continue;
|
||||
sas_target_priv_data = sas_device_priv_data->sas_target;
|
||||
if (!sas_target_priv_data)
|
||||
continue;
|
||||
|
||||
if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
|
||||
raid_device = mpt3sas_raid_device_find_by_handle(ioc,
|
||||
sas_target_priv_data->handle);
|
||||
|
||||
switch (raid_device->volume_type) {
|
||||
case MPI2_RAID_VOL_TYPE_RAID0:
|
||||
if (raid_device->device_info &
|
||||
MPI2_SAS_DEVICE_INFO_SSP_TARGET)
|
||||
qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
|
||||
else
|
||||
qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
|
||||
break;
|
||||
case MPI2_RAID_VOL_TYPE_RAID1E:
|
||||
case MPI2_RAID_VOL_TYPE_RAID1:
|
||||
case MPI2_RAID_VOL_TYPE_RAID10:
|
||||
case MPI2_RAID_VOL_TYPE_UNKNOWN:
|
||||
default:
|
||||
qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
|
||||
}
|
||||
} else if (sas_target_priv_data->flags &
|
||||
MPT_TARGET_FLAGS_PCIE_DEVICE)
|
||||
qdepth = MPT3SAS_NVME_QUEUE_DEPTH;
|
||||
else
|
||||
qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
|
||||
|
||||
mpt3sas_scsih_change_queue_depth(sdev, qdepth);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
ioc->enable_sdev_max_qd = 1;
|
||||
shost_for_each_device(sdev, ioc->shost) {
|
||||
mpt3sas_scsih_change_queue_depth(sdev, shost->can_queue);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25))
|
||||
static DEVICE_ATTR(enable_sdev_max_qd, S_IRUGO | S_IWUSR,
|
||||
_ctl_enable_sdev_max_qd_show, _ctl_enable_sdev_max_qd_store);
|
||||
#else
|
||||
static CLASS_DEVICE_ATTR(enable_sdev_max_qd, S_IRUGO | S_IWUSR,
|
||||
_ctl_enable_sdev_max_qd_show, _ctl_enable_sdev_max_qd_store);
|
||||
#endif
|
||||
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25))
|
||||
struct device_attribute *mpt3sas_host_attrs[] = {
|
||||
&dev_attr_version_fw,
|
||||
|
|
@ -4664,6 +4951,7 @@ struct device_attribute *mpt3sas_host_attrs[] = {
|
|||
&dev_attr_ddio_err_count,
|
||||
#endif
|
||||
&dev_attr_drv_support_bitmap,
|
||||
&dev_attr_enable_sdev_max_qd,
|
||||
NULL,
|
||||
};
|
||||
#else
|
||||
|
|
@ -4702,6 +4990,7 @@ struct class_device_attribute *mpt3sas_host_attrs[] = {
|
|||
&class_device_attr_ddio_err_count,
|
||||
#endif
|
||||
&class_device_attr_drv_support_bitmap,
|
||||
&class_device_attr_enable_sdev_max_qd,
|
||||
NULL,
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -104,6 +104,8 @@
|
|||
struct mpt3_diag_query)
|
||||
#define MPT3DIAGREADBUFFER _IOWR(MPT3_MAGIC_NUMBER, 30, \
|
||||
struct mpt3_diag_read_buffer)
|
||||
#define MPT3ADDNLDIAGQUERY _IOWR(MPT3_MAGIC_NUMBER, 32, \
|
||||
struct mpt3_addnl_diag_query)
|
||||
|
||||
/* Trace Buffer default UniqueId */
|
||||
#define MPT2DIAGBUFFUNIQUEID (0x07075900)
|
||||
|
|
@ -440,6 +442,26 @@ struct mpt3_diag_read_buffer {
|
|||
uint32_t diagnostic_data[1];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mpt3_addnl_diag_query - diagnostic buffer release reason
|
||||
* @hdr - generic header
|
||||
* @unique_id - unique id associated with this buffer.
|
||||
* @buffer_rel_condition - Release condition ioctl/sysfs/reset
|
||||
* @reserved1
|
||||
* @trigger_type - Master/Event/scsi/MPI
|
||||
* @trigger_info_dwords - Data Correspondig to trigger type
|
||||
* @reserved2
|
||||
*/
|
||||
struct mpt3_addnl_diag_query {
|
||||
struct mpt3_ioctl_header hdr;
|
||||
uint32_t unique_id;
|
||||
uint16_t buffer_rel_condition;
|
||||
uint16_t reserved1;
|
||||
uint32_t trigger_type;
|
||||
uint32_t trigger_info_dwords[2];
|
||||
uint32_t reserved2[2];
|
||||
};
|
||||
|
||||
/* Chunk size to use when doing a FW Download */
|
||||
#define FW_DL_CHUNK_SIZE 0x4000
|
||||
#endif /* MPT3SAS_CTL_H_INCLUDED */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* This is the Fusion MPT base driver providing common API layer interface
|
||||
* for access to MPT (Message Passing Technology) firmware.
|
||||
*
|
||||
* Copyright (C) 2020 Broadcom Inc.
|
||||
* (mailto:MPT-FusionLinux.pdl@broadcom.com)
|
||||
*
|
||||
* 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 the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
|
||||
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
|
||||
* solely responsible for determining the appropriateness of using and
|
||||
* distributing the Program and assumes all risks associated with its
|
||||
* exercise of rights under this Agreement, including but not limited to
|
||||
* the risks and costs of program errors, damage to or loss of data,
|
||||
* programs or equipment, and unavailability or interruption of operations.
|
||||
|
||||
* DISCLAIMER OF LIABILITY
|
||||
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/uio.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#include "mpt3sas_base.h"
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
struct dentry *mpt3sas_debugfs_root = NULL;
|
||||
|
||||
/*
|
||||
* _debugfs_iocdump_read : copy ioc dump from debugfs buffer
|
||||
*/
|
||||
static ssize_t
|
||||
_debugfs_iocdump_read(struct file *filp, char __user *ubuf, size_t cnt,
|
||||
loff_t *ppos)
|
||||
|
||||
{
|
||||
struct mpt3sas_debugfs_buffer *debug = filp->private_data;
|
||||
|
||||
if (!debug || !debug->buf)
|
||||
return 0;
|
||||
|
||||
return simple_read_from_buffer(ubuf, cnt, ppos, debug->buf, debug->len);
|
||||
}
|
||||
|
||||
/*
|
||||
* _debugfs_iocdump_open : open the ioc_dump debugfs attribute file
|
||||
*/
|
||||
static int
|
||||
_debugfs_iocdump_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct MPT3SAS_ADAPTER *ioc = inode->i_private;
|
||||
struct mpt3sas_debugfs_buffer *debug;
|
||||
|
||||
debug = kzalloc(sizeof(struct mpt3sas_debugfs_buffer), GFP_KERNEL);
|
||||
if (!debug)
|
||||
return -ENOMEM;
|
||||
|
||||
debug->buf = (void *)ioc;
|
||||
debug->len = sizeof(struct MPT3SAS_ADAPTER);
|
||||
file->private_data = debug;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* _debugfs_iocdump_release : release the ioc_dump debugfs attribute
|
||||
*/
|
||||
static int
|
||||
_debugfs_iocdump_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct mpt3sas_debugfs_buffer *debug = file->private_data;
|
||||
|
||||
if (!debug)
|
||||
return 0;
|
||||
|
||||
file->private_data = NULL;
|
||||
kfree(debug);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations mpt3sas_debugfs_iocdump_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = _debugfs_iocdump_open,
|
||||
.read = _debugfs_iocdump_read,
|
||||
.release = _debugfs_iocdump_release,
|
||||
};
|
||||
|
||||
/*
|
||||
* mpt3sas_init_debugfs : Create debugfs root for mpt3sas driver
|
||||
*/
|
||||
void mpt3sas_init_debugfs(void)
|
||||
{
|
||||
mpt3sas_debugfs_root = debugfs_create_dir("mpt3sas", NULL);
|
||||
if (!mpt3sas_debugfs_root)
|
||||
pr_info("mpt3sas: Cannot create debugfs root\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* mpt3sas_exit_debugfs : Remove debugfs root for mpt3sas driver
|
||||
*/
|
||||
void mpt3sas_exit_debugfs(void)
|
||||
{
|
||||
if (mpt3sas_debugfs_root)
|
||||
debugfs_remove_recursive(mpt3sas_debugfs_root);
|
||||
}
|
||||
|
||||
/*
|
||||
* mpt3sas_setup_debugfs : Setup debugfs per HBA adapter
|
||||
* ioc: MPT3SAS_ADAPTER object
|
||||
*/
|
||||
void
|
||||
mpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
char name[64];
|
||||
|
||||
snprintf(name, sizeof(name), "scsi_host%d", ioc->shost->host_no);
|
||||
if (!ioc->debugfs_root) {
|
||||
ioc->debugfs_root =
|
||||
debugfs_create_dir(name, mpt3sas_debugfs_root);
|
||||
if (!ioc->debugfs_root) {
|
||||
dev_err(&ioc->pdev->dev,
|
||||
"Cannot create per adapter debugfs directory\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(name, sizeof(name), "ioc_dump");
|
||||
ioc->ioc_dump = debugfs_create_file(name, S_IRUGO,
|
||||
ioc->debugfs_root, ioc, &mpt3sas_debugfs_iocdump_fops);
|
||||
if (!ioc->ioc_dump) {
|
||||
dev_err(&ioc->pdev->dev,
|
||||
"Cannot create ioc_dump debugfs file\n");
|
||||
debugfs_remove(ioc->debugfs_root);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(name, sizeof(name), "host_recovery");
|
||||
debugfs_create_u8(name, S_IRUGO, ioc->debugfs_root, &ioc->shost_recovery);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* mpt3sas_destroy_debugfs : Destroy debugfs per HBA adapter
|
||||
* ioc: MPT3SAS_ADAPTER object
|
||||
*/
|
||||
void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
if (ioc->debugfs_root)
|
||||
debugfs_remove_recursive(ioc->debugfs_root);
|
||||
}
|
||||
|
||||
#else
|
||||
void mpt3sas_init_debugfs(void)
|
||||
{
|
||||
}
|
||||
void mpt3sas_exit_debugfs(void)
|
||||
{
|
||||
}
|
||||
void mpt3sas_setup_debugfs(struct megasas_instance *instance)
|
||||
{
|
||||
}
|
||||
void mpt3sas_destroy_debugfs(struct megasas_instance *instance)
|
||||
{
|
||||
}
|
||||
#endif /*CONFIG_DEBUG_FS*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -132,6 +132,26 @@ _transport_sas_node_find_by_sas_phy(struct MPT3SAS_ADAPTER *ioc,
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* _transport_get_port_id_by_sas_phy - get zone's port id that Phy belong to
|
||||
* @phy - sas_phy object
|
||||
*
|
||||
* Return Port number
|
||||
*/
|
||||
static inline u8
|
||||
_transport_get_port_id_by_sas_phy(struct sas_phy *phy)
|
||||
{
|
||||
u8 port_id = 0xFF;
|
||||
#if defined(SAS_PHY_HOSTDATA)
|
||||
struct hba_port *port = phy->hostdata;
|
||||
if (port)
|
||||
port_id = port->port_id;
|
||||
else
|
||||
BUG();
|
||||
#endif
|
||||
return port_id;
|
||||
}
|
||||
|
||||
static int
|
||||
_transport_find_parent_node(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct sas_phy *phy)
|
||||
|
|
@ -159,6 +179,49 @@ _transport_find_parent_node(struct MPT3SAS_ADAPTER *ioc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* _transport_get_port_id_by_rphy - Get Port number from rphy object
|
||||
* @ioc: per adapter object
|
||||
* @rphy: sas_rphy object
|
||||
*
|
||||
* Returns Port number.
|
||||
*/
|
||||
u8
|
||||
_transport_get_port_id_by_rphy(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct sas_rphy *rphy)
|
||||
{
|
||||
struct _sas_node *sas_expander;
|
||||
struct _sas_device *sas_device;
|
||||
unsigned long flags;
|
||||
u8 port_id = 0xFF;
|
||||
|
||||
if (!rphy)
|
||||
return port_id;
|
||||
|
||||
if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
|
||||
rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) {
|
||||
spin_lock_irqsave(&ioc->sas_node_lock, flags);
|
||||
list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
|
||||
if (sas_expander->rphy == rphy) {
|
||||
port_id = sas_expander->port->port_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
|
||||
} else if (rphy->identify.device_type == SAS_END_DEVICE) {
|
||||
spin_lock_irqsave(&ioc->sas_device_lock, flags);
|
||||
sas_device = __mpt3sas_get_sdev_by_addr_and_rphy(ioc,
|
||||
rphy->identify.sas_address, rphy);
|
||||
if (sas_device) {
|
||||
port_id = sas_device->port->port_id;
|
||||
sas_device_put(sas_device);
|
||||
}
|
||||
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
|
||||
}
|
||||
|
||||
return port_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* _transport_convert_phy_link_rate -
|
||||
* @link_rate: link rate returned from mpt firmware
|
||||
|
|
@ -377,7 +440,7 @@ struct rep_manu_reply {
|
|||
*/
|
||||
static int
|
||||
_transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc,
|
||||
u64 sas_address, struct sas_expander_device *edev)
|
||||
u64 sas_address, struct sas_expander_device *edev, u8 port_id)
|
||||
{
|
||||
Mpi2SmpPassthroughRequest_t *mpi_request;
|
||||
Mpi2SmpPassthroughReply_t *mpi_reply;
|
||||
|
|
@ -448,7 +511,7 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc,
|
|||
|
||||
memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
|
||||
mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
|
||||
mpi_request->PhysicalPort = 0xFF;
|
||||
mpi_request->PhysicalPort = port_id;
|
||||
mpi_request->SASAddress = cpu_to_le64(sas_address);
|
||||
mpi_request->RequestDataLength = cpu_to_le16(data_out_sz);
|
||||
psge = &mpi_request->SGL;
|
||||
|
|
@ -740,6 +803,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
|
|||
#if defined(MPT_WIDE_PORT_API)
|
||||
struct sas_port *port;
|
||||
#endif
|
||||
struct virtual_phy *vphy = NULL;
|
||||
|
||||
if (!hba_port) {
|
||||
printk(MPT3SAS_ERR_FMT "failure at %s:%d/%s()!\n",
|
||||
|
|
@ -793,10 +857,21 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
|
|||
continue;
|
||||
list_add_tail(&sas_node->phy[i].port_siblings,
|
||||
&mpt3sas_port->phy_list);
|
||||
if (sas_node->handle <= ioc->sas_hba.num_phys) {
|
||||
hba_port->phy_mask |= (1 << i);
|
||||
}
|
||||
mpt3sas_port->num_phys++;
|
||||
if (sas_node->handle <= ioc->sas_hba.num_phys) {
|
||||
if (!sas_node->phy[i].hba_vphy) {
|
||||
hba_port->phy_mask |= (1 << i);
|
||||
continue;
|
||||
}
|
||||
|
||||
vphy = mpt3sas_get_vphy_by_phy(ioc, hba_port, i);
|
||||
if (!vphy) {
|
||||
printk(MPT3SAS_ERR_FMT
|
||||
"failure at %s:%d/%s()!\n",
|
||||
ioc->name, __FILE__, __LINE__, __func__);
|
||||
goto out_fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mpt3sas_port->num_phys) {
|
||||
|
|
@ -847,8 +922,14 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
|
|||
if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
|
||||
rphy = sas_end_device_alloc(port);
|
||||
sas_device->rphy=rphy;
|
||||
if (sas_node->handle <= ioc->sas_hba.num_phys)
|
||||
hba_port->sas_address = sas_device->sas_address;
|
||||
if (sas_node->handle <= ioc->sas_hba.num_phys) {
|
||||
if (!vphy)
|
||||
hba_port->sas_address =
|
||||
sas_device->sas_address;
|
||||
else
|
||||
vphy->sas_address =
|
||||
sas_device->sas_address;
|
||||
}
|
||||
} else {
|
||||
rphy = sas_expander_alloc(port,
|
||||
mpt3sas_port->remote_identify.device_type);
|
||||
|
|
@ -876,11 +957,12 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
|
|||
sas_device->pend_sas_rphy_add = 0;
|
||||
sas_device_put(sas_device);
|
||||
}
|
||||
if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
|
||||
dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
|
||||
"sas_addr(0x%016llx)\n", handle,
|
||||
(unsigned long long)
|
||||
mpt3sas_port->remote_identify.sas_address);
|
||||
|
||||
dev_printk(KERN_INFO, &rphy->dev,
|
||||
"%s: added: handle(0x%04x), sas_addr(0x%016llx)\n",
|
||||
__func__, handle, (unsigned long long)
|
||||
mpt3sas_port->remote_identify.sas_address);
|
||||
|
||||
mpt3sas_port->rphy = rphy;
|
||||
spin_lock_irqsave(&ioc->sas_node_lock, flags);
|
||||
list_add_tail(&mpt3sas_port->port_list, &sas_node->sas_port_list);
|
||||
|
|
@ -894,7 +976,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
|
|||
MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
|
||||
_transport_expander_report_manufacture(ioc,
|
||||
mpt3sas_port->remote_identify.sas_address,
|
||||
rphy_to_expander_device(rphy));
|
||||
rphy_to_expander_device(rphy), hba_port->port_id);
|
||||
#endif
|
||||
return mpt3sas_port;
|
||||
|
||||
|
|
@ -932,6 +1014,7 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
|
|||
struct _sas_phy *mpt3sas_phy, *next_phy;
|
||||
#endif
|
||||
struct hba_port *hba_port, *hba_port_next=NULL;
|
||||
struct virtual_phy *vphy, *vphy_next=NULL;
|
||||
|
||||
if (!port)
|
||||
return;
|
||||
|
|
@ -962,17 +1045,52 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
|
|||
|
||||
if ((sas_node->handle <= ioc->sas_hba.num_phys) &&
|
||||
(ioc->multipath_on_hba)) {
|
||||
|
||||
if (port->vphys_mask) {
|
||||
list_for_each_entry_safe(vphy, vphy_next,
|
||||
&port->vphys_list, list) {
|
||||
if (vphy->sas_address != sas_address)
|
||||
continue;
|
||||
printk(MPT3SAS_INFO_FMT
|
||||
"remove vphy entry: %p of port:%p,from %d"
|
||||
" port's vphys list\n", ioc->name,
|
||||
vphy, port, port->port_id);
|
||||
port->vphys_mask &= ~vphy->phy_mask;
|
||||
list_del(&vphy->list);
|
||||
kfree(vphy);
|
||||
}
|
||||
|
||||
if (!port->vphys_mask && !port->sas_address) {
|
||||
printk(MPT3SAS_INFO_FMT
|
||||
"remove hba_port entry: %p port: %d from"
|
||||
" hba_port list\n", ioc->name,
|
||||
port, port->port_id);
|
||||
list_del(&port->list);
|
||||
kfree(port);
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(hba_port, hba_port_next,
|
||||
&ioc->port_table_list, list) {
|
||||
&ioc->port_table_list, list) {
|
||||
if (hba_port != port)
|
||||
continue;
|
||||
if (hba_port->sas_address != sas_address)
|
||||
continue;
|
||||
printk(MPT3SAS_INFO_FMT "remove hba_port entry: %p"
|
||||
" port: %d from hba_port list\n", ioc->name,
|
||||
hba_port, hba_port->port_id);
|
||||
list_del(&hba_port->list);
|
||||
kfree(hba_port);
|
||||
if (!port->vphys_mask) {
|
||||
printk(MPT3SAS_INFO_FMT
|
||||
"remove hba_port entry: %p port: %d from"
|
||||
" hba_port list\n", ioc->name,
|
||||
hba_port, hba_port->port_id);
|
||||
list_del(&hba_port->list);
|
||||
kfree(hba_port);
|
||||
} else {
|
||||
printk(MPT3SAS_INFO_FMT
|
||||
"clearing sas_address from hba_port"
|
||||
" entry: %p port: %d from hba_port list\n",
|
||||
ioc->name, hba_port, hba_port->port_id);
|
||||
port->sas_address = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1000,6 +1118,8 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
|
|||
}
|
||||
if(!ioc->remove_host)
|
||||
sas_port_delete(mpt3sas_port->port);
|
||||
printk(MPT3SAS_INFO_FMT "%s: removed: sas_addr(0x%016llx)\n",
|
||||
ioc->name, __func__, (unsigned long long)sas_address);
|
||||
#else
|
||||
if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
|
||||
dev_printk(KERN_INFO, &mpt3sas_port->rphy->dev,
|
||||
|
|
@ -1007,6 +1127,8 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
|
|||
(unsigned long long)sas_address);
|
||||
if(!ioc->remove_host)
|
||||
sas_rphy_delete(mpt3sas_port->rphy);
|
||||
printk(MPT3SAS_INFO_FMT "%s: removed: sas_addr(0x%016llx)\n",
|
||||
ioc->name, __func__, (unsigned long long)sas_address);
|
||||
#endif
|
||||
kfree(mpt3sas_port);
|
||||
}
|
||||
|
|
@ -1354,7 +1476,7 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc,
|
|||
|
||||
memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
|
||||
mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
|
||||
mpi_request->PhysicalPort = 0xFF;
|
||||
mpi_request->PhysicalPort = _transport_get_port_id_by_sas_phy(phy);
|
||||
mpi_request->VF_ID = 0; /* TODO */
|
||||
mpi_request->VP_ID = 0;
|
||||
mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
|
||||
|
|
@ -1646,7 +1768,7 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
|
|||
|
||||
memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
|
||||
mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
|
||||
mpi_request->PhysicalPort = 0xFF;
|
||||
mpi_request->PhysicalPort = _transport_get_port_id_by_sas_phy(phy);
|
||||
mpi_request->VF_ID = 0; /* TODO */
|
||||
mpi_request->VP_ID = 0;
|
||||
mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
|
||||
|
|
@ -2141,7 +2263,7 @@ _transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
|
|||
|
||||
memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
|
||||
mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
|
||||
mpi_request->PhysicalPort = 0xFF;
|
||||
mpi_request->PhysicalPort = _transport_get_port_id_by_rphy(ioc, rphy);
|
||||
mpi_request->SASAddress = (rphy) ?
|
||||
cpu_to_le64(rphy->identify.sas_address) :
|
||||
cpu_to_le64(ioc->sas_hba.sas_address);
|
||||
|
|
@ -2369,7 +2491,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
|
|||
|
||||
memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
|
||||
mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
|
||||
mpi_request->PhysicalPort = 0xFF;
|
||||
mpi_request->PhysicalPort = _transport_get_port_id_by_rphy(ioc, rphy);
|
||||
mpi_request->SASAddress = (rphy) ?
|
||||
cpu_to_le64(rphy->identify.sas_address) :
|
||||
cpu_to_le64(ioc->sas_hba.sas_address);
|
||||
|
|
|
|||
|
|
@ -1,436 +1,468 @@
|
|||
/*
|
||||
* This module provides common API to set Diagnostic trigger for MPT
|
||||
* (Message Passing Technology) based controllers
|
||||
*
|
||||
* This code is based on drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
|
||||
* Copyright (C) 2013-2018 LSI Corporation
|
||||
* Copyright (C) 2013-2018 Avago Technologies
|
||||
* Copyright (C) 2013-2018 Broadcom Inc.
|
||||
* (mailto:MPT-FusionLinux.pdl@broadcom.com)
|
||||
*
|
||||
* 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 the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
|
||||
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
|
||||
* solely responsible for determining the appropriateness of using and
|
||||
* distributing the Program and assumes all risks associated with its
|
||||
* exercise of rights under this Agreement, including but not limited to
|
||||
* the risks and costs of program errors, damage to or loss of data,
|
||||
* programs or equipment, and unavailability or interruption of operations.
|
||||
|
||||
* DISCLAIMER OF LIABILITY
|
||||
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/poll.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "mpt3sas_base.h"
|
||||
|
||||
/**
|
||||
* _mpt3sas_raise_sigio - notifiy app
|
||||
* @ioc: per adapter object
|
||||
* @event_data:
|
||||
*/
|
||||
static void
|
||||
_mpt3sas_raise_sigio(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
|
||||
{
|
||||
Mpi2EventNotificationReply_t *mpi_reply;
|
||||
u16 sz, event_data_sz;
|
||||
unsigned long flags;
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter\n",
|
||||
ioc->name, __func__));
|
||||
|
||||
sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
|
||||
sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4;
|
||||
mpi_reply = kzalloc(sz, GFP_KERNEL);
|
||||
if (!mpi_reply)
|
||||
goto out;
|
||||
mpi_reply->Event = cpu_to_le16(MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED);
|
||||
event_data_sz = (sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4) / 4;
|
||||
mpi_reply->EventDataLength = cpu_to_le16(event_data_sz);
|
||||
memcpy(&mpi_reply->EventData, event_data,
|
||||
sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: add to driver "
|
||||
"event log\n", ioc->name, __func__));
|
||||
mpt3sas_ctl_add_to_event_log(ioc, mpi_reply);
|
||||
kfree(mpi_reply);
|
||||
out:
|
||||
|
||||
/* clearing the diag_trigger_active flag */
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: clearing "
|
||||
"diag_trigger_active flag\n", ioc->name, __func__));
|
||||
ioc->diag_trigger_active = 0;
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: exit\n", ioc->name,
|
||||
__func__));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_process_trigger_data - process the event data for the trigger
|
||||
* @ioc: per adapter object
|
||||
* @event_data:
|
||||
*/
|
||||
void
|
||||
mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
|
||||
{
|
||||
u8 issue_reset = 0;
|
||||
u32 *trig_data = (u32*)&event_data->u.master;
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter\n",
|
||||
ioc->name, __func__));
|
||||
|
||||
/* release the diag buffer trace */
|
||||
if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: release "
|
||||
"trace diag buffer\n", ioc->name, __func__));
|
||||
|
||||
/* add a log message so that user knows which event caused the release */
|
||||
printk(MPT3SAS_INFO_FMT "%s: Releasing the trace buffer."
|
||||
"Trigger_Type 0x%08x, Data[0] 0x%08x, Data[1] 0x%08x\n", ioc->name,
|
||||
__func__, event_data->trigger_type, trig_data[0], trig_data[1]);
|
||||
|
||||
mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
|
||||
&issue_reset);
|
||||
}
|
||||
|
||||
_mpt3sas_raise_sigio(ioc, event_data);
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: exit\n", ioc->name,
|
||||
__func__));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_trigger_master - Master trigger handler
|
||||
* @ioc: per adapter object
|
||||
* @trigger_bitmask:
|
||||
*
|
||||
*/
|
||||
void
|
||||
mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, u32 trigger_bitmask)
|
||||
{
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
|
||||
unsigned long flags;
|
||||
u8 found_match = 0;
|
||||
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT ||
|
||||
trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET)
|
||||
goto by_pass_checks;
|
||||
|
||||
/* check to see if trace buffers are currently registered */
|
||||
if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check to see if trace buffers are currently released */
|
||||
if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_RELEASED) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
by_pass_checks:
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter - "
|
||||
"trigger_bitmask = 0x%08x\n", ioc->name, __func__,
|
||||
trigger_bitmask));
|
||||
|
||||
/* don't send trigger if an trigger is currently active */
|
||||
if (ioc->diag_trigger_active) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check for the trigger condition */
|
||||
if (ioc->diag_trigger_master.MasterData & trigger_bitmask) {
|
||||
found_match = 1;
|
||||
ioc->diag_trigger_active = 1;
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: setting "
|
||||
"diag_trigger_active flag\n", ioc->name, __func__));
|
||||
}
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
if (!found_match)
|
||||
goto out;
|
||||
|
||||
memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
|
||||
event_data.trigger_type = MPT3SAS_TRIGGER_MASTER;
|
||||
event_data.u.master.MasterData = trigger_bitmask;
|
||||
|
||||
if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT ||
|
||||
trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET)
|
||||
_mpt3sas_raise_sigio(ioc, &event_data);
|
||||
else
|
||||
mpt3sas_send_trigger_data_event(ioc, &event_data);
|
||||
|
||||
out:
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: exit\n", ioc->name,
|
||||
__func__));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_trigger_event - Event trigger handler
|
||||
* @ioc: per adapter object
|
||||
* @event:
|
||||
* @log_entry_qualifier:
|
||||
*
|
||||
*/
|
||||
void
|
||||
mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event,
|
||||
u16 log_entry_qualifier)
|
||||
{
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
|
||||
struct SL_WH_EVENT_TRIGGER_T *event_trigger;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
u8 found_match;
|
||||
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
/* check to see if trace buffers are currently registered */
|
||||
if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check to see if trace buffers are currently released */
|
||||
if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_RELEASED) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter - "
|
||||
"event = 0x%04x, log_entry_qualifier = 0x%04x\n", ioc->name,
|
||||
__func__, event, log_entry_qualifier));
|
||||
|
||||
/* don't send trigger if an trigger is currently active */
|
||||
if (ioc->diag_trigger_active) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check for the trigger condition */
|
||||
event_trigger = ioc->diag_trigger_event.EventTriggerEntry;
|
||||
for (i = 0 , found_match = 0; i < ioc->diag_trigger_event.ValidEntries
|
||||
&& !found_match; i++, event_trigger++) {
|
||||
if (event_trigger->EventValue != event)
|
||||
continue;
|
||||
if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
|
||||
if (event_trigger->LogEntryQualifier ==
|
||||
log_entry_qualifier)
|
||||
found_match = 1;
|
||||
continue;
|
||||
}
|
||||
found_match = 1;
|
||||
ioc->diag_trigger_active = 1;
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: setting "
|
||||
"diag_trigger_active flag\n", ioc->name, __func__));
|
||||
}
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
if (!found_match)
|
||||
goto out;
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: setting "
|
||||
"diag_trigger_active flag\n", ioc->name, __func__));
|
||||
memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
|
||||
event_data.trigger_type = MPT3SAS_TRIGGER_EVENT;
|
||||
event_data.u.event.EventValue = event;
|
||||
event_data.u.event.LogEntryQualifier = log_entry_qualifier;
|
||||
mpt3sas_send_trigger_data_event(ioc, &event_data);
|
||||
out:
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: exit\n", ioc->name,
|
||||
__func__));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_trigger_scsi - SCSI trigger handler
|
||||
* @ioc: per adapter object
|
||||
* @sense_key:
|
||||
* @asc:
|
||||
* @ascq:
|
||||
*
|
||||
*/
|
||||
void
|
||||
mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, u8 asc,
|
||||
u8 ascq)
|
||||
{
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
|
||||
struct SL_WH_SCSI_TRIGGER_T *scsi_trigger;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
u8 found_match;
|
||||
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
/* check to see if trace buffers are currently registered */
|
||||
if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check to see if trace buffers are currently released */
|
||||
if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_RELEASED) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter - "
|
||||
"sense_key = 0x%02x, asc = 0x%02x, ascq = 0x%02x\n", ioc->name,
|
||||
__func__, sense_key, asc, ascq));
|
||||
|
||||
/* don't send trigger if an trigger is currently active */
|
||||
if (ioc->diag_trigger_active) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check for the trigger condition */
|
||||
scsi_trigger = ioc->diag_trigger_scsi.SCSITriggerEntry;
|
||||
for (i = 0 , found_match = 0; i < ioc->diag_trigger_scsi.ValidEntries
|
||||
&& !found_match; i++, scsi_trigger++) {
|
||||
if (scsi_trigger->SenseKey != sense_key)
|
||||
continue;
|
||||
if (!(scsi_trigger->ASC == 0xFF || scsi_trigger->ASC == asc))
|
||||
continue;
|
||||
if (!(scsi_trigger->ASCQ == 0xFF || scsi_trigger->ASCQ == ascq))
|
||||
continue;
|
||||
found_match = 1;
|
||||
ioc->diag_trigger_active = 1;
|
||||
}
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
if (!found_match)
|
||||
goto out;
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: setting "
|
||||
"diag_trigger_active flag\n", ioc->name, __func__));
|
||||
memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
|
||||
event_data.trigger_type = MPT3SAS_TRIGGER_SCSI;
|
||||
event_data.u.scsi.SenseKey = sense_key;
|
||||
event_data.u.scsi.ASC = asc;
|
||||
event_data.u.scsi.ASCQ = ascq;
|
||||
mpt3sas_send_trigger_data_event(ioc, &event_data);
|
||||
out:
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: exit\n", ioc->name,
|
||||
__func__));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_trigger_mpi - MPI trigger handler
|
||||
* @ioc: per adapter object
|
||||
* @ioc_status:
|
||||
* @loginfo:
|
||||
*
|
||||
*/
|
||||
void
|
||||
mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, u32 loginfo)
|
||||
{
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
|
||||
struct SL_WH_MPI_TRIGGER_T *mpi_trigger;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
u8 found_match;
|
||||
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
/* check to see if trace buffers are currently registered */
|
||||
if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check to see if trace buffers are currently released */
|
||||
if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_RELEASED) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter - "
|
||||
"ioc_status = 0x%04x, loginfo = 0x%08x\n", ioc->name, __func__,
|
||||
ioc_status, loginfo));
|
||||
|
||||
/* don't send trigger if an trigger is currently active */
|
||||
if (ioc->diag_trigger_active) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check for the trigger condition */
|
||||
mpi_trigger = ioc->diag_trigger_mpi.MPITriggerEntry;
|
||||
for (i = 0 , found_match = 0; i < ioc->diag_trigger_mpi.ValidEntries
|
||||
&& !found_match; i++, mpi_trigger++) {
|
||||
if (mpi_trigger->IOCStatus != ioc_status)
|
||||
continue;
|
||||
if (!(mpi_trigger->IocLogInfo == 0xFFFFFFFF ||
|
||||
mpi_trigger->IocLogInfo == loginfo))
|
||||
continue;
|
||||
found_match = 1;
|
||||
ioc->diag_trigger_active = 1;
|
||||
}
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
if (!found_match)
|
||||
goto out;
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: setting "
|
||||
"diag_trigger_active flag\n", ioc->name, __func__));
|
||||
memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
|
||||
event_data.trigger_type = MPT3SAS_TRIGGER_MPI;
|
||||
event_data.u.mpi.IOCStatus = ioc_status;
|
||||
event_data.u.mpi.IocLogInfo = loginfo;
|
||||
mpt3sas_send_trigger_data_event(ioc, &event_data);
|
||||
out:
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: exit\n", ioc->name,
|
||||
__func__));
|
||||
}
|
||||
/*
|
||||
* This module provides common API to set Diagnostic trigger for MPT
|
||||
* (Message Passing Technology) based controllers
|
||||
*
|
||||
* This code is based on drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
|
||||
* Copyright (C) 2013-2018 LSI Corporation
|
||||
* Copyright (C) 2013-2018 Avago Technologies
|
||||
* Copyright (C) 2013-2018 Broadcom Inc.
|
||||
* (mailto:MPT-FusionLinux.pdl@broadcom.com)
|
||||
*
|
||||
* 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 the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
|
||||
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
|
||||
* solely responsible for determining the appropriateness of using and
|
||||
* distributing the Program and assumes all risks associated with its
|
||||
* exercise of rights under this Agreement, including but not limited to
|
||||
* the risks and costs of program errors, damage to or loss of data,
|
||||
* programs or equipment, and unavailability or interruption of operations.
|
||||
|
||||
* DISCLAIMER OF LIABILITY
|
||||
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/poll.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "mpt3sas_base.h"
|
||||
|
||||
/**
|
||||
* _mpt3sas_raise_sigio - notifiy app
|
||||
* @ioc: per adapter object
|
||||
* @event_data:
|
||||
*/
|
||||
static void
|
||||
_mpt3sas_raise_sigio(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
|
||||
{
|
||||
Mpi2EventNotificationReply_t *mpi_reply;
|
||||
u16 sz, event_data_sz;
|
||||
unsigned long flags;
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter\n",
|
||||
ioc->name, __func__));
|
||||
|
||||
sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
|
||||
sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4;
|
||||
mpi_reply = kzalloc(sz, GFP_KERNEL);
|
||||
if (!mpi_reply)
|
||||
goto out;
|
||||
mpi_reply->Event = cpu_to_le16(MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED);
|
||||
event_data_sz = (sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4) / 4;
|
||||
mpi_reply->EventDataLength = cpu_to_le16(event_data_sz);
|
||||
memcpy(&mpi_reply->EventData, event_data,
|
||||
sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: add to driver "
|
||||
"event log\n", ioc->name, __func__));
|
||||
mpt3sas_ctl_add_to_event_log(ioc, mpi_reply);
|
||||
kfree(mpi_reply);
|
||||
out:
|
||||
|
||||
/* clearing the diag_trigger_active flag */
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: clearing "
|
||||
"diag_trigger_active flag\n", ioc->name, __func__));
|
||||
ioc->diag_trigger_active = 0;
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: exit\n", ioc->name,
|
||||
__func__));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_process_trigger_data - process the event data for the trigger
|
||||
* @ioc: per adapter object
|
||||
* @event_data:
|
||||
*/
|
||||
void
|
||||
mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc,
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
|
||||
{
|
||||
u8 issue_reset = 0;
|
||||
u32 *trig_data = (u32*)&event_data->u.master;
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter\n",
|
||||
ioc->name, __func__));
|
||||
|
||||
/* release the diag buffer trace */
|
||||
if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: release "
|
||||
"trace diag buffer\n", ioc->name, __func__));
|
||||
|
||||
/* add a log message so that user knows which event caused the release */
|
||||
printk(MPT3SAS_INFO_FMT "%s: Releasing the trace buffer."
|
||||
"Trigger_Type 0x%08x, Data[0] 0x%08x, Data[1] 0x%08x\n", ioc->name,
|
||||
__func__, event_data->trigger_type, trig_data[0], trig_data[1]);
|
||||
|
||||
mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
|
||||
&issue_reset);
|
||||
}
|
||||
|
||||
ioc->htb_rel.buffer_rel_condition = MPT3_DIAG_BUFFER_REL_TRIGGER;
|
||||
if (event_data) {
|
||||
ioc->htb_rel.trigger_type = event_data->trigger_type;
|
||||
switch (event_data->trigger_type) {
|
||||
case MPT3SAS_TRIGGER_SCSI:
|
||||
memcpy(&ioc->htb_rel.trigger_info_dwords,
|
||||
&event_data->u.scsi,
|
||||
sizeof(struct SL_WH_SCSI_TRIGGER_T));
|
||||
break;
|
||||
case MPT3SAS_TRIGGER_MPI:
|
||||
memcpy(&ioc->htb_rel.trigger_info_dwords,
|
||||
&event_data->u.mpi,
|
||||
sizeof(struct SL_WH_MPI_TRIGGER_T));
|
||||
break;
|
||||
case MPT3SAS_TRIGGER_MASTER:
|
||||
ioc->htb_rel.trigger_info_dwords[0] =
|
||||
event_data->u.master.MasterData;
|
||||
break;
|
||||
case MPT3SAS_TRIGGER_EVENT:
|
||||
memcpy(&ioc->htb_rel.trigger_info_dwords,
|
||||
&event_data->u.event,
|
||||
sizeof(struct SL_WH_EVENT_TRIGGER_T));
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: %d - Is not a valid Trigger type\n",
|
||||
ioc->name, event_data->trigger_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_mpt3sas_raise_sigio(ioc, event_data);
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: exit\n", ioc->name,
|
||||
__func__));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_trigger_master - Master trigger handler
|
||||
* @ioc: per adapter object
|
||||
* @trigger_bitmask:
|
||||
*
|
||||
*/
|
||||
void
|
||||
mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, u32 trigger_bitmask)
|
||||
{
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
|
||||
unsigned long flags;
|
||||
u8 found_match = 0;
|
||||
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT ||
|
||||
trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET)
|
||||
goto by_pass_checks;
|
||||
|
||||
/* check to see if trace buffers are currently registered */
|
||||
if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check to see if trace buffers are currently released */
|
||||
if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_RELEASED) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
by_pass_checks:
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter - "
|
||||
"trigger_bitmask = 0x%08x\n", ioc->name, __func__,
|
||||
trigger_bitmask));
|
||||
|
||||
/* don't send trigger if an trigger is currently active */
|
||||
if (ioc->diag_trigger_active) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check for the trigger condition */
|
||||
if (ioc->diag_trigger_master.MasterData & trigger_bitmask) {
|
||||
found_match = 1;
|
||||
ioc->diag_trigger_active = 1;
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: setting "
|
||||
"diag_trigger_active flag\n", ioc->name, __func__));
|
||||
}
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
if (!found_match)
|
||||
goto out;
|
||||
|
||||
memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
|
||||
event_data.trigger_type = MPT3SAS_TRIGGER_MASTER;
|
||||
event_data.u.master.MasterData = trigger_bitmask;
|
||||
if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT ||
|
||||
trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET) {
|
||||
ioc->htb_rel.trigger_type = MPT3SAS_TRIGGER_MASTER;
|
||||
ioc->htb_rel.trigger_info_dwords[0] = trigger_bitmask;
|
||||
if (ioc->reset_from_user)
|
||||
ioc->htb_rel.trigger_info_dwords[1] =
|
||||
MPT_DIAG_RESET_ISSUED_BY_USER;
|
||||
_mpt3sas_raise_sigio(ioc, &event_data);
|
||||
} else
|
||||
mpt3sas_send_trigger_data_event(ioc, &event_data);
|
||||
|
||||
out:
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: exit\n", ioc->name,
|
||||
__func__));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_trigger_event - Event trigger handler
|
||||
* @ioc: per adapter object
|
||||
* @event:
|
||||
* @log_entry_qualifier:
|
||||
*
|
||||
*/
|
||||
void
|
||||
mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event,
|
||||
u16 log_entry_qualifier)
|
||||
{
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
|
||||
struct SL_WH_EVENT_TRIGGER_T *event_trigger;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
u8 found_match;
|
||||
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
/* check to see if trace buffers are currently registered */
|
||||
if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check to see if trace buffers are currently released */
|
||||
if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_RELEASED) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter - "
|
||||
"event = 0x%04x, log_entry_qualifier = 0x%04x\n", ioc->name,
|
||||
__func__, event, log_entry_qualifier));
|
||||
|
||||
/* don't send trigger if an trigger is currently active */
|
||||
if (ioc->diag_trigger_active) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check for the trigger condition */
|
||||
event_trigger = ioc->diag_trigger_event.EventTriggerEntry;
|
||||
for (i = 0 , found_match = 0; i < ioc->diag_trigger_event.ValidEntries
|
||||
&& !found_match; i++, event_trigger++) {
|
||||
if (event_trigger->EventValue != event)
|
||||
continue;
|
||||
if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
|
||||
if (event_trigger->LogEntryQualifier ==
|
||||
log_entry_qualifier)
|
||||
found_match = 1;
|
||||
continue;
|
||||
}
|
||||
found_match = 1;
|
||||
ioc->diag_trigger_active = 1;
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: setting "
|
||||
"diag_trigger_active flag\n", ioc->name, __func__));
|
||||
}
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
if (!found_match)
|
||||
goto out;
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: setting "
|
||||
"diag_trigger_active flag\n", ioc->name, __func__));
|
||||
memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
|
||||
event_data.trigger_type = MPT3SAS_TRIGGER_EVENT;
|
||||
event_data.u.event.EventValue = event;
|
||||
event_data.u.event.LogEntryQualifier = log_entry_qualifier;
|
||||
mpt3sas_send_trigger_data_event(ioc, &event_data);
|
||||
out:
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: exit\n", ioc->name,
|
||||
__func__));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_trigger_scsi - SCSI trigger handler
|
||||
* @ioc: per adapter object
|
||||
* @sense_key:
|
||||
* @asc:
|
||||
* @ascq:
|
||||
*
|
||||
*/
|
||||
void
|
||||
mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, u8 asc,
|
||||
u8 ascq)
|
||||
{
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
|
||||
struct SL_WH_SCSI_TRIGGER_T *scsi_trigger;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
u8 found_match;
|
||||
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
/* check to see if trace buffers are currently registered */
|
||||
if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check to see if trace buffers are currently released */
|
||||
if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_RELEASED) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter - "
|
||||
"sense_key = 0x%02x, asc = 0x%02x, ascq = 0x%02x\n", ioc->name,
|
||||
__func__, sense_key, asc, ascq));
|
||||
|
||||
/* don't send trigger if an trigger is currently active */
|
||||
if (ioc->diag_trigger_active) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check for the trigger condition */
|
||||
scsi_trigger = ioc->diag_trigger_scsi.SCSITriggerEntry;
|
||||
for (i = 0 , found_match = 0; i < ioc->diag_trigger_scsi.ValidEntries
|
||||
&& !found_match; i++, scsi_trigger++) {
|
||||
if (scsi_trigger->SenseKey != sense_key)
|
||||
continue;
|
||||
if (!(scsi_trigger->ASC == 0xFF || scsi_trigger->ASC == asc))
|
||||
continue;
|
||||
if (!(scsi_trigger->ASCQ == 0xFF || scsi_trigger->ASCQ == ascq))
|
||||
continue;
|
||||
found_match = 1;
|
||||
ioc->diag_trigger_active = 1;
|
||||
}
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
if (!found_match)
|
||||
goto out;
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: setting "
|
||||
"diag_trigger_active flag\n", ioc->name, __func__));
|
||||
memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
|
||||
event_data.trigger_type = MPT3SAS_TRIGGER_SCSI;
|
||||
event_data.u.scsi.SenseKey = sense_key;
|
||||
event_data.u.scsi.ASC = asc;
|
||||
event_data.u.scsi.ASCQ = ascq;
|
||||
mpt3sas_send_trigger_data_event(ioc, &event_data);
|
||||
out:
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: exit\n", ioc->name,
|
||||
__func__));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_trigger_mpi - MPI trigger handler
|
||||
* @ioc: per adapter object
|
||||
* @ioc_status:
|
||||
* @loginfo:
|
||||
*
|
||||
*/
|
||||
void
|
||||
mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, u32 loginfo)
|
||||
{
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
|
||||
struct SL_WH_MPI_TRIGGER_T *mpi_trigger;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
u8 found_match;
|
||||
|
||||
spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
/* check to see if trace buffers are currently registered */
|
||||
if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check to see if trace buffers are currently released */
|
||||
if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
|
||||
MPT3_DIAG_BUFFER_IS_RELEASED) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: enter - "
|
||||
"ioc_status = 0x%04x, loginfo = 0x%08x\n", ioc->name, __func__,
|
||||
ioc_status, loginfo));
|
||||
|
||||
/* don't send trigger if an trigger is currently active */
|
||||
if (ioc->diag_trigger_active) {
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check for the trigger condition */
|
||||
mpi_trigger = ioc->diag_trigger_mpi.MPITriggerEntry;
|
||||
for (i = 0 , found_match = 0; i < ioc->diag_trigger_mpi.ValidEntries
|
||||
&& !found_match; i++, mpi_trigger++) {
|
||||
if (mpi_trigger->IOCStatus != ioc_status)
|
||||
continue;
|
||||
if (!(mpi_trigger->IocLogInfo == 0xFFFFFFFF ||
|
||||
mpi_trigger->IocLogInfo == loginfo))
|
||||
continue;
|
||||
found_match = 1;
|
||||
ioc->diag_trigger_active = 1;
|
||||
}
|
||||
spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
|
||||
|
||||
if (!found_match)
|
||||
goto out;
|
||||
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: setting "
|
||||
"diag_trigger_active flag\n", ioc->name, __func__));
|
||||
memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
|
||||
event_data.trigger_type = MPT3SAS_TRIGGER_MPI;
|
||||
event_data.u.mpi.IOCStatus = ioc_status;
|
||||
event_data.u.mpi.IocLogInfo = loginfo;
|
||||
mpt3sas_send_trigger_data_event(ioc, &event_data);
|
||||
out:
|
||||
dTriggerDiagPrintk(ioc, printk(MPT3SAS_INFO_FMT "%s: exit\n", ioc->name,
|
||||
__func__));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,195 +1,195 @@
|
|||
/*
|
||||
* This is the Fusion MPT base driver providing common API layer interface
|
||||
* to set Diagnostic triggers for MPT (Message Passing Technology) based
|
||||
* controllers
|
||||
*
|
||||
* This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h
|
||||
* Copyright (C) 2013-2018 LSI Corporation
|
||||
* Copyright (C) 2013-2018 Avago Technologies
|
||||
* Copyright (C) 2013-2018 Broadcom Inc.
|
||||
* (mailto:MPT-FusionLinux.pdl@broadcom.com)
|
||||
*
|
||||
* 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 the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
|
||||
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
|
||||
* solely responsible for determining the appropriateness of using and
|
||||
* distributing the Program and assumes all risks associated with its
|
||||
* exercise of rights under this Agreement, including but not limited to
|
||||
* the risks and costs of program errors, damage to or loss of data,
|
||||
* programs or equipment, and unavailability or interruption of operations.
|
||||
|
||||
* DISCLAIMER OF LIABILITY
|
||||
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
/* Diagnostic Trigger Configuration Data Structures */
|
||||
|
||||
#ifndef MPT3SAS_TRIGGER_DIAG_H_INCLUDED
|
||||
#define MPT3SAS_TRIGGER_DIAG_H_INCLUDED
|
||||
|
||||
/* limitation on number of entries */
|
||||
#define NUM_VALID_ENTRIES (20)
|
||||
|
||||
/* trigger types */
|
||||
#define MPT3SAS_TRIGGER_MASTER (1)
|
||||
#define MPT3SAS_TRIGGER_EVENT (2)
|
||||
#define MPT3SAS_TRIGGER_SCSI (3)
|
||||
#define MPT3SAS_TRIGGER_MPI (4)
|
||||
|
||||
/* trigger names */
|
||||
#define MASTER_TRIGGER_FILE_NAME "diag_trigger_master"
|
||||
#define EVENT_TRIGGERS_FILE_NAME "diag_trigger_event"
|
||||
#define SCSI_TRIGGERS_FILE_NAME "diag_trigger_scsi"
|
||||
#define MPI_TRIGGER_FILE_NAME "diag_trigger_mpi"
|
||||
|
||||
/* master trigger bitmask */
|
||||
#define MASTER_TRIGGER_FW_FAULT (0x00000001)
|
||||
#define MASTER_TRIGGER_ADAPTER_RESET (0x00000002)
|
||||
#define MASTER_TRIGGER_TASK_MANAGMENT (0x00000004)
|
||||
#define MASTER_TRIGGER_DEVICE_REMOVAL (0x00000008)
|
||||
|
||||
/* fake firmware event for tigger */
|
||||
#define MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED (0x6E)
|
||||
|
||||
/**
|
||||
* MasterTrigger is a single U32 passed to/from sysfs.
|
||||
*
|
||||
* Bit Flags (enables) include:
|
||||
* 1. FW Faults
|
||||
* 2. Adapter Reset issued by driver
|
||||
* 3. TMs
|
||||
* 4. Device Remove Event sent by FW
|
||||
*/
|
||||
|
||||
struct SL_WH_MASTER_TRIGGER_T {
|
||||
uint32_t MasterData;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_EVENT_TRIGGER_T - Definition of an event trigger element
|
||||
* @EventValue: Event Code to trigger on
|
||||
* @LogEntryQualifier: Type of FW event that logged (Log Entry Added Event only)
|
||||
*
|
||||
* Defines an event that should induce a DIAG_TRIGGER driver event if observed.
|
||||
*/
|
||||
struct SL_WH_EVENT_TRIGGER_T {
|
||||
uint16_t EventValue;
|
||||
uint16_t LogEntryQualifier;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_EVENT_TRIGGERS_T - Structure passed to/from sysfs containing a
|
||||
* list of Event Triggers to be monitored for.
|
||||
* @ValidEntries: Number of _SL_WH_EVENT_TRIGGER_T structures contained in this
|
||||
* structure.
|
||||
* @EventTriggerEntry: List of Event trigger elements.
|
||||
*
|
||||
* This binary structure is transferred via sysfs to get/set Event Triggers
|
||||
* in the Linux Driver.
|
||||
*/
|
||||
|
||||
struct SL_WH_EVENT_TRIGGERS_T {
|
||||
uint32_t ValidEntries;
|
||||
struct SL_WH_EVENT_TRIGGER_T EventTriggerEntry[NUM_VALID_ENTRIES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_SCSI_TRIGGER_T - Definition of a SCSI trigger element
|
||||
* @ASCQ: Additional Sense Code Qualifier. Can be specific or 0xFF for
|
||||
* wildcard.
|
||||
* @ASC: Additional Sense Code. Can be specific or 0xFF for wildcard
|
||||
* @SenseKey: SCSI Sense Key
|
||||
*
|
||||
* Defines a sense key (single or many variants) that should induce a
|
||||
* DIAG_TRIGGER driver event if observed.
|
||||
*/
|
||||
struct SL_WH_SCSI_TRIGGER_T {
|
||||
U8 ASCQ;
|
||||
U8 ASC;
|
||||
U8 SenseKey;
|
||||
U8 Reserved;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_SCSI_TRIGGERS_T - Structure passed to/from sysfs containing a
|
||||
* list of SCSI sense codes that should trigger a DIAG_SERVICE event when
|
||||
* observed.
|
||||
* @ValidEntries: Number of _SL_WH_SCSI_TRIGGER_T structures contained in this
|
||||
* structure.
|
||||
* @SCSITriggerEntry: List of SCSI Sense Code trigger elements.
|
||||
*
|
||||
* This binary structure is transferred via sysfs to get/set SCSI Sense Code
|
||||
* Triggers in the Linux Driver.
|
||||
*/
|
||||
struct SL_WH_SCSI_TRIGGERS_T {
|
||||
uint32_t ValidEntries;
|
||||
struct SL_WH_SCSI_TRIGGER_T SCSITriggerEntry[NUM_VALID_ENTRIES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_MPI_TRIGGER_T - Definition of an MPI trigger element
|
||||
* @IOCStatus: MPI IOCStatus
|
||||
* @IocLogInfo: MPI IocLogInfo. Can be specific or 0xFFFFFFFF for wildcard
|
||||
*
|
||||
* Defines a MPI IOCStatus/IocLogInfo pair that should induce a DIAG_TRIGGER
|
||||
* driver event if observed.
|
||||
*/
|
||||
struct SL_WH_MPI_TRIGGER_T {
|
||||
uint16_t IOCStatus;
|
||||
uint16_t Reserved;
|
||||
uint32_t IocLogInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_MPI_TRIGGERS_T - Structure passed to/from sysfs containing a
|
||||
* list of MPI IOCStatus/IocLogInfo pairs that should trigger a DIAG_SERVICE
|
||||
* event when observed.
|
||||
* @ValidEntries: Number of _SL_WH_MPI_TRIGGER_T structures contained in this
|
||||
* structure.
|
||||
* @MPITriggerEntry: List of MPI IOCStatus/IocLogInfo trigger elements.
|
||||
*
|
||||
* This binary structure is transferred via sysfs to get/set MPI Error Triggers
|
||||
* in the Linux Driver.
|
||||
*/
|
||||
struct SL_WH_MPI_TRIGGERS_T {
|
||||
uint32_t ValidEntries;
|
||||
struct SL_WH_MPI_TRIGGER_T MPITriggerEntry[NUM_VALID_ENTRIES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_TRIGGERS_EVENT_DATA_T - event data for trigger
|
||||
* @trigger_type: trigger type (see MPT3SAS_TRIGGER_XXXX)
|
||||
* @u: trigger condition that caused trigger to be sent
|
||||
*/
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T {
|
||||
uint32_t trigger_type;
|
||||
union {
|
||||
struct SL_WH_MASTER_TRIGGER_T master;
|
||||
struct SL_WH_EVENT_TRIGGER_T event;
|
||||
struct SL_WH_SCSI_TRIGGER_T scsi;
|
||||
struct SL_WH_MPI_TRIGGER_T mpi;
|
||||
} u;
|
||||
};
|
||||
#endif /* MPT3SAS_TRIGGER_DIAG_H_INCLUDED */
|
||||
/*
|
||||
* This is the Fusion MPT base driver providing common API layer interface
|
||||
* to set Diagnostic triggers for MPT (Message Passing Technology) based
|
||||
* controllers
|
||||
*
|
||||
* This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h
|
||||
* Copyright (C) 2013-2018 LSI Corporation
|
||||
* Copyright (C) 2013-2018 Avago Technologies
|
||||
* Copyright (C) 2013-2018 Broadcom Inc.
|
||||
* (mailto:MPT-FusionLinux.pdl@broadcom.com)
|
||||
*
|
||||
* 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 the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
|
||||
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
|
||||
* solely responsible for determining the appropriateness of using and
|
||||
* distributing the Program and assumes all risks associated with its
|
||||
* exercise of rights under this Agreement, including but not limited to
|
||||
* the risks and costs of program errors, damage to or loss of data,
|
||||
* programs or equipment, and unavailability or interruption of operations.
|
||||
|
||||
* DISCLAIMER OF LIABILITY
|
||||
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
/* Diagnostic Trigger Configuration Data Structures */
|
||||
|
||||
#ifndef MPT3SAS_TRIGGER_DIAG_H_INCLUDED
|
||||
#define MPT3SAS_TRIGGER_DIAG_H_INCLUDED
|
||||
|
||||
/* limitation on number of entries */
|
||||
#define NUM_VALID_ENTRIES (20)
|
||||
|
||||
/* trigger types */
|
||||
#define MPT3SAS_TRIGGER_MASTER (1)
|
||||
#define MPT3SAS_TRIGGER_EVENT (2)
|
||||
#define MPT3SAS_TRIGGER_SCSI (3)
|
||||
#define MPT3SAS_TRIGGER_MPI (4)
|
||||
|
||||
/* trigger names */
|
||||
#define MASTER_TRIGGER_FILE_NAME "diag_trigger_master"
|
||||
#define EVENT_TRIGGERS_FILE_NAME "diag_trigger_event"
|
||||
#define SCSI_TRIGGERS_FILE_NAME "diag_trigger_scsi"
|
||||
#define MPI_TRIGGER_FILE_NAME "diag_trigger_mpi"
|
||||
|
||||
/* master trigger bitmask */
|
||||
#define MASTER_TRIGGER_FW_FAULT (0x00000001)
|
||||
#define MASTER_TRIGGER_ADAPTER_RESET (0x00000002)
|
||||
#define MASTER_TRIGGER_TASK_MANAGMENT (0x00000004)
|
||||
#define MASTER_TRIGGER_DEVICE_REMOVAL (0x00000008)
|
||||
|
||||
/* fake firmware event for tigger */
|
||||
#define MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED (0x6E)
|
||||
|
||||
/**
|
||||
* MasterTrigger is a single U32 passed to/from sysfs.
|
||||
*
|
||||
* Bit Flags (enables) include:
|
||||
* 1. FW Faults
|
||||
* 2. Adapter Reset issued by driver
|
||||
* 3. TMs
|
||||
* 4. Device Remove Event sent by FW
|
||||
*/
|
||||
|
||||
struct SL_WH_MASTER_TRIGGER_T {
|
||||
uint32_t MasterData;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_EVENT_TRIGGER_T - Definition of an event trigger element
|
||||
* @EventValue: Event Code to trigger on
|
||||
* @LogEntryQualifier: Type of FW event that logged (Log Entry Added Event only)
|
||||
*
|
||||
* Defines an event that should induce a DIAG_TRIGGER driver event if observed.
|
||||
*/
|
||||
struct SL_WH_EVENT_TRIGGER_T {
|
||||
uint16_t EventValue;
|
||||
uint16_t LogEntryQualifier;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_EVENT_TRIGGERS_T - Structure passed to/from sysfs containing a
|
||||
* list of Event Triggers to be monitored for.
|
||||
* @ValidEntries: Number of _SL_WH_EVENT_TRIGGER_T structures contained in this
|
||||
* structure.
|
||||
* @EventTriggerEntry: List of Event trigger elements.
|
||||
*
|
||||
* This binary structure is transferred via sysfs to get/set Event Triggers
|
||||
* in the Linux Driver.
|
||||
*/
|
||||
|
||||
struct SL_WH_EVENT_TRIGGERS_T {
|
||||
uint32_t ValidEntries;
|
||||
struct SL_WH_EVENT_TRIGGER_T EventTriggerEntry[NUM_VALID_ENTRIES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_SCSI_TRIGGER_T - Definition of a SCSI trigger element
|
||||
* @ASCQ: Additional Sense Code Qualifier. Can be specific or 0xFF for
|
||||
* wildcard.
|
||||
* @ASC: Additional Sense Code. Can be specific or 0xFF for wildcard
|
||||
* @SenseKey: SCSI Sense Key
|
||||
*
|
||||
* Defines a sense key (single or many variants) that should induce a
|
||||
* DIAG_TRIGGER driver event if observed.
|
||||
*/
|
||||
struct SL_WH_SCSI_TRIGGER_T {
|
||||
U8 ASCQ;
|
||||
U8 ASC;
|
||||
U8 SenseKey;
|
||||
U8 Reserved;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_SCSI_TRIGGERS_T - Structure passed to/from sysfs containing a
|
||||
* list of SCSI sense codes that should trigger a DIAG_SERVICE event when
|
||||
* observed.
|
||||
* @ValidEntries: Number of _SL_WH_SCSI_TRIGGER_T structures contained in this
|
||||
* structure.
|
||||
* @SCSITriggerEntry: List of SCSI Sense Code trigger elements.
|
||||
*
|
||||
* This binary structure is transferred via sysfs to get/set SCSI Sense Code
|
||||
* Triggers in the Linux Driver.
|
||||
*/
|
||||
struct SL_WH_SCSI_TRIGGERS_T {
|
||||
uint32_t ValidEntries;
|
||||
struct SL_WH_SCSI_TRIGGER_T SCSITriggerEntry[NUM_VALID_ENTRIES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_MPI_TRIGGER_T - Definition of an MPI trigger element
|
||||
* @IOCStatus: MPI IOCStatus
|
||||
* @IocLogInfo: MPI IocLogInfo. Can be specific or 0xFFFFFFFF for wildcard
|
||||
*
|
||||
* Defines a MPI IOCStatus/IocLogInfo pair that should induce a DIAG_TRIGGER
|
||||
* driver event if observed.
|
||||
*/
|
||||
struct SL_WH_MPI_TRIGGER_T {
|
||||
uint16_t IOCStatus;
|
||||
uint16_t Reserved;
|
||||
uint32_t IocLogInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_MPI_TRIGGERS_T - Structure passed to/from sysfs containing a
|
||||
* list of MPI IOCStatus/IocLogInfo pairs that should trigger a DIAG_SERVICE
|
||||
* event when observed.
|
||||
* @ValidEntries: Number of _SL_WH_MPI_TRIGGER_T structures contained in this
|
||||
* structure.
|
||||
* @MPITriggerEntry: List of MPI IOCStatus/IocLogInfo trigger elements.
|
||||
*
|
||||
* This binary structure is transferred via sysfs to get/set MPI Error Triggers
|
||||
* in the Linux Driver.
|
||||
*/
|
||||
struct SL_WH_MPI_TRIGGERS_T {
|
||||
uint32_t ValidEntries;
|
||||
struct SL_WH_MPI_TRIGGER_T MPITriggerEntry[NUM_VALID_ENTRIES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SL_WH_TRIGGERS_EVENT_DATA_T - event data for trigger
|
||||
* @trigger_type: trigger type (see MPT3SAS_TRIGGER_XXXX)
|
||||
* @u: trigger condition that caused trigger to be sent
|
||||
*/
|
||||
struct SL_WH_TRIGGERS_EVENT_DATA_T {
|
||||
uint32_t trigger_type;
|
||||
union {
|
||||
struct SL_WH_MASTER_TRIGGER_T master;
|
||||
struct SL_WH_EVENT_TRIGGER_T event;
|
||||
struct SL_WH_SCSI_TRIGGER_T scsi;
|
||||
struct SL_WH_MPI_TRIGGER_T mpi;
|
||||
} u;
|
||||
};
|
||||
#endif /* MPT3SAS_TRIGGER_DIAG_H_INCLUDED */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,157 @@
|
|||
|
||||
/*
|
||||
* This is the Fusion MPT base driver providing common API layer interface
|
||||
* to store diag trigger values into persistent driver triggers pages
|
||||
* for MPT (Message Passing Technology) based
|
||||
* controllers
|
||||
*
|
||||
* This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h
|
||||
* Copyright (C) 2013-2020 LSI Corporation
|
||||
* Copyright (C) 2013-2020 Avago Technologies
|
||||
* Copyright (C) 2013-2020 Broadcom Inc.
|
||||
* (mailto:MPT-FusionLinux.pdl@broadcom.com)
|
||||
*
|
||||
* 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 the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
|
||||
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
|
||||
* solely responsible for determining the appropriateness of using and
|
||||
* distributing the Program and assumes all risks associated with its
|
||||
* exercise of rights under this Agreement, including but not limited to
|
||||
* the risks and costs of program errors, damage to or loss of data,
|
||||
* programs or equipment, and unavailability or interruption of operations.
|
||||
|
||||
* DISCLAIMER OF LIABILITY
|
||||
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "mpi/mpi2_cnfg.h"
|
||||
|
||||
#ifndef MPI2_TRIGGER_PAGES_H
|
||||
#define MPI2_TRIGGER_PAGES_H
|
||||
|
||||
#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER (0xE0)
|
||||
|
||||
#define MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION (0x01)
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_0
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 TriggerFlags; /* 0x08 */
|
||||
U16 Reserved0xA; /* 0x0A */
|
||||
U32 Reserved0xC[61]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_0,
|
||||
MPI2_POINTER PTR_MPI26_CONFIG_PAGE_DRIVER_TIGGER_0,
|
||||
Mpi26DriverTriggerPage0_t, MPI2_POINTER pMpi26DriverTriggerPage0_t;
|
||||
|
||||
/* Trigger Flags */
|
||||
#define MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID (0x0001)
|
||||
#define MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID (0x0002)
|
||||
#define MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID (0x0004)
|
||||
#define MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID (0x0008)
|
||||
|
||||
|
||||
#define MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION (0x01)
|
||||
typedef struct _MPI26_DRIVER_MASTER_TIGGER_ENTRY
|
||||
{
|
||||
U32 MasterTriggerFlags;
|
||||
} MPI26_DRIVER_MASTER_TIGGER_ENTRY, MPI2_POINTER PTR_MPI26_DRIVER_MASTER_TIGGER_ENTRY;
|
||||
|
||||
#define MPI26_MAX_MASTER_TRIGGERS (1)
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_1
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 NumMasterTrigger; /* 0x08 */
|
||||
U16 Reserved0xA; /* 0x0A */
|
||||
MPI26_DRIVER_MASTER_TIGGER_ENTRY MasterTriggers[MPI26_MAX_MASTER_TRIGGERS]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_1,
|
||||
MPI2_POINTER PTR_MPI26_CONFIG_PAGE_DRIVER_TIGGER_1,
|
||||
Mpi26DriverTriggerPage1_t, MPI2_POINTER pMpi26DriverTriggerPage1_t;
|
||||
|
||||
/* Master Trigger Flags */
|
||||
#define MPI26_DRIVER_TRIGGER1_FLAG_FW_FAULT (0x00000001)
|
||||
#define MPI26_DRIVER_TRIGGER1_FLAG_DIAG_RESET (0x00000002)
|
||||
#define MPI26_DRIVER_TRIGGER1_FLAG_TASK_MGMT (0x00000004)
|
||||
#define MPI26_DRIVER_TRIGGER1_FLAG_DEVICE_REMOVAL (0x00000008)
|
||||
|
||||
|
||||
#define MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION (0x01)
|
||||
typedef struct _MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY
|
||||
{
|
||||
U16 MPIEventCode; /* 0x00 */
|
||||
U16 MPIEventCodeSpecific; /* 0x02 */
|
||||
} MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY, MPI2_POINTER PTR_MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY;
|
||||
|
||||
#define MPI26_MAX_MPI_EVENT_TRIGGERS (20)
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_2
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 NumMPIEventTrigger; /* 0x08 */
|
||||
U16 Reserved0xA; /* 0x0A */
|
||||
MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY MPIEventTriggers[MPI26_MAX_MPI_EVENT_TRIGGERS]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_2,
|
||||
MPI2_POINTER PTR_MPI26_CONFIG_PAGE_DRIVER_TIGGER_2,
|
||||
Mpi26DriverTriggerPage2_t, MPI2_POINTER pMpi26DriverTriggerPage2_t;
|
||||
|
||||
|
||||
#define MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION (0x01)
|
||||
typedef struct _MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY
|
||||
{
|
||||
U8 ASCQ; /* 0x00 */
|
||||
U8 ASC; /* 0x01 */
|
||||
U8 SenseKey; /* 0x02 */
|
||||
U8 Reserved; /* 0x03 */
|
||||
} MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY, MPI2_POINTER PTR_MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY;
|
||||
|
||||
#define MPI26_MAX_SCSI_SENSE_TRIGGERS (20)
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_3
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 NumSCSISenseTrigger; /* 0x08 */
|
||||
U16 Reserved0xA; /* 0x0A */
|
||||
MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY SCSISenseTriggers[MPI26_MAX_SCSI_SENSE_TRIGGERS]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_3,
|
||||
MPI2_POINTER PTR_MPI26_CONFIG_PAGE_DRIVER_TIGGER_3,
|
||||
Mpi26DriverTriggerPage3_t, MPI2_POINTER pMpi26DriverTriggerPage3_t;
|
||||
|
||||
#define MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION (0x01)
|
||||
typedef struct _MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY
|
||||
{
|
||||
U16 IOCStatus; /* 0x00 */
|
||||
U16 Reserved; /* 0x02 */
|
||||
U32 LogInfo; /* 0x04 */
|
||||
} MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY, MPI2_POINTER PTR_MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY;
|
||||
|
||||
#define MPI26_MAX_LOGINFO_TRIGGERS (20)
|
||||
typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_4
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 NumIOCStatusLogInfoTrigger; /* 0x08 */
|
||||
U16 Reserved0xA; /* 0x0A */
|
||||
MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY IOCStatusLoginfoTriggers[MPI26_MAX_LOGINFO_TRIGGERS]; /* 0x0C */
|
||||
} MPI26_CONFIG_PAGE_DRIVER_TIGGER_4,
|
||||
MPI2_POINTER PTR_MPI26_CONFIG_PAGE_DRIVER_TIGGER_4,
|
||||
Mpi26DriverTriggerPage4_t, MPI2_POINTER pMpi26DriverTriggerPage4_t;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# DISCLAIMER OF LIABILITY
|
||||
# THIS IS SAMPLE SCRIPT.
|
||||
# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
# USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
|
||||
|
||||
clear
|
||||
CWD=`pwd`;
|
||||
scsi_host="/sys/class/scsi_host"
|
||||
cd ${scsi_host}
|
||||
subfolders=`ls -1`
|
||||
for i in ${subfolders}; do
|
||||
cd ${i};
|
||||
if [ `cat proc_name` == "mpt3sas" ]; then
|
||||
reset_count=`cat ioc_reset_count`
|
||||
{
|
||||
while true; do
|
||||
if [[ `cat /sys/kernel/debug/mpt3sas/scsi_${i}/host_recovery` == 1 && `cat ioc_reset_count` == $reset_count ]]; then
|
||||
date_str=$(date +'%y-%m-%d-%H-%M-%S')
|
||||
file_name=${i}-iocdump-${date_str};
|
||||
echo "==== host reset on ${i} is observed at ${date_str}, hence copied the ioc dump to file ${file_name} ===="
|
||||
cat /sys/kernel/debug/mpt3sas/scsi_${i}/ioc_dump > ${CWD}/$file_name;
|
||||
reset_count=`expr $reset_count + 1`;
|
||||
fi;
|
||||
sleep 1;
|
||||
done;
|
||||
} &
|
||||
fi;
|
||||
cd ${scsi_host}
|
||||
done;
|
||||
|
||||
while true; do sleep 300; done
|
||||
|
||||
echo -e \\n
|
||||
|
|
@ -3293,7 +3293,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
|
|||
}
|
||||
|
||||
blk_pm_runtime_init(sdp->request_queue, dev);
|
||||
device_add_disk(dev, gd);
|
||||
device_add_disk(dev, gd, NULL);
|
||||
if (sdkp->capacity)
|
||||
sd_dif_config_host(sdkp);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
ccflags-y += -I.
|
||||
obj-$(CONFIG_SCSI_SMARTPQI) += smartpqi.o
|
||||
smartpqi-objs := smartpqi_init.o smartpqi_sis.o smartpqi_sas_transport.o
|
||||
smartpqi-objs := smartpqi_init.o smartpqi_sis.o smartpqi_sas_transport.o smartpqi_kernel_compat.o
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* driver for Microsemi PQI-based storage controllers
|
||||
* Copyright (c) 2016-2017 Microsemi Corporation
|
||||
* driver for Microchip PQI-based storage controllers
|
||||
* Copyright (c) 2019-2021 Microchip Technology Inc. and its subsidiaries
|
||||
* Copyright (c) 2016-2018 Microsemi Corporation
|
||||
* Copyright (c) 2016 PMC-Sierra, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -12,15 +13,18 @@
|
|||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more details.
|
||||
*
|
||||
* Questions/Comments/Bugfixes to esc.storagedev@microsemi.com
|
||||
* Questions/Comments/Bugfixes to storagedev@microchip.com
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/io-64-nonatomic-lo-hi.h>
|
||||
|
||||
#if !defined(_SMARTPQI_H)
|
||||
#define _SMARTPQI_H
|
||||
|
||||
#define TORTUGA 0
|
||||
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <linux/bsg-lib.h>
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
#define PQI_DEVICE_SIGNATURE "PQI DREG"
|
||||
|
|
@ -63,7 +67,7 @@ struct pqi_device_registers {
|
|||
/*
|
||||
* controller registers
|
||||
*
|
||||
* These are defined by the Microsemi implementation.
|
||||
* These are defined by the Microchip implementation.
|
||||
*
|
||||
* Some registers (those named sis_*) are only used when in
|
||||
* legacy SIS mode before we transition the controller into
|
||||
|
|
@ -83,7 +87,8 @@ struct pqi_ctrl_registers {
|
|||
__le32 sis_ctrl_to_host_doorbell_clear; /* A0h */
|
||||
u8 reserved4[0xb0 - (0xa0 + sizeof(__le32))];
|
||||
__le32 sis_driver_scratch; /* B0h */
|
||||
u8 reserved5[0xbc - (0xb0 + sizeof(__le32))];
|
||||
__le32 sis_product_identifier; /* B4h */
|
||||
u8 reserved5[0xbc - (0xb4 + sizeof(__le32))];
|
||||
__le32 sis_firmware_status; /* BCh */
|
||||
u8 reserved6[0x1000 - (0xbc + sizeof(__le32))];
|
||||
__le32 sis_mailbox[8]; /* 1000h */
|
||||
|
|
@ -97,6 +102,12 @@ struct pqi_ctrl_registers {
|
|||
struct pqi_device_registers pqi_registers; /* 4000h */
|
||||
};
|
||||
|
||||
#if ((HZ) < 1000)
|
||||
#define PQI_HZ 1000
|
||||
#else
|
||||
#define PQI_HZ (HZ)
|
||||
#endif
|
||||
|
||||
#define PQI_DEVICE_REGISTERS_OFFSET 0x4000
|
||||
|
||||
enum pqi_io_path {
|
||||
|
|
@ -126,10 +137,13 @@ struct pqi_iu_header {
|
|||
__le16 iu_length; /* in bytes - does not include the length */
|
||||
/* of this header */
|
||||
__le16 response_queue_id; /* specifies the OQ where the */
|
||||
/* response IU is to be delivered */
|
||||
u8 work_area[2]; /* reserved for driver use */
|
||||
/* response IU is to be delivered */
|
||||
u16 driver_flags; /* reserved for driver use */
|
||||
};
|
||||
|
||||
/* manifest constants for pqi_iu_header.driver_flags */
|
||||
#define PQI_DRIVER_NONBLOCKABLE_REQUEST 0x1
|
||||
|
||||
/*
|
||||
* According to the PQI spec, the IU header is only the first 4 bytes of our
|
||||
* pqi_iu_header structure.
|
||||
|
|
@ -254,6 +268,7 @@ struct pqi_device_capability {
|
|||
};
|
||||
|
||||
#define PQI_MAX_EMBEDDED_SG_DESCRIPTORS 4
|
||||
#define PQI_MAX_EMBEDDED_R56_SG_DESCRIPTORS 3
|
||||
|
||||
struct pqi_raid_path_request {
|
||||
struct pqi_iu_header header;
|
||||
|
|
@ -274,9 +289,10 @@ struct pqi_raid_path_request {
|
|||
u8 reserved4 : 2;
|
||||
u8 additional_cdb_bytes_usage : 3;
|
||||
u8 reserved5 : 3;
|
||||
u8 cdb[32];
|
||||
struct pqi_sg_descriptor
|
||||
sg_descriptors[PQI_MAX_EMBEDDED_SG_DESCRIPTORS];
|
||||
u8 cdb[16];
|
||||
u8 reserved6[12];
|
||||
__le32 timeout;
|
||||
struct pqi_sg_descriptor sg_descriptors[PQI_MAX_EMBEDDED_SG_DESCRIPTORS];
|
||||
};
|
||||
|
||||
struct pqi_aio_path_request {
|
||||
|
|
@ -303,8 +319,73 @@ struct pqi_aio_path_request {
|
|||
u8 cdb_length;
|
||||
u8 lun_number[8];
|
||||
u8 reserved4[4];
|
||||
struct pqi_sg_descriptor
|
||||
sg_descriptors[PQI_MAX_EMBEDDED_SG_DESCRIPTORS];
|
||||
struct pqi_sg_descriptor sg_descriptors[PQI_MAX_EMBEDDED_SG_DESCRIPTORS];
|
||||
};
|
||||
|
||||
#define PQI_RAID1_NVME_XFER_LIMIT (32 * 1024) /* 32 KiB */
|
||||
|
||||
struct pqi_aio_r1_path_request {
|
||||
struct pqi_iu_header header;
|
||||
__le16 request_id;
|
||||
__le16 volume_id; /* ID of the RAID volume */
|
||||
__le32 it_nexus_1; /* IT nexus of the 1st drive in the RAID volume */
|
||||
__le32 it_nexus_2; /* IT nexus of the 2nd drive in the RAID volume */
|
||||
__le32 it_nexus_3; /* IT nexus of the 3rd drive in the RAID volume */
|
||||
__le32 data_length; /* total bytes to read/write */
|
||||
u8 data_direction : 2;
|
||||
u8 partial : 1;
|
||||
u8 memory_type : 1;
|
||||
u8 fence : 1;
|
||||
u8 encryption_enable : 1;
|
||||
u8 reserved : 2;
|
||||
u8 task_attribute : 3;
|
||||
u8 command_priority : 4;
|
||||
u8 reserved2 : 1;
|
||||
__le16 data_encryption_key_index;
|
||||
u8 cdb[16];
|
||||
__le16 error_index;
|
||||
u8 num_sg_descriptors;
|
||||
u8 cdb_length;
|
||||
u8 num_drives; /* number of drives in the RAID volume (2 or 3) */
|
||||
u8 reserved3[3];
|
||||
__le32 encrypt_tweak_lower;
|
||||
__le32 encrypt_tweak_upper;
|
||||
struct pqi_sg_descriptor sg_descriptors[PQI_MAX_EMBEDDED_SG_DESCRIPTORS];
|
||||
};
|
||||
|
||||
#define PQI_DEFAULT_MAX_WRITE_RAID_5_6 (8 * 1024U)
|
||||
#define PQI_DEFAULT_MAX_TRANSFER_ENCRYPTED_SAS_SATA (~0U)
|
||||
#define PQI_DEFAULT_MAX_TRANSFER_ENCRYPTED_NVME (32 * 1024U)
|
||||
|
||||
struct pqi_aio_r56_path_request {
|
||||
struct pqi_iu_header header;
|
||||
__le16 request_id;
|
||||
__le16 volume_id; /* ID of the RAID volume */
|
||||
__le32 data_it_nexus; /* IT nexus for the data drive */
|
||||
__le32 p_parity_it_nexus; /* IT nexus for the P parity drive */
|
||||
__le32 q_parity_it_nexus; /* IT nexus for the Q parity drive */
|
||||
__le32 data_length; /* total bytes to read/write */
|
||||
u8 data_direction : 2;
|
||||
u8 partial : 1;
|
||||
u8 mem_type : 1; /* 0 = PCIe, 1 = DDR */
|
||||
u8 fence : 1;
|
||||
u8 encryption_enable : 1;
|
||||
u8 reserved : 2;
|
||||
u8 task_attribute : 3;
|
||||
u8 command_priority : 4;
|
||||
u8 reserved1 : 1;
|
||||
__le16 data_encryption_key_index;
|
||||
u8 cdb[16];
|
||||
__le16 error_index;
|
||||
u8 num_sg_descriptors;
|
||||
u8 cdb_length;
|
||||
u8 xor_multiplier;
|
||||
u8 reserved2[3];
|
||||
__le32 encrypt_tweak_lower;
|
||||
__le32 encrypt_tweak_upper;
|
||||
__le64 row; /* row = logical LBA/blocks per row */
|
||||
u8 reserved3[8];
|
||||
struct pqi_sg_descriptor sg_descriptors[PQI_MAX_EMBEDDED_R56_SG_DESCRIPTORS];
|
||||
};
|
||||
|
||||
struct pqi_io_response {
|
||||
|
|
@ -347,14 +428,28 @@ struct pqi_event_config {
|
|||
|
||||
#define PQI_MAX_EVENT_DESCRIPTORS 255
|
||||
|
||||
#define PQI_EVENT_OFA_MEMORY_ALLOCATION 0x0
|
||||
#define PQI_EVENT_OFA_QUIESCE 0x1
|
||||
#define PQI_EVENT_OFA_CANCELED 0x2
|
||||
|
||||
struct pqi_event_response {
|
||||
struct pqi_iu_header header;
|
||||
u8 event_type;
|
||||
u8 reserved2 : 7;
|
||||
u8 request_acknowlege : 1;
|
||||
u8 request_acknowledge : 1;
|
||||
__le16 event_id;
|
||||
__le32 additional_event_id;
|
||||
u8 data[16];
|
||||
union {
|
||||
struct {
|
||||
__le32 bytes_requested;
|
||||
u8 reserved[12];
|
||||
} ofa_memory_allocation;
|
||||
|
||||
struct {
|
||||
__le16 reason; /* reason for cancellation */
|
||||
u8 reserved[14];
|
||||
} ofa_cancelled;
|
||||
} data;
|
||||
};
|
||||
|
||||
struct pqi_event_acknowledge_request {
|
||||
|
|
@ -369,7 +464,8 @@ struct pqi_task_management_request {
|
|||
struct pqi_iu_header header;
|
||||
__le16 request_id;
|
||||
__le16 nexus_id;
|
||||
u8 reserved[4];
|
||||
u8 reserved[2];
|
||||
__le16 timeout;
|
||||
u8 lun_number[8];
|
||||
__le16 protocol_specific;
|
||||
__le16 outbound_queue_id_to_manage;
|
||||
|
|
@ -389,6 +485,50 @@ struct pqi_task_management_response {
|
|||
u8 response_code;
|
||||
};
|
||||
|
||||
struct pqi_vendor_general_request {
|
||||
struct pqi_iu_header header;
|
||||
__le16 request_id;
|
||||
__le16 function_code;
|
||||
union {
|
||||
struct {
|
||||
__le16 first_section;
|
||||
__le16 last_section;
|
||||
u8 reserved[48];
|
||||
} config_table_update;
|
||||
|
||||
struct {
|
||||
__le64 buffer_address;
|
||||
__le32 buffer_length;
|
||||
u8 reserved[40];
|
||||
} ofa_memory_allocation;
|
||||
} data;
|
||||
};
|
||||
|
||||
struct pqi_vendor_general_response {
|
||||
struct pqi_iu_header header;
|
||||
__le16 request_id;
|
||||
__le16 function_code;
|
||||
__le16 status;
|
||||
u8 reserved[2];
|
||||
};
|
||||
|
||||
#define PQI_VENDOR_GENERAL_CONFIG_TABLE_UPDATE 0
|
||||
#define PQI_VENDOR_GENERAL_HOST_MEMORY_UPDATE 1
|
||||
|
||||
#define PQI_OFA_VERSION 1
|
||||
#define PQI_OFA_SIGNATURE "OFA_QRM"
|
||||
#define PQI_OFA_MAX_SG_DESCRIPTORS 64
|
||||
|
||||
struct pqi_ofa_memory {
|
||||
__le64 signature; /* "OFA_QRM" */
|
||||
__le16 version; /* version of this struct (1 = 1st version) */
|
||||
u8 reserved[62];
|
||||
__le32 bytes_allocated; /* total allocated memory in bytes */
|
||||
__le16 num_memory_descriptors;
|
||||
u8 reserved1[2];
|
||||
struct pqi_sg_descriptor sg_descriptor[PQI_OFA_MAX_SG_DESCRIPTORS];
|
||||
};
|
||||
|
||||
struct pqi_aio_error_info {
|
||||
u8 status;
|
||||
u8 service_response;
|
||||
|
|
@ -416,9 +556,13 @@ struct pqi_raid_error_info {
|
|||
#define PQI_REQUEST_IU_TASK_MANAGEMENT 0x13
|
||||
#define PQI_REQUEST_IU_RAID_PATH_IO 0x14
|
||||
#define PQI_REQUEST_IU_AIO_PATH_IO 0x15
|
||||
#define PQI_REQUEST_IU_AIO_PATH_RAID5_IO 0x18
|
||||
#define PQI_REQUEST_IU_AIO_PATH_RAID6_IO 0x19
|
||||
#define PQI_REQUEST_IU_AIO_PATH_RAID1_IO 0x1A
|
||||
#define PQI_REQUEST_IU_GENERAL_ADMIN 0x60
|
||||
#define PQI_REQUEST_IU_REPORT_VENDOR_EVENT_CONFIG 0x72
|
||||
#define PQI_REQUEST_IU_SET_VENDOR_EVENT_CONFIG 0x73
|
||||
#define PQI_REQUEST_IU_VENDOR_GENERAL 0x75
|
||||
#define PQI_REQUEST_IU_ACKNOWLEDGE_VENDOR_EVENT 0xf6
|
||||
|
||||
#define PQI_RESPONSE_IU_GENERAL_MANAGEMENT 0x81
|
||||
|
|
@ -430,6 +574,7 @@ struct pqi_raid_error_info {
|
|||
#define PQI_RESPONSE_IU_AIO_PATH_IO_ERROR 0xf3
|
||||
#define PQI_RESPONSE_IU_AIO_PATH_DISABLED 0xf4
|
||||
#define PQI_RESPONSE_IU_VENDOR_EVENT 0xf5
|
||||
#define PQI_RESPONSE_IU_VENDOR_GENERAL 0xf7
|
||||
|
||||
#define PQI_GENERAL_ADMIN_FUNCTION_REPORT_DEVICE_CAPABILITY 0x0
|
||||
#define PQI_GENERAL_ADMIN_FUNCTION_CREATE_IQ 0x10
|
||||
|
|
@ -483,6 +628,8 @@ struct pqi_raid_error_info {
|
|||
#define CISS_CMD_STATUS_TMF 0xd
|
||||
#define CISS_CMD_STATUS_AIO_DISABLED 0xe
|
||||
|
||||
#define PQI_CMD_STATUS_ABORTED CISS_CMD_STATUS_ABORTED
|
||||
|
||||
#define PQI_NUM_EVENT_QUEUE_ELEMENTS 32
|
||||
#define PQI_EVENT_OQ_ELEMENT_LENGTH sizeof(struct pqi_event_response)
|
||||
|
||||
|
|
@ -490,6 +637,7 @@ struct pqi_raid_error_info {
|
|||
#define PQI_EVENT_TYPE_HARDWARE 0x2
|
||||
#define PQI_EVENT_TYPE_PHYSICAL_DEVICE 0x4
|
||||
#define PQI_EVENT_TYPE_LOGICAL_DEVICE 0x5
|
||||
#define PQI_EVENT_TYPE_OFA 0xfb
|
||||
#define PQI_EVENT_TYPE_AIO_STATE_CHANGE 0xfd
|
||||
#define PQI_EVENT_TYPE_AIO_CONFIG_CHANGE 0xfe
|
||||
|
||||
|
|
@ -513,6 +661,7 @@ struct pqi_raid_error_info {
|
|||
/* these values are defined by the PQI spec */
|
||||
#define PQI_MAX_NUM_ELEMENTS_ADMIN_QUEUE 255
|
||||
#define PQI_MAX_NUM_ELEMENTS_OPERATIONAL_QUEUE 65535
|
||||
|
||||
#define PQI_QUEUE_ELEMENT_ARRAY_ALIGNMENT 64
|
||||
#define PQI_QUEUE_ELEMENT_LENGTH_ALIGNMENT 16
|
||||
#define PQI_ADMIN_INDEX_ALIGNMENT 64
|
||||
|
|
@ -554,6 +703,7 @@ typedef u32 pqi_index_t;
|
|||
#define SOP_TASK_ATTRIBUTE_ACA 4
|
||||
|
||||
#define SOP_TMF_COMPLETE 0x0
|
||||
#define SOP_TMF_REJECTED 0x4
|
||||
#define SOP_TMF_FUNCTION_SUCCEEDED 0x8
|
||||
|
||||
/* additional CDB bytes usage field codes */
|
||||
|
|
@ -581,8 +731,8 @@ struct pqi_admin_queues_aligned {
|
|||
struct pqi_admin_queues {
|
||||
void *iq_element_array;
|
||||
void *oq_element_array;
|
||||
volatile pqi_index_t *iq_ci;
|
||||
volatile pqi_index_t *oq_pi;
|
||||
pqi_index_t __iomem *iq_ci;
|
||||
pqi_index_t __iomem *oq_pi;
|
||||
dma_addr_t iq_element_array_bus_addr;
|
||||
dma_addr_t oq_element_array_bus_addr;
|
||||
dma_addr_t iq_ci_bus_addr;
|
||||
|
|
@ -606,8 +756,8 @@ struct pqi_queue_group {
|
|||
dma_addr_t oq_element_array_bus_addr;
|
||||
__le32 __iomem *iq_pi[2];
|
||||
pqi_index_t iq_pi_copy[2];
|
||||
volatile pqi_index_t *iq_ci[2];
|
||||
volatile pqi_index_t *oq_pi;
|
||||
pqi_index_t __iomem *iq_ci[2];
|
||||
pqi_index_t __iomem *oq_pi;
|
||||
dma_addr_t iq_ci_bus_addr[2];
|
||||
dma_addr_t oq_pi_bus_addr;
|
||||
__le32 __iomem *oq_ci;
|
||||
|
|
@ -620,7 +770,7 @@ struct pqi_event_queue {
|
|||
u16 oq_id;
|
||||
u16 int_msg_num;
|
||||
void *oq_element_array;
|
||||
volatile pqi_index_t *oq_pi;
|
||||
pqi_index_t __iomem *oq_pi;
|
||||
dma_addr_t oq_element_array_bus_addr;
|
||||
dma_addr_t oq_pi_bus_addr;
|
||||
__le32 __iomem *oq_ci;
|
||||
|
|
@ -628,7 +778,11 @@ struct pqi_event_queue {
|
|||
};
|
||||
|
||||
#define PQI_DEFAULT_QUEUE_GROUP 0
|
||||
#if TORTUGA
|
||||
#define PQI_MAX_QUEUE_GROUPS 1
|
||||
#else
|
||||
#define PQI_MAX_QUEUE_GROUPS PQI_MAX_MSIX_VECTORS
|
||||
#endif
|
||||
|
||||
struct pqi_encryption_info {
|
||||
u16 data_encryption_key_index;
|
||||
|
|
@ -642,11 +796,13 @@ struct pqi_encryption_info {
|
|||
#define PQI_CONFIG_TABLE_MAX_LENGTH ((u16)~0)
|
||||
|
||||
/* configuration table section IDs */
|
||||
#define PQI_CONFIG_TABLE_ALL_SECTIONS (-1)
|
||||
#define PQI_CONFIG_TABLE_SECTION_GENERAL_INFO 0
|
||||
#define PQI_CONFIG_TABLE_SECTION_FIRMWARE_FEATURES 1
|
||||
#define PQI_CONFIG_TABLE_SECTION_FIRMWARE_ERRATA 2
|
||||
#define PQI_CONFIG_TABLE_SECTION_DEBUG 3
|
||||
#define PQI_CONFIG_TABLE_SECTION_HEARTBEAT 4
|
||||
#define PQI_CONFIG_TABLE_SECTION_SOFT_RESET 5
|
||||
|
||||
struct pqi_config_table {
|
||||
u8 signature[8]; /* "CFGTABLE" */
|
||||
|
|
@ -678,6 +834,36 @@ struct pqi_config_table_general_info {
|
|||
/* command */
|
||||
};
|
||||
|
||||
struct pqi_config_table_firmware_features {
|
||||
struct pqi_config_table_section_header header;
|
||||
__le16 num_elements;
|
||||
u8 features_supported[];
|
||||
/* u8 features_requested_by_host[]; */
|
||||
/* u8 features_enabled[]; */
|
||||
/* The 2 fields below are only valid if the MAX_KNOWN_FEATURE bit is set. */
|
||||
/* __le16 firmware_max_known_feature; */
|
||||
/* __le16 host_max_known_feature; */
|
||||
};
|
||||
|
||||
#define PQI_FIRMWARE_FEATURE_OFA 0
|
||||
#define PQI_FIRMWARE_FEATURE_SMP 1
|
||||
#define PQI_FIRMWARE_FEATURE_MAX_KNOWN_FEATURE 2
|
||||
#define PQI_FIRMWARE_FEATURE_RAID_0_READ_BYPASS 3
|
||||
#define PQI_FIRMWARE_FEATURE_RAID_1_READ_BYPASS 4
|
||||
#define PQI_FIRMWARE_FEATURE_RAID_5_READ_BYPASS 5
|
||||
#define PQI_FIRMWARE_FEATURE_RAID_6_READ_BYPASS 6
|
||||
#define PQI_FIRMWARE_FEATURE_RAID_0_WRITE_BYPASS 7
|
||||
#define PQI_FIRMWARE_FEATURE_RAID_1_WRITE_BYPASS 8
|
||||
#define PQI_FIRMWARE_FEATURE_RAID_5_WRITE_BYPASS 9
|
||||
#define PQI_FIRMWARE_FEATURE_RAID_6_WRITE_BYPASS 10
|
||||
#define PQI_FIRMWARE_FEATURE_SOFT_RESET_HANDSHAKE 11
|
||||
#define PQI_FIRMWARE_FEATURE_UNIQUE_SATA_WWN 12
|
||||
#define PQI_FIRMWARE_FEATURE_RAID_IU_TIMEOUT 13
|
||||
#define PQI_FIRMWARE_FEATURE_TMF_IU_TIMEOUT 14
|
||||
#define PQI_FIRMWARE_FEATURE_RAID_BYPASS_ON_ENCRYPTED_NVME 15
|
||||
#define PQI_FIRMWARE_FEATURE_UNIQUE_WWID_IN_REPORT_PHYS_LUN 16
|
||||
#define PQI_FIRMWARE_FEATURE_MAXIMUM 16
|
||||
|
||||
struct pqi_config_table_debug {
|
||||
struct pqi_config_table_section_header header;
|
||||
__le32 scratchpad;
|
||||
|
|
@ -688,6 +874,22 @@ struct pqi_config_table_heartbeat {
|
|||
__le32 heartbeat_counter;
|
||||
};
|
||||
|
||||
struct pqi_config_table_soft_reset {
|
||||
struct pqi_config_table_section_header header;
|
||||
u8 soft_reset_status;
|
||||
};
|
||||
|
||||
#define PQI_SOFT_RESET_INITIATE 0x1
|
||||
#define PQI_SOFT_RESET_ABORT 0x2
|
||||
|
||||
enum pqi_soft_reset_status {
|
||||
RESET_INITIATE_FIRMWARE,
|
||||
RESET_INITIATE_DRIVER,
|
||||
RESET_ABORT,
|
||||
RESET_NORESPONSE,
|
||||
RESET_TIMEDOUT
|
||||
};
|
||||
|
||||
union pqi_reset_register {
|
||||
struct {
|
||||
u32 reset_type : 3;
|
||||
|
|
@ -710,10 +912,17 @@ union pqi_reset_register {
|
|||
|
||||
#define PQI_RESET_POLL_INTERVAL_MSECS 100
|
||||
|
||||
#if TORTUGA
|
||||
#define PQI_MAX_OUTSTANDING_REQUESTS 32
|
||||
#define PQI_MAX_OUTSTANDING_REQUESTS_KDUMP PQI_MAX_OUTSTANDING_REQUESTS
|
||||
#define PQI_MAX_TRANSFER_SIZE (512 * 1024U)
|
||||
#define PQI_MAX_TRANSFER_SIZE_KDUMP PQI_MAX_TRANSFER_SIZE
|
||||
#else
|
||||
#define PQI_MAX_OUTSTANDING_REQUESTS ((u32)~0)
|
||||
#define PQI_MAX_OUTSTANDING_REQUESTS_KDUMP 32
|
||||
#define PQI_MAX_TRANSFER_SIZE (1024U * 1024U)
|
||||
#define PQI_MAX_TRANSFER_SIZE (4 * 1024U * 1024U)
|
||||
#define PQI_MAX_TRANSFER_SIZE_KDUMP (512 * 1024U)
|
||||
#endif
|
||||
|
||||
#define RAID_MAP_MAX_ENTRIES 1024
|
||||
|
||||
|
|
@ -722,13 +931,21 @@ union pqi_reset_register {
|
|||
#define PQI_HBA_BUS 2
|
||||
#define PQI_EXTERNAL_RAID_VOLUME_BUS 3
|
||||
#define PQI_MAX_BUS PQI_EXTERNAL_RAID_VOLUME_BUS
|
||||
#define PQI_VSEP_CISS_BTL 379
|
||||
|
||||
struct report_lun_header {
|
||||
__be32 list_length;
|
||||
u8 extended_response;
|
||||
u8 flags;
|
||||
u8 reserved[3];
|
||||
};
|
||||
|
||||
/* for flags field of struct report_lun_header */
|
||||
#define CISS_REPORT_LOG_FLAG_UNIQUE_LUN_ID (1 << 0)
|
||||
#define CISS_REPORT_LOG_FLAG_QUEUE_DEPTH (1 << 5)
|
||||
#define CISS_REPORT_LOG_FLAG_DRIVE_TYPE_MIX (1 << 6)
|
||||
|
||||
#define CISS_REPORT_PHYS_FLAG_OTHER (1 << 1)
|
||||
|
||||
struct report_log_lun_extended_entry {
|
||||
u8 lunid[8];
|
||||
u8 volume_id[16];
|
||||
|
|
@ -750,7 +967,7 @@ struct report_phys_lun_extended_entry {
|
|||
};
|
||||
|
||||
/* for device_flags field of struct report_phys_lun_extended_entry */
|
||||
#define REPORT_PHYS_LUN_DEV_FLAG_AIO_ENABLED 0x8
|
||||
#define CISS_REPORT_PHYS_DEV_FLAG_AIO_ENABLED 0x8
|
||||
|
||||
struct report_phys_lun_extended {
|
||||
struct report_lun_header header;
|
||||
|
|
@ -763,7 +980,7 @@ struct raid_map_disk_data {
|
|||
u8 reserved[2];
|
||||
};
|
||||
|
||||
/* constants for flags field of RAID map */
|
||||
/* for flags field of RAID map */
|
||||
#define RAID_MAP_ENCRYPTION_ENABLED 0x1
|
||||
|
||||
struct raid_map {
|
||||
|
|
@ -793,8 +1010,65 @@ struct raid_map {
|
|||
|
||||
#pragma pack()
|
||||
|
||||
struct pqi_scsi_dev_raid_map_data {
|
||||
bool is_write;
|
||||
u8 raid_level;
|
||||
u32 map_index;
|
||||
u64 first_block;
|
||||
u64 last_block;
|
||||
u32 data_length;
|
||||
u32 block_cnt;
|
||||
u32 blocks_per_row;
|
||||
u64 first_row;
|
||||
u64 last_row;
|
||||
u32 first_row_offset;
|
||||
u32 last_row_offset;
|
||||
u32 first_column;
|
||||
u32 last_column;
|
||||
u64 r5or6_first_row;
|
||||
u64 r5or6_last_row;
|
||||
u32 r5or6_first_row_offset;
|
||||
u32 r5or6_last_row_offset;
|
||||
u32 r5or6_first_column;
|
||||
u32 r5or6_last_column;
|
||||
u16 data_disks_per_row;
|
||||
u32 total_disks_per_row;
|
||||
u16 layout_map_count;
|
||||
u32 stripesize;
|
||||
u16 strip_size;
|
||||
u32 first_group;
|
||||
u32 last_group;
|
||||
u32 map_row;
|
||||
u32 aio_handle;
|
||||
u64 disk_block;
|
||||
u32 disk_block_cnt;
|
||||
u8 cdb[16];
|
||||
u8 cdb_length;
|
||||
|
||||
/* RAID 1 specific */
|
||||
#define NUM_RAID1_MAP_ENTRIES 3
|
||||
u32 num_it_nexus_entries;
|
||||
u32 it_nexus[NUM_RAID1_MAP_ENTRIES];
|
||||
|
||||
/* RAID 5 / RAID 6 specific */
|
||||
u32 p_parity_it_nexus; /* aio_handle */
|
||||
u32 q_parity_it_nexus; /* aio_handle */
|
||||
u8 xor_mult;
|
||||
u64 row;
|
||||
u64 stripe_lba;
|
||||
u32 p_index;
|
||||
u32 q_index;
|
||||
};
|
||||
|
||||
#define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0"
|
||||
|
||||
#define NUM_STREAMS_PER_LUN 8
|
||||
|
||||
struct pqi_stream_data {
|
||||
u64 next_lba;
|
||||
u32 last_accessed;
|
||||
};
|
||||
|
||||
struct pqi_scsi_dev {
|
||||
int devtype; /* as reported by INQUIRY commmand */
|
||||
u8 device_type; /* as reported by */
|
||||
|
|
@ -808,13 +1082,15 @@ struct pqi_scsi_dev {
|
|||
u8 volume_id[16];
|
||||
u8 is_physical_device : 1;
|
||||
u8 is_external_raid_device : 1;
|
||||
u8 is_expander_smp_device : 1;
|
||||
u8 target_lun_valid : 1;
|
||||
u8 device_gone : 1;
|
||||
u8 new_device : 1;
|
||||
u8 keep_device : 1;
|
||||
u8 volume_offline : 1;
|
||||
u8 rescan : 1;
|
||||
bool aio_enabled; /* only valid for physical disks */
|
||||
bool in_reset;
|
||||
bool in_remove;
|
||||
bool device_offline;
|
||||
u8 vendor[8]; /* bytes 8-15 of inquiry data */
|
||||
u8 model[16]; /* bytes 16-31 of inquiry data */
|
||||
|
|
@ -827,13 +1103,17 @@ struct pqi_scsi_dev {
|
|||
u8 active_path_index;
|
||||
u8 path_map;
|
||||
u8 bay;
|
||||
u8 box_index;
|
||||
u8 phys_box_on_bus;
|
||||
u8 phy_connected_dev_type;
|
||||
u8 box[8];
|
||||
u16 phys_connector[8];
|
||||
u8 phy_id;
|
||||
bool raid_bypass_configured; /* RAID bypass configured */
|
||||
bool raid_bypass_enabled; /* RAID bypass enabled */
|
||||
int offload_to_mirror; /* Send next RAID bypass request */
|
||||
/* to mirror drive. */
|
||||
u32 next_bypass_group;
|
||||
struct raid_map *raid_map; /* RAID bypass map */
|
||||
u32 max_transfer_encrypted;
|
||||
|
||||
struct pqi_sas_port *sas_port;
|
||||
struct scsi_device *sdev;
|
||||
|
|
@ -843,12 +1123,13 @@ struct pqi_scsi_dev {
|
|||
struct list_head add_list_entry;
|
||||
struct list_head delete_list_entry;
|
||||
|
||||
struct pqi_stream_data stream_data[NUM_STREAMS_PER_LUN];
|
||||
atomic_t scsi_cmds_outstanding;
|
||||
atomic_t raid_bypass_cnt;
|
||||
u8 page_83_identifier[16];
|
||||
};
|
||||
|
||||
/* VPD inquiry pages */
|
||||
#define SCSI_VPD_SUPPORTED_PAGES 0x0 /* standard page */
|
||||
#define SCSI_VPD_DEVICE_ID 0x83 /* standard page */
|
||||
#define CISS_VPD_LV_DEVICE_GEOMETRY 0xc1 /* vendor-specific page */
|
||||
#define CISS_VPD_LV_BYPASS_STATUS 0xc2 /* vendor-specific page */
|
||||
#define CISS_VPD_LV_STATUS 0xc3 /* vendor-specific page */
|
||||
|
|
@ -914,6 +1195,7 @@ struct pqi_sas_node {
|
|||
struct pqi_sas_port {
|
||||
struct list_head port_list_entry;
|
||||
u64 sas_address;
|
||||
struct pqi_scsi_dev *device;
|
||||
struct sas_port *port;
|
||||
int next_phy_index;
|
||||
struct list_head phy_list_head;
|
||||
|
|
@ -945,13 +1227,13 @@ struct pqi_io_request {
|
|||
struct list_head request_list_entry;
|
||||
};
|
||||
|
||||
#define PQI_NUM_SUPPORTED_EVENTS 6
|
||||
#define PQI_NUM_SUPPORTED_EVENTS 7
|
||||
|
||||
struct pqi_event {
|
||||
bool pending;
|
||||
u8 event_type;
|
||||
__le16 event_id;
|
||||
__le32 additional_event_id;
|
||||
u16 event_id;
|
||||
u32 additional_event_id;
|
||||
};
|
||||
|
||||
#define PQI_RESERVED_IO_SLOTS_LUN_RESET 1
|
||||
|
|
@ -961,10 +1243,20 @@ struct pqi_event {
|
|||
(PQI_RESERVED_IO_SLOTS_LUN_RESET + PQI_RESERVED_IO_SLOTS_EVENT_ACK + \
|
||||
PQI_RESERVED_IO_SLOTS_SYNCHRONOUS_REQUESTS)
|
||||
|
||||
#define PQI_CTRL_PRODUCT_ID_GEN1 0
|
||||
#define PQI_CTRL_PRODUCT_ID_GEN2 7
|
||||
#define PQI_CTRL_PRODUCT_REVISION_A 0
|
||||
#define PQI_CTRL_PRODUCT_REVISION_B 1
|
||||
|
||||
struct pqi_ctrl_info {
|
||||
unsigned int ctrl_id;
|
||||
struct pci_dev *pci_dev;
|
||||
char firmware_version[11];
|
||||
char firmware_version[32];
|
||||
char serial_number[17];
|
||||
char model[17];
|
||||
char vendor[9];
|
||||
u8 product_id;
|
||||
u8 product_revision;
|
||||
void __iomem *iomem_base;
|
||||
struct pqi_ctrl_registers __iomem *registers;
|
||||
struct pqi_device_registers __iomem *pqi_registers;
|
||||
|
|
@ -994,6 +1286,7 @@ struct pqi_ctrl_info {
|
|||
u16 max_inbound_iu_length_per_firmware;
|
||||
u16 max_inbound_iu_length;
|
||||
unsigned int max_sg_per_iu;
|
||||
unsigned int max_sg_per_r56_iu;
|
||||
void *admin_queue_memory_base;
|
||||
u32 admin_queue_memory_length;
|
||||
dma_addr_t admin_queue_memory_base_dma_handle;
|
||||
|
|
@ -1007,6 +1300,8 @@ struct pqi_ctrl_info {
|
|||
int max_msix_vectors;
|
||||
int num_msix_vectors_enabled;
|
||||
int num_msix_vectors_initialized;
|
||||
u32 msix_vectors[PQI_MAX_MSIX_VECTORS];
|
||||
void *intr_data[PQI_MAX_MSIX_VECTORS];
|
||||
int event_irq;
|
||||
struct Scsi_Host *scsi_host;
|
||||
|
||||
|
|
@ -1014,10 +1309,27 @@ struct pqi_ctrl_info {
|
|||
struct mutex lun_reset_mutex;
|
||||
bool controller_online;
|
||||
bool block_requests;
|
||||
bool scan_blocked;
|
||||
u8 inbound_spanning_supported : 1;
|
||||
u8 outbound_spanning_supported : 1;
|
||||
u8 pqi_mode_enabled : 1;
|
||||
u8 pqi_reset_quiesce_supported : 1;
|
||||
u8 soft_reset_handshake_supported : 1;
|
||||
u8 raid_iu_timeout_supported : 1;
|
||||
u8 tmf_iu_timeout_supported : 1;
|
||||
u8 unique_wwid_in_report_phys_lun_supported : 1;
|
||||
u8 enable_r1_writes : 1;
|
||||
u8 enable_r5_writes : 1;
|
||||
u8 enable_r6_writes : 1;
|
||||
u8 lv_drive_type_mix_valid : 1;
|
||||
u8 enable_stream_detection : 1;
|
||||
|
||||
u8 ciss_report_log_flags;
|
||||
u32 max_transfer_encrypted_sas_sata;
|
||||
u32 max_transfer_encrypted_nvme;
|
||||
u32 max_write_raid_5_6;
|
||||
u32 max_write_raid_1_10_2drive;
|
||||
u32 max_write_raid_1_10_3drive;
|
||||
|
||||
struct list_head scsi_device_list;
|
||||
spinlock_t scsi_device_list_lock;
|
||||
|
|
@ -1038,6 +1350,7 @@ struct pqi_ctrl_info {
|
|||
int previous_num_interrupts;
|
||||
u32 previous_heartbeat_count;
|
||||
__le32 __iomem *heartbeat_counter;
|
||||
u8 __iomem *soft_reset_status;
|
||||
struct timer_list heartbeat_timer;
|
||||
struct work_struct ctrl_offline_work;
|
||||
|
||||
|
|
@ -1046,9 +1359,16 @@ struct pqi_ctrl_info {
|
|||
atomic_t num_blocked_threads;
|
||||
wait_queue_head_t block_requests_wait;
|
||||
|
||||
struct list_head raid_bypass_retry_list;
|
||||
spinlock_t raid_bypass_retry_list_lock;
|
||||
struct work_struct raid_bypass_retry_work;
|
||||
struct mutex ofa_mutex;
|
||||
struct pqi_ofa_memory *pqi_ofa_mem_virt_addr;
|
||||
dma_addr_t pqi_ofa_mem_dma_handle;
|
||||
void **pqi_ofa_chunk_virt_addr;
|
||||
struct work_struct ofa_memory_alloc_work;
|
||||
struct work_struct ofa_quiesce_work;
|
||||
u32 ofa_bytes_requested;
|
||||
u16 ofa_cancel_reason;
|
||||
|
||||
atomic_t total_scmds_outstanding;
|
||||
};
|
||||
|
||||
enum pqi_ctrl_mode {
|
||||
|
|
@ -1067,19 +1387,21 @@ enum pqi_ctrl_mode {
|
|||
#define CISS_REPORT_PHYS 0xc3 /* Report Physical LUNs */
|
||||
#define CISS_GET_RAID_MAP 0xc8
|
||||
|
||||
/* constants for CISS_REPORT_LOG/CISS_REPORT_PHYS commands */
|
||||
#define CISS_REPORT_LOG_EXTENDED 0x1
|
||||
#define CISS_REPORT_PHYS_EXTENDED 0x2
|
||||
|
||||
/* BMIC commands */
|
||||
#define BMIC_IDENTIFY_CONTROLLER 0x11
|
||||
#define BMIC_IDENTIFY_PHYSICAL_DEVICE 0x15
|
||||
#define BMIC_READ 0x26
|
||||
#define BMIC_WRITE 0x27
|
||||
#define BMIC_SENSE_FEATURE 0x61
|
||||
#define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64
|
||||
#define BMIC_SENSE_SUBSYSTEM_INFORMATION 0x66
|
||||
#define BMIC_CSMI_PASSTHRU 0x68
|
||||
#define BMIC_WRITE_HOST_WELLNESS 0xa5
|
||||
#define BMIC_FLUSH_CACHE 0xc2
|
||||
#define BMIC_SET_DIAG_OPTIONS 0xf4
|
||||
#define BMIC_SENSE_DIAG_OPTIONS 0xf5
|
||||
|
||||
#define CSMI_CC_SAS_SMP_PASSTHRU 0x17
|
||||
|
||||
#define SA_FLUSH_CACHE 0x1
|
||||
|
||||
|
|
@ -1090,6 +1412,19 @@ enum pqi_ctrl_mode {
|
|||
(((CISS_GET_LEVEL_2_BUS((lunid)) - 1) << 8) + \
|
||||
CISS_GET_LEVEL_2_TARGET((lunid)))
|
||||
|
||||
#define LV_GET_DRIVE_TYPE_MIX(lunid) ((lunid)[6])
|
||||
|
||||
#define LV_DRIVE_TYPE_MIX_UNKNOWN 0
|
||||
#define LV_DRIVE_TYPE_MIX_NO_RESTRICTION 1
|
||||
#define LV_DRIVE_TYPE_MIX_SAS_HDD_ONLY 2
|
||||
#define LV_DRIVE_TYPE_MIX_SATA_HDD_ONLY 3
|
||||
#define LV_DRIVE_TYPE_MIX_SAS_OR_SATA_SSD_ONLY 4
|
||||
#define LV_DRIVE_TYPE_MIX_SAS_SSD_ONLY 5
|
||||
#define LV_DRIVE_TYPE_MIX_SATA_SSD_ONLY 6
|
||||
#define LV_DRIVE_TYPE_MIX_SAS_ONLY 7
|
||||
#define LV_DRIVE_TYPE_MIX_SATA_ONLY 8
|
||||
#define LV_DRIVE_TYPE_MIX_NVME_ONLY 9
|
||||
|
||||
#define NO_TIMEOUT ((unsigned long) -1)
|
||||
|
||||
#pragma pack(1)
|
||||
|
|
@ -1097,16 +1432,38 @@ enum pqi_ctrl_mode {
|
|||
struct bmic_identify_controller {
|
||||
u8 configured_logical_drive_count;
|
||||
__le32 configuration_signature;
|
||||
u8 firmware_version[4];
|
||||
u8 firmware_version_short[4];
|
||||
u8 reserved[145];
|
||||
__le16 extended_logical_unit_count;
|
||||
u8 reserved1[34];
|
||||
__le16 firmware_build_number;
|
||||
u8 reserved2[100];
|
||||
u8 reserved2[8];
|
||||
u8 vendor_id[8];
|
||||
u8 product_id[16];
|
||||
u8 reserved3[62];
|
||||
__le32 extra_controller_flags;
|
||||
u8 reserved4[2];
|
||||
u8 controller_mode;
|
||||
u8 reserved3[32];
|
||||
u8 spare_part_number[32];
|
||||
u8 firmware_version_long[32];
|
||||
};
|
||||
|
||||
/* constants for extra_controller_flags field of bmic_identify_controller */
|
||||
#define BMIC_IDENTIFY_EXTRA_FLAGS_LONG_FW_VERSION_SUPPORTED 0x20000000
|
||||
|
||||
struct bmic_sense_subsystem_info {
|
||||
u8 reserved[44];
|
||||
u8 ctrl_serial_number[16];
|
||||
};
|
||||
|
||||
/* constants for device_type field */
|
||||
#define SA_DEVICE_TYPE_SATA 0x1
|
||||
#define SA_DEVICE_TYPE_SAS 0x2
|
||||
#define SA_DEVICE_TYPE_EXPANDER_SMP 0x5
|
||||
#define SA_DEVICE_TYPE_SES 0x6
|
||||
#define SA_DEVICE_TYPE_CONTROLLER 0x7
|
||||
#define SA_DEVICE_TYPE_NVME 0x9
|
||||
|
||||
struct bmic_identify_physical_device {
|
||||
u8 scsi_bus; /* SCSI Bus number on controller */
|
||||
u8 scsi_id; /* SCSI ID on this bus */
|
||||
|
|
@ -1131,7 +1488,7 @@ struct bmic_identify_physical_device {
|
|||
__le32 rpm; /* drive rotational speed in RPM */
|
||||
u8 device_type; /* type of drive */
|
||||
u8 sata_version; /* only valid when device_type = */
|
||||
/* BMIC_DEVICE_TYPE_SATA */
|
||||
/* SA_DEVICE_TYPE_SATA */
|
||||
__le64 big_total_block_count;
|
||||
__le64 ris_starting_lba;
|
||||
__le32 ris_size;
|
||||
|
|
@ -1187,6 +1544,78 @@ struct bmic_identify_physical_device {
|
|||
u8 padding_to_multiple_of_512[9];
|
||||
};
|
||||
|
||||
#define BMIC_SENSE_FEATURE_IO_PAGE 0x8
|
||||
#define BMIC_SENSE_FEATURE_IO_PAGE_AIO_SUBPAGE 0x2
|
||||
|
||||
struct bmic_sense_feature_buffer_header {
|
||||
u8 page_code;
|
||||
u8 subpage_code;
|
||||
__le16 buffer_length;
|
||||
};
|
||||
|
||||
struct bmic_sense_feature_page_header {
|
||||
u8 page_code;
|
||||
u8 subpage_code;
|
||||
__le16 page_length;
|
||||
};
|
||||
|
||||
struct bmic_sense_feature_io_page_aio_subpage {
|
||||
struct bmic_sense_feature_page_header header;
|
||||
u8 firmware_read_support;
|
||||
u8 driver_read_support;
|
||||
u8 firmware_write_support;
|
||||
u8 driver_write_support;
|
||||
__le16 max_transfer_encrypted_sas_sata;
|
||||
__le16 max_transfer_encrypted_nvme;
|
||||
__le16 max_write_raid_5_6;
|
||||
__le16 max_write_raid_1_10_2drive;
|
||||
__le16 max_write_raid_1_10_3drive;
|
||||
};
|
||||
|
||||
struct bmic_smp_request {
|
||||
u8 frame_type;
|
||||
u8 function;
|
||||
u8 allocated_response_length;
|
||||
u8 request_length;
|
||||
u8 additional_request_bytes[1016];
|
||||
};
|
||||
|
||||
struct bmic_smp_response {
|
||||
u8 frame_type;
|
||||
u8 function;
|
||||
u8 function_result;
|
||||
u8 response_length;
|
||||
u8 additional_response_bytes[1016];
|
||||
};
|
||||
|
||||
struct bmic_csmi_ioctl_header {
|
||||
__le32 header_length;
|
||||
u8 signature[8];
|
||||
__le32 timeout;
|
||||
__le32 control_code;
|
||||
__le32 return_code;
|
||||
__le32 length;
|
||||
};
|
||||
|
||||
struct bmic_csmi_smp_passthru {
|
||||
u8 phy_identifier;
|
||||
u8 port_identifier;
|
||||
u8 connection_rate;
|
||||
u8 reserved;
|
||||
__be64 destination_sas_address;
|
||||
__le32 request_length;
|
||||
struct bmic_smp_request request;
|
||||
u8 connection_status;
|
||||
u8 reserved1[3];
|
||||
__le32 response_length;
|
||||
struct bmic_smp_response response;
|
||||
};
|
||||
|
||||
struct bmic_csmi_smp_passthru_buffer {
|
||||
struct bmic_csmi_ioctl_header ioctl_header;
|
||||
struct bmic_csmi_smp_passthru parameters;
|
||||
};
|
||||
|
||||
struct bmic_flush_cache {
|
||||
u8 disable_flag;
|
||||
u8 system_power_action;
|
||||
|
|
@ -1204,8 +1633,22 @@ enum bmic_flush_cache_shutdown_event {
|
|||
RESTART = 4
|
||||
};
|
||||
|
||||
struct bmic_diag_options {
|
||||
__le32 options;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
static inline struct pqi_ctrl_info *shost_to_hba(struct Scsi_Host *shost)
|
||||
{
|
||||
void *hostdata = shost_priv(shost);
|
||||
|
||||
return *((struct pqi_ctrl_info **)hostdata);
|
||||
}
|
||||
|
||||
void pqi_sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
|
||||
struct sas_rphy *rphy);
|
||||
int pqi_scsi_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd);
|
||||
int pqi_add_sas_host(struct Scsi_Host *shost, struct pqi_ctrl_info *ctrl_info);
|
||||
void pqi_delete_sas_host(struct pqi_ctrl_info *ctrl_info);
|
||||
int pqi_add_sas_device(struct pqi_sas_node *pqi_sas_node,
|
||||
|
|
@ -1214,7 +1657,10 @@ void pqi_remove_sas_device(struct pqi_scsi_dev *device);
|
|||
struct pqi_scsi_dev *pqi_find_device_by_sas_rphy(
|
||||
struct pqi_ctrl_info *ctrl_info, struct sas_rphy *rphy);
|
||||
void pqi_prep_for_scsi_done(struct scsi_cmnd *scmd);
|
||||
int pqi_csmi_smp_passthru(struct pqi_ctrl_info *ctrl_info,
|
||||
struct bmic_csmi_smp_passthru_buffer *buffer, size_t buffer_length,
|
||||
struct pqi_raid_error_info *error_info);
|
||||
|
||||
extern struct sas_function_template pqi_sas_transport_functions;
|
||||
|
||||
#endif /* _SMARTPQI_H */
|
||||
#endif /* _SMARTPQI_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue