brintos

brintos / linux-shallow public Read only

0
0
Text · 50.9 KiB · c7e1089 Raw
1888 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Microsemi Switchtec(tm) PCIe Management Driver4 * Copyright (c) 2017, Microsemi Corporation5 */6 7#include <linux/switchtec.h>8#include <linux/switchtec_ioctl.h>9 10#include <linux/interrupt.h>11#include <linux/module.h>12#include <linux/fs.h>13#include <linux/uaccess.h>14#include <linux/poll.h>15#include <linux/wait.h>16#include <linux/io-64-nonatomic-lo-hi.h>17#include <linux/nospec.h>18 19MODULE_DESCRIPTION("Microsemi Switchtec(tm) PCIe Management Driver");20MODULE_VERSION("0.1");21MODULE_LICENSE("GPL");22MODULE_AUTHOR("Microsemi Corporation");23 24static int max_devices = 16;25module_param(max_devices, int, 0644);26MODULE_PARM_DESC(max_devices, "max number of switchtec device instances");27 28static bool use_dma_mrpc = true;29module_param(use_dma_mrpc, bool, 0644);30MODULE_PARM_DESC(use_dma_mrpc,31		 "Enable the use of the DMA MRPC feature");32 33static int nirqs = 32;34module_param(nirqs, int, 0644);35MODULE_PARM_DESC(nirqs, "number of interrupts to allocate (more may be useful for NTB applications)");36 37static dev_t switchtec_devt;38static DEFINE_IDA(switchtec_minor_ida);39 40const struct class switchtec_class = {41	.name = "switchtec",42};43EXPORT_SYMBOL_GPL(switchtec_class);44 45enum mrpc_state {46	MRPC_IDLE = 0,47	MRPC_QUEUED,48	MRPC_RUNNING,49	MRPC_DONE,50	MRPC_IO_ERROR,51};52 53struct switchtec_user {54	struct switchtec_dev *stdev;55 56	enum mrpc_state state;57 58	wait_queue_head_t cmd_comp;59	struct kref kref;60	struct list_head list;61 62	bool cmd_done;63	u32 cmd;64	u32 status;65	u32 return_code;66	size_t data_len;67	size_t read_len;68	unsigned char data[SWITCHTEC_MRPC_PAYLOAD_SIZE];69	int event_cnt;70};71 72/*73 * The MMIO reads to the device_id register should always return the device ID74 * of the device, otherwise the firmware is probably stuck or unreachable75 * due to a firmware reset which clears PCI state including the BARs and Memory76 * Space Enable bits.77 */78static int is_firmware_running(struct switchtec_dev *stdev)79{80	u32 device = ioread32(&stdev->mmio_sys_info->device_id);81 82	return stdev->pdev->device == device;83}84 85static struct switchtec_user *stuser_create(struct switchtec_dev *stdev)86{87	struct switchtec_user *stuser;88 89	stuser = kzalloc(sizeof(*stuser), GFP_KERNEL);90	if (!stuser)91		return ERR_PTR(-ENOMEM);92 93	get_device(&stdev->dev);94	stuser->stdev = stdev;95	kref_init(&stuser->kref);96	INIT_LIST_HEAD(&stuser->list);97	init_waitqueue_head(&stuser->cmd_comp);98	stuser->event_cnt = atomic_read(&stdev->event_cnt);99 100	dev_dbg(&stdev->dev, "%s: %p\n", __func__, stuser);101 102	return stuser;103}104 105static void stuser_free(struct kref *kref)106{107	struct switchtec_user *stuser;108 109	stuser = container_of(kref, struct switchtec_user, kref);110 111	dev_dbg(&stuser->stdev->dev, "%s: %p\n", __func__, stuser);112 113	put_device(&stuser->stdev->dev);114	kfree(stuser);115}116 117static void stuser_put(struct switchtec_user *stuser)118{119	kref_put(&stuser->kref, stuser_free);120}121 122static void stuser_set_state(struct switchtec_user *stuser,123			     enum mrpc_state state)124{125	/* requires the mrpc_mutex to already be held when called */126 127	static const char * const state_names[] = {128		[MRPC_IDLE] = "IDLE",129		[MRPC_QUEUED] = "QUEUED",130		[MRPC_RUNNING] = "RUNNING",131		[MRPC_DONE] = "DONE",132		[MRPC_IO_ERROR] = "IO_ERROR",133	};134 135	stuser->state = state;136 137	dev_dbg(&stuser->stdev->dev, "stuser state %p -> %s",138		stuser, state_names[state]);139}140 141static void mrpc_complete_cmd(struct switchtec_dev *stdev);142 143static void flush_wc_buf(struct switchtec_dev *stdev)144{145	struct ntb_dbmsg_regs __iomem *mmio_dbmsg;146 147	/*148	 * odb (outbound doorbell) register is processed by low latency149	 * hardware and w/o side effect150	 */151	mmio_dbmsg = (void __iomem *)stdev->mmio_ntb +152		SWITCHTEC_NTB_REG_DBMSG_OFFSET;153	ioread32(&mmio_dbmsg->odb);154}155 156static void mrpc_cmd_submit(struct switchtec_dev *stdev)157{158	/* requires the mrpc_mutex to already be held when called */159 160	struct switchtec_user *stuser;161 162	if (stdev->mrpc_busy)163		return;164 165	if (list_empty(&stdev->mrpc_queue))166		return;167 168	stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,169			    list);170 171	if (stdev->dma_mrpc) {172		stdev->dma_mrpc->status = SWITCHTEC_MRPC_STATUS_INPROGRESS;173		memset(stdev->dma_mrpc->data, 0xFF, SWITCHTEC_MRPC_PAYLOAD_SIZE);174	}175 176	stuser_set_state(stuser, MRPC_RUNNING);177	stdev->mrpc_busy = 1;178	memcpy_toio(&stdev->mmio_mrpc->input_data,179		    stuser->data, stuser->data_len);180	flush_wc_buf(stdev);181	iowrite32(stuser->cmd, &stdev->mmio_mrpc->cmd);182 183	schedule_delayed_work(&stdev->mrpc_timeout,184			      msecs_to_jiffies(500));185}186 187static int mrpc_queue_cmd(struct switchtec_user *stuser)188{189	/* requires the mrpc_mutex to already be held when called */190 191	struct switchtec_dev *stdev = stuser->stdev;192 193	kref_get(&stuser->kref);194	stuser->read_len = sizeof(stuser->data);195	stuser_set_state(stuser, MRPC_QUEUED);196	stuser->cmd_done = false;197	list_add_tail(&stuser->list, &stdev->mrpc_queue);198 199	mrpc_cmd_submit(stdev);200 201	return 0;202}203 204static void mrpc_cleanup_cmd(struct switchtec_dev *stdev)205{206	/* requires the mrpc_mutex to already be held when called */207 208	struct switchtec_user *stuser = list_entry(stdev->mrpc_queue.next,209						   struct switchtec_user, list);210 211	stuser->cmd_done = true;212	wake_up_interruptible(&stuser->cmd_comp);213	list_del_init(&stuser->list);214	stuser_put(stuser);215	stdev->mrpc_busy = 0;216 217	mrpc_cmd_submit(stdev);218}219 220static void mrpc_complete_cmd(struct switchtec_dev *stdev)221{222	/* requires the mrpc_mutex to already be held when called */223 224	struct switchtec_user *stuser;225 226	if (list_empty(&stdev->mrpc_queue))227		return;228 229	stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,230			    list);231 232	if (stdev->dma_mrpc)233		stuser->status = stdev->dma_mrpc->status;234	else235		stuser->status = ioread32(&stdev->mmio_mrpc->status);236 237	if (stuser->status == SWITCHTEC_MRPC_STATUS_INPROGRESS)238		return;239 240	stuser_set_state(stuser, MRPC_DONE);241	stuser->return_code = 0;242 243	if (stuser->status != SWITCHTEC_MRPC_STATUS_DONE &&244	    stuser->status != SWITCHTEC_MRPC_STATUS_ERROR)245		goto out;246 247	if (stdev->dma_mrpc)248		stuser->return_code = stdev->dma_mrpc->rtn_code;249	else250		stuser->return_code = ioread32(&stdev->mmio_mrpc->ret_value);251	if (stuser->return_code != 0)252		goto out;253 254	if (stdev->dma_mrpc)255		memcpy(stuser->data, &stdev->dma_mrpc->data,256			      stuser->read_len);257	else258		memcpy_fromio(stuser->data, &stdev->mmio_mrpc->output_data,259			      stuser->read_len);260out:261	mrpc_cleanup_cmd(stdev);262}263 264static void mrpc_event_work(struct work_struct *work)265{266	struct switchtec_dev *stdev;267 268	stdev = container_of(work, struct switchtec_dev, mrpc_work);269 270	dev_dbg(&stdev->dev, "%s\n", __func__);271 272	mutex_lock(&stdev->mrpc_mutex);273	cancel_delayed_work(&stdev->mrpc_timeout);274	mrpc_complete_cmd(stdev);275	mutex_unlock(&stdev->mrpc_mutex);276}277 278static void mrpc_error_complete_cmd(struct switchtec_dev *stdev)279{280	/* requires the mrpc_mutex to already be held when called */281 282	struct switchtec_user *stuser;283 284	if (list_empty(&stdev->mrpc_queue))285		return;286 287	stuser = list_entry(stdev->mrpc_queue.next,288			    struct switchtec_user, list);289 290	stuser_set_state(stuser, MRPC_IO_ERROR);291 292	mrpc_cleanup_cmd(stdev);293}294 295static void mrpc_timeout_work(struct work_struct *work)296{297	struct switchtec_dev *stdev;298	u32 status;299 300	stdev = container_of(work, struct switchtec_dev, mrpc_timeout.work);301 302	dev_dbg(&stdev->dev, "%s\n", __func__);303 304	mutex_lock(&stdev->mrpc_mutex);305 306	if (!is_firmware_running(stdev)) {307		mrpc_error_complete_cmd(stdev);308		goto out;309	}310 311	if (stdev->dma_mrpc)312		status = stdev->dma_mrpc->status;313	else314		status = ioread32(&stdev->mmio_mrpc->status);315	if (status == SWITCHTEC_MRPC_STATUS_INPROGRESS) {316		schedule_delayed_work(&stdev->mrpc_timeout,317				      msecs_to_jiffies(500));318		goto out;319	}320 321	mrpc_complete_cmd(stdev);322out:323	mutex_unlock(&stdev->mrpc_mutex);324}325 326static ssize_t device_version_show(struct device *dev,327	struct device_attribute *attr, char *buf)328{329	struct switchtec_dev *stdev = to_stdev(dev);330	u32 ver;331 332	ver = ioread32(&stdev->mmio_sys_info->device_version);333 334	return sysfs_emit(buf, "%x\n", ver);335}336static DEVICE_ATTR_RO(device_version);337 338static ssize_t fw_version_show(struct device *dev,339	struct device_attribute *attr, char *buf)340{341	struct switchtec_dev *stdev = to_stdev(dev);342	u32 ver;343 344	ver = ioread32(&stdev->mmio_sys_info->firmware_version);345 346	return sysfs_emit(buf, "%08x\n", ver);347}348static DEVICE_ATTR_RO(fw_version);349 350static ssize_t io_string_show(char *buf, void __iomem *attr, size_t len)351{352	int i;353 354	memcpy_fromio(buf, attr, len);355	buf[len] = '\n';356	buf[len + 1] = 0;357 358	for (i = len - 1; i > 0; i--) {359		if (buf[i] != ' ')360			break;361		buf[i] = '\n';362		buf[i + 1] = 0;363	}364 365	return strlen(buf);366}367 368#define DEVICE_ATTR_SYS_INFO_STR(field) \369static ssize_t field ## _show(struct device *dev, \370	struct device_attribute *attr, char *buf) \371{ \372	struct switchtec_dev *stdev = to_stdev(dev); \373	struct sys_info_regs __iomem *si = stdev->mmio_sys_info; \374	if (stdev->gen == SWITCHTEC_GEN3) \375		return io_string_show(buf, &si->gen3.field, \376				      sizeof(si->gen3.field)); \377	else if (stdev->gen >= SWITCHTEC_GEN4) \378		return io_string_show(buf, &si->gen4.field, \379				      sizeof(si->gen4.field)); \380	else \381		return -EOPNOTSUPP; \382} \383\384static DEVICE_ATTR_RO(field)385 386DEVICE_ATTR_SYS_INFO_STR(vendor_id);387DEVICE_ATTR_SYS_INFO_STR(product_id);388DEVICE_ATTR_SYS_INFO_STR(product_revision);389 390static ssize_t component_vendor_show(struct device *dev,391				     struct device_attribute *attr, char *buf)392{393	struct switchtec_dev *stdev = to_stdev(dev);394	struct sys_info_regs __iomem *si = stdev->mmio_sys_info;395 396	/* component_vendor field not supported after gen3 */397	if (stdev->gen != SWITCHTEC_GEN3)398		return sysfs_emit(buf, "none\n");399 400	return io_string_show(buf, &si->gen3.component_vendor,401			      sizeof(si->gen3.component_vendor));402}403static DEVICE_ATTR_RO(component_vendor);404 405static ssize_t component_id_show(struct device *dev,406	struct device_attribute *attr, char *buf)407{408	struct switchtec_dev *stdev = to_stdev(dev);409	int id = ioread16(&stdev->mmio_sys_info->gen3.component_id);410 411	/* component_id field not supported after gen3 */412	if (stdev->gen != SWITCHTEC_GEN3)413		return sysfs_emit(buf, "none\n");414 415	return sysfs_emit(buf, "PM%04X\n", id);416}417static DEVICE_ATTR_RO(component_id);418 419static ssize_t component_revision_show(struct device *dev,420	struct device_attribute *attr, char *buf)421{422	struct switchtec_dev *stdev = to_stdev(dev);423	int rev = ioread8(&stdev->mmio_sys_info->gen3.component_revision);424 425	/* component_revision field not supported after gen3 */426	if (stdev->gen != SWITCHTEC_GEN3)427		return sysfs_emit(buf, "255\n");428 429	return sysfs_emit(buf, "%d\n", rev);430}431static DEVICE_ATTR_RO(component_revision);432 433static ssize_t partition_show(struct device *dev,434	struct device_attribute *attr, char *buf)435{436	struct switchtec_dev *stdev = to_stdev(dev);437 438	return sysfs_emit(buf, "%d\n", stdev->partition);439}440static DEVICE_ATTR_RO(partition);441 442static ssize_t partition_count_show(struct device *dev,443	struct device_attribute *attr, char *buf)444{445	struct switchtec_dev *stdev = to_stdev(dev);446 447	return sysfs_emit(buf, "%d\n", stdev->partition_count);448}449static DEVICE_ATTR_RO(partition_count);450 451static struct attribute *switchtec_device_attrs[] = {452	&dev_attr_device_version.attr,453	&dev_attr_fw_version.attr,454	&dev_attr_vendor_id.attr,455	&dev_attr_product_id.attr,456	&dev_attr_product_revision.attr,457	&dev_attr_component_vendor.attr,458	&dev_attr_component_id.attr,459	&dev_attr_component_revision.attr,460	&dev_attr_partition.attr,461	&dev_attr_partition_count.attr,462	NULL,463};464 465ATTRIBUTE_GROUPS(switchtec_device);466 467static int switchtec_dev_open(struct inode *inode, struct file *filp)468{469	struct switchtec_dev *stdev;470	struct switchtec_user *stuser;471 472	stdev = container_of(inode->i_cdev, struct switchtec_dev, cdev);473 474	stuser = stuser_create(stdev);475	if (IS_ERR(stuser))476		return PTR_ERR(stuser);477 478	filp->private_data = stuser;479	stream_open(inode, filp);480 481	dev_dbg(&stdev->dev, "%s: %p\n", __func__, stuser);482 483	return 0;484}485 486static int switchtec_dev_release(struct inode *inode, struct file *filp)487{488	struct switchtec_user *stuser = filp->private_data;489 490	stuser_put(stuser);491 492	return 0;493}494 495static int lock_mutex_and_test_alive(struct switchtec_dev *stdev)496{497	if (mutex_lock_interruptible(&stdev->mrpc_mutex))498		return -EINTR;499 500	if (!stdev->alive) {501		mutex_unlock(&stdev->mrpc_mutex);502		return -ENODEV;503	}504 505	return 0;506}507 508static ssize_t switchtec_dev_write(struct file *filp, const char __user *data,509				   size_t size, loff_t *off)510{511	struct switchtec_user *stuser = filp->private_data;512	struct switchtec_dev *stdev = stuser->stdev;513	int rc;514 515	if (size < sizeof(stuser->cmd) ||516	    size > sizeof(stuser->cmd) + sizeof(stuser->data))517		return -EINVAL;518 519	stuser->data_len = size - sizeof(stuser->cmd);520 521	rc = lock_mutex_and_test_alive(stdev);522	if (rc)523		return rc;524 525	if (stuser->state != MRPC_IDLE) {526		rc = -EBADE;527		goto out;528	}529 530	rc = copy_from_user(&stuser->cmd, data, sizeof(stuser->cmd));531	if (rc) {532		rc = -EFAULT;533		goto out;534	}535	if (((MRPC_CMD_ID(stuser->cmd) == MRPC_GAS_WRITE) ||536	     (MRPC_CMD_ID(stuser->cmd) == MRPC_GAS_READ)) &&537	    !capable(CAP_SYS_ADMIN)) {538		rc = -EPERM;539		goto out;540	}541 542	data += sizeof(stuser->cmd);543	rc = copy_from_user(&stuser->data, data, size - sizeof(stuser->cmd));544	if (rc) {545		rc = -EFAULT;546		goto out;547	}548 549	rc = mrpc_queue_cmd(stuser);550 551out:552	mutex_unlock(&stdev->mrpc_mutex);553 554	if (rc)555		return rc;556 557	return size;558}559 560static ssize_t switchtec_dev_read(struct file *filp, char __user *data,561				  size_t size, loff_t *off)562{563	struct switchtec_user *stuser = filp->private_data;564	struct switchtec_dev *stdev = stuser->stdev;565	int rc;566 567	if (size < sizeof(stuser->cmd) ||568	    size > sizeof(stuser->cmd) + sizeof(stuser->data))569		return -EINVAL;570 571	rc = lock_mutex_and_test_alive(stdev);572	if (rc)573		return rc;574 575	if (stuser->state == MRPC_IDLE) {576		mutex_unlock(&stdev->mrpc_mutex);577		return -EBADE;578	}579 580	stuser->read_len = size - sizeof(stuser->return_code);581 582	mutex_unlock(&stdev->mrpc_mutex);583 584	if (filp->f_flags & O_NONBLOCK) {585		if (!stuser->cmd_done)586			return -EAGAIN;587	} else {588		rc = wait_event_interruptible(stuser->cmd_comp,589					      stuser->cmd_done);590		if (rc < 0)591			return rc;592	}593 594	rc = lock_mutex_and_test_alive(stdev);595	if (rc)596		return rc;597 598	if (stuser->state == MRPC_IO_ERROR) {599		mutex_unlock(&stdev->mrpc_mutex);600		return -EIO;601	}602 603	if (stuser->state != MRPC_DONE) {604		mutex_unlock(&stdev->mrpc_mutex);605		return -EBADE;606	}607 608	rc = copy_to_user(data, &stuser->return_code,609			  sizeof(stuser->return_code));610	if (rc) {611		mutex_unlock(&stdev->mrpc_mutex);612		return -EFAULT;613	}614 615	data += sizeof(stuser->return_code);616	rc = copy_to_user(data, &stuser->data,617			  size - sizeof(stuser->return_code));618	if (rc) {619		mutex_unlock(&stdev->mrpc_mutex);620		return -EFAULT;621	}622 623	stuser_set_state(stuser, MRPC_IDLE);624 625	mutex_unlock(&stdev->mrpc_mutex);626 627	if (stuser->status == SWITCHTEC_MRPC_STATUS_DONE ||628	    stuser->status == SWITCHTEC_MRPC_STATUS_ERROR)629		return size;630	else if (stuser->status == SWITCHTEC_MRPC_STATUS_INTERRUPTED)631		return -ENXIO;632	else633		return -EBADMSG;634}635 636static __poll_t switchtec_dev_poll(struct file *filp, poll_table *wait)637{638	struct switchtec_user *stuser = filp->private_data;639	struct switchtec_dev *stdev = stuser->stdev;640	__poll_t ret = 0;641 642	poll_wait(filp, &stuser->cmd_comp, wait);643	poll_wait(filp, &stdev->event_wq, wait);644 645	if (lock_mutex_and_test_alive(stdev))646		return EPOLLIN | EPOLLRDHUP | EPOLLOUT | EPOLLERR | EPOLLHUP;647 648	mutex_unlock(&stdev->mrpc_mutex);649 650	if (stuser->cmd_done)651		ret |= EPOLLIN | EPOLLRDNORM;652 653	if (stuser->event_cnt != atomic_read(&stdev->event_cnt))654		ret |= EPOLLPRI | EPOLLRDBAND;655 656	return ret;657}658 659static int ioctl_flash_info(struct switchtec_dev *stdev,660			    struct switchtec_ioctl_flash_info __user *uinfo)661{662	struct switchtec_ioctl_flash_info info = {0};663	struct flash_info_regs __iomem *fi = stdev->mmio_flash_info;664 665	if (stdev->gen == SWITCHTEC_GEN3) {666		info.flash_length = ioread32(&fi->gen3.flash_length);667		info.num_partitions = SWITCHTEC_NUM_PARTITIONS_GEN3;668	} else if (stdev->gen >= SWITCHTEC_GEN4) {669		info.flash_length = ioread32(&fi->gen4.flash_length);670		info.num_partitions = SWITCHTEC_NUM_PARTITIONS_GEN4;671	} else {672		return -EOPNOTSUPP;673	}674 675	if (copy_to_user(uinfo, &info, sizeof(info)))676		return -EFAULT;677 678	return 0;679}680 681static void set_fw_info_part(struct switchtec_ioctl_flash_part_info *info,682			     struct partition_info __iomem *pi)683{684	info->address = ioread32(&pi->address);685	info->length = ioread32(&pi->length);686}687 688static int flash_part_info_gen3(struct switchtec_dev *stdev,689		struct switchtec_ioctl_flash_part_info *info)690{691	struct flash_info_regs_gen3 __iomem *fi =692		&stdev->mmio_flash_info->gen3;693	struct sys_info_regs_gen3 __iomem *si = &stdev->mmio_sys_info->gen3;694	u32 active_addr = -1;695 696	switch (info->flash_partition) {697	case SWITCHTEC_IOCTL_PART_CFG0:698		active_addr = ioread32(&fi->active_cfg);699		set_fw_info_part(info, &fi->cfg0);700		if (ioread16(&si->cfg_running) == SWITCHTEC_GEN3_CFG0_RUNNING)701			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;702		break;703	case SWITCHTEC_IOCTL_PART_CFG1:704		active_addr = ioread32(&fi->active_cfg);705		set_fw_info_part(info, &fi->cfg1);706		if (ioread16(&si->cfg_running) == SWITCHTEC_GEN3_CFG1_RUNNING)707			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;708		break;709	case SWITCHTEC_IOCTL_PART_IMG0:710		active_addr = ioread32(&fi->active_img);711		set_fw_info_part(info, &fi->img0);712		if (ioread16(&si->img_running) == SWITCHTEC_GEN3_IMG0_RUNNING)713			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;714		break;715	case SWITCHTEC_IOCTL_PART_IMG1:716		active_addr = ioread32(&fi->active_img);717		set_fw_info_part(info, &fi->img1);718		if (ioread16(&si->img_running) == SWITCHTEC_GEN3_IMG1_RUNNING)719			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;720		break;721	case SWITCHTEC_IOCTL_PART_NVLOG:722		set_fw_info_part(info, &fi->nvlog);723		break;724	case SWITCHTEC_IOCTL_PART_VENDOR0:725		set_fw_info_part(info, &fi->vendor[0]);726		break;727	case SWITCHTEC_IOCTL_PART_VENDOR1:728		set_fw_info_part(info, &fi->vendor[1]);729		break;730	case SWITCHTEC_IOCTL_PART_VENDOR2:731		set_fw_info_part(info, &fi->vendor[2]);732		break;733	case SWITCHTEC_IOCTL_PART_VENDOR3:734		set_fw_info_part(info, &fi->vendor[3]);735		break;736	case SWITCHTEC_IOCTL_PART_VENDOR4:737		set_fw_info_part(info, &fi->vendor[4]);738		break;739	case SWITCHTEC_IOCTL_PART_VENDOR5:740		set_fw_info_part(info, &fi->vendor[5]);741		break;742	case SWITCHTEC_IOCTL_PART_VENDOR6:743		set_fw_info_part(info, &fi->vendor[6]);744		break;745	case SWITCHTEC_IOCTL_PART_VENDOR7:746		set_fw_info_part(info, &fi->vendor[7]);747		break;748	default:749		return -EINVAL;750	}751 752	if (info->address == active_addr)753		info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;754 755	return 0;756}757 758static int flash_part_info_gen4(struct switchtec_dev *stdev,759		struct switchtec_ioctl_flash_part_info *info)760{761	struct flash_info_regs_gen4 __iomem *fi = &stdev->mmio_flash_info->gen4;762	struct sys_info_regs_gen4 __iomem *si = &stdev->mmio_sys_info->gen4;763	struct active_partition_info_gen4 __iomem *af = &fi->active_flag;764 765	switch (info->flash_partition) {766	case SWITCHTEC_IOCTL_PART_MAP_0:767		set_fw_info_part(info, &fi->map0);768		break;769	case SWITCHTEC_IOCTL_PART_MAP_1:770		set_fw_info_part(info, &fi->map1);771		break;772	case SWITCHTEC_IOCTL_PART_KEY_0:773		set_fw_info_part(info, &fi->key0);774		if (ioread8(&af->key) == SWITCHTEC_GEN4_KEY0_ACTIVE)775			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;776		if (ioread16(&si->key_running) == SWITCHTEC_GEN4_KEY0_RUNNING)777			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;778		break;779	case SWITCHTEC_IOCTL_PART_KEY_1:780		set_fw_info_part(info, &fi->key1);781		if (ioread8(&af->key) == SWITCHTEC_GEN4_KEY1_ACTIVE)782			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;783		if (ioread16(&si->key_running) == SWITCHTEC_GEN4_KEY1_RUNNING)784			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;785		break;786	case SWITCHTEC_IOCTL_PART_BL2_0:787		set_fw_info_part(info, &fi->bl2_0);788		if (ioread8(&af->bl2) == SWITCHTEC_GEN4_BL2_0_ACTIVE)789			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;790		if (ioread16(&si->bl2_running) == SWITCHTEC_GEN4_BL2_0_RUNNING)791			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;792		break;793	case SWITCHTEC_IOCTL_PART_BL2_1:794		set_fw_info_part(info, &fi->bl2_1);795		if (ioread8(&af->bl2) == SWITCHTEC_GEN4_BL2_1_ACTIVE)796			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;797		if (ioread16(&si->bl2_running) == SWITCHTEC_GEN4_BL2_1_RUNNING)798			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;799		break;800	case SWITCHTEC_IOCTL_PART_CFG0:801		set_fw_info_part(info, &fi->cfg0);802		if (ioread8(&af->cfg) == SWITCHTEC_GEN4_CFG0_ACTIVE)803			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;804		if (ioread16(&si->cfg_running) == SWITCHTEC_GEN4_CFG0_RUNNING)805			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;806		break;807	case SWITCHTEC_IOCTL_PART_CFG1:808		set_fw_info_part(info, &fi->cfg1);809		if (ioread8(&af->cfg) == SWITCHTEC_GEN4_CFG1_ACTIVE)810			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;811		if (ioread16(&si->cfg_running) == SWITCHTEC_GEN4_CFG1_RUNNING)812			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;813		break;814	case SWITCHTEC_IOCTL_PART_IMG0:815		set_fw_info_part(info, &fi->img0);816		if (ioread8(&af->img) == SWITCHTEC_GEN4_IMG0_ACTIVE)817			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;818		if (ioread16(&si->img_running) == SWITCHTEC_GEN4_IMG0_RUNNING)819			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;820		break;821	case SWITCHTEC_IOCTL_PART_IMG1:822		set_fw_info_part(info, &fi->img1);823		if (ioread8(&af->img) == SWITCHTEC_GEN4_IMG1_ACTIVE)824			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;825		if (ioread16(&si->img_running) == SWITCHTEC_GEN4_IMG1_RUNNING)826			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;827		break;828	case SWITCHTEC_IOCTL_PART_NVLOG:829		set_fw_info_part(info, &fi->nvlog);830		break;831	case SWITCHTEC_IOCTL_PART_VENDOR0:832		set_fw_info_part(info, &fi->vendor[0]);833		break;834	case SWITCHTEC_IOCTL_PART_VENDOR1:835		set_fw_info_part(info, &fi->vendor[1]);836		break;837	case SWITCHTEC_IOCTL_PART_VENDOR2:838		set_fw_info_part(info, &fi->vendor[2]);839		break;840	case SWITCHTEC_IOCTL_PART_VENDOR3:841		set_fw_info_part(info, &fi->vendor[3]);842		break;843	case SWITCHTEC_IOCTL_PART_VENDOR4:844		set_fw_info_part(info, &fi->vendor[4]);845		break;846	case SWITCHTEC_IOCTL_PART_VENDOR5:847		set_fw_info_part(info, &fi->vendor[5]);848		break;849	case SWITCHTEC_IOCTL_PART_VENDOR6:850		set_fw_info_part(info, &fi->vendor[6]);851		break;852	case SWITCHTEC_IOCTL_PART_VENDOR7:853		set_fw_info_part(info, &fi->vendor[7]);854		break;855	default:856		return -EINVAL;857	}858 859	return 0;860}861 862static int ioctl_flash_part_info(struct switchtec_dev *stdev,863		struct switchtec_ioctl_flash_part_info __user *uinfo)864{865	int ret;866	struct switchtec_ioctl_flash_part_info info = {0};867 868	if (copy_from_user(&info, uinfo, sizeof(info)))869		return -EFAULT;870 871	if (stdev->gen == SWITCHTEC_GEN3) {872		ret = flash_part_info_gen3(stdev, &info);873		if (ret)874			return ret;875	} else if (stdev->gen >= SWITCHTEC_GEN4) {876		ret = flash_part_info_gen4(stdev, &info);877		if (ret)878			return ret;879	} else {880		return -EOPNOTSUPP;881	}882 883	if (copy_to_user(uinfo, &info, sizeof(info)))884		return -EFAULT;885 886	return 0;887}888 889static int ioctl_event_summary(struct switchtec_dev *stdev,890	struct switchtec_user *stuser,891	struct switchtec_ioctl_event_summary __user *usum,892	size_t size)893{894	struct switchtec_ioctl_event_summary *s;895	int i;896	u32 reg;897	int ret = 0;898 899	s = kzalloc(sizeof(*s), GFP_KERNEL);900	if (!s)901		return -ENOMEM;902 903	s->global = ioread32(&stdev->mmio_sw_event->global_summary);904	s->part_bitmap = ioread64(&stdev->mmio_sw_event->part_event_bitmap);905	s->local_part = ioread32(&stdev->mmio_part_cfg->part_event_summary);906 907	for (i = 0; i < stdev->partition_count; i++) {908		reg = ioread32(&stdev->mmio_part_cfg_all[i].part_event_summary);909		s->part[i] = reg;910	}911 912	for (i = 0; i < stdev->pff_csr_count; i++) {913		reg = ioread32(&stdev->mmio_pff_csr[i].pff_event_summary);914		s->pff[i] = reg;915	}916 917	if (copy_to_user(usum, s, size)) {918		ret = -EFAULT;919		goto error_case;920	}921 922	stuser->event_cnt = atomic_read(&stdev->event_cnt);923 924error_case:925	kfree(s);926	return ret;927}928 929static u32 __iomem *global_ev_reg(struct switchtec_dev *stdev,930				  size_t offset, int index)931{932	return (void __iomem *)stdev->mmio_sw_event + offset;933}934 935static u32 __iomem *part_ev_reg(struct switchtec_dev *stdev,936				size_t offset, int index)937{938	return (void __iomem *)&stdev->mmio_part_cfg_all[index] + offset;939}940 941static u32 __iomem *pff_ev_reg(struct switchtec_dev *stdev,942			       size_t offset, int index)943{944	return (void __iomem *)&stdev->mmio_pff_csr[index] + offset;945}946 947#define EV_GLB(i, r)[i] = {offsetof(struct sw_event_regs, r), global_ev_reg}948#define EV_PAR(i, r)[i] = {offsetof(struct part_cfg_regs, r), part_ev_reg}949#define EV_PFF(i, r)[i] = {offsetof(struct pff_csr_regs, r), pff_ev_reg}950 951static const struct event_reg {952	size_t offset;953	u32 __iomem *(*map_reg)(struct switchtec_dev *stdev,954				size_t offset, int index);955} event_regs[] = {956	EV_GLB(SWITCHTEC_IOCTL_EVENT_STACK_ERROR, stack_error_event_hdr),957	EV_GLB(SWITCHTEC_IOCTL_EVENT_PPU_ERROR, ppu_error_event_hdr),958	EV_GLB(SWITCHTEC_IOCTL_EVENT_ISP_ERROR, isp_error_event_hdr),959	EV_GLB(SWITCHTEC_IOCTL_EVENT_SYS_RESET, sys_reset_event_hdr),960	EV_GLB(SWITCHTEC_IOCTL_EVENT_FW_EXC, fw_exception_hdr),961	EV_GLB(SWITCHTEC_IOCTL_EVENT_FW_NMI, fw_nmi_hdr),962	EV_GLB(SWITCHTEC_IOCTL_EVENT_FW_NON_FATAL, fw_non_fatal_hdr),963	EV_GLB(SWITCHTEC_IOCTL_EVENT_FW_FATAL, fw_fatal_hdr),964	EV_GLB(SWITCHTEC_IOCTL_EVENT_TWI_MRPC_COMP, twi_mrpc_comp_hdr),965	EV_GLB(SWITCHTEC_IOCTL_EVENT_TWI_MRPC_COMP_ASYNC,966	       twi_mrpc_comp_async_hdr),967	EV_GLB(SWITCHTEC_IOCTL_EVENT_CLI_MRPC_COMP, cli_mrpc_comp_hdr),968	EV_GLB(SWITCHTEC_IOCTL_EVENT_CLI_MRPC_COMP_ASYNC,969	       cli_mrpc_comp_async_hdr),970	EV_GLB(SWITCHTEC_IOCTL_EVENT_GPIO_INT, gpio_interrupt_hdr),971	EV_GLB(SWITCHTEC_IOCTL_EVENT_GFMS, gfms_event_hdr),972	EV_PAR(SWITCHTEC_IOCTL_EVENT_PART_RESET, part_reset_hdr),973	EV_PAR(SWITCHTEC_IOCTL_EVENT_MRPC_COMP, mrpc_comp_hdr),974	EV_PAR(SWITCHTEC_IOCTL_EVENT_MRPC_COMP_ASYNC, mrpc_comp_async_hdr),975	EV_PAR(SWITCHTEC_IOCTL_EVENT_DYN_PART_BIND_COMP, dyn_binding_hdr),976	EV_PAR(SWITCHTEC_IOCTL_EVENT_INTERCOMM_REQ_NOTIFY,977	       intercomm_notify_hdr),978	EV_PFF(SWITCHTEC_IOCTL_EVENT_AER_IN_P2P, aer_in_p2p_hdr),979	EV_PFF(SWITCHTEC_IOCTL_EVENT_AER_IN_VEP, aer_in_vep_hdr),980	EV_PFF(SWITCHTEC_IOCTL_EVENT_DPC, dpc_hdr),981	EV_PFF(SWITCHTEC_IOCTL_EVENT_CTS, cts_hdr),982	EV_PFF(SWITCHTEC_IOCTL_EVENT_UEC, uec_hdr),983	EV_PFF(SWITCHTEC_IOCTL_EVENT_HOTPLUG, hotplug_hdr),984	EV_PFF(SWITCHTEC_IOCTL_EVENT_IER, ier_hdr),985	EV_PFF(SWITCHTEC_IOCTL_EVENT_THRESH, threshold_hdr),986	EV_PFF(SWITCHTEC_IOCTL_EVENT_POWER_MGMT, power_mgmt_hdr),987	EV_PFF(SWITCHTEC_IOCTL_EVENT_TLP_THROTTLING, tlp_throttling_hdr),988	EV_PFF(SWITCHTEC_IOCTL_EVENT_FORCE_SPEED, force_speed_hdr),989	EV_PFF(SWITCHTEC_IOCTL_EVENT_CREDIT_TIMEOUT, credit_timeout_hdr),990	EV_PFF(SWITCHTEC_IOCTL_EVENT_LINK_STATE, link_state_hdr),991};992 993static u32 __iomem *event_hdr_addr(struct switchtec_dev *stdev,994				   int event_id, int index)995{996	size_t off;997 998	if (event_id < 0 || event_id >= SWITCHTEC_IOCTL_MAX_EVENTS)999		return (u32 __iomem *)ERR_PTR(-EINVAL);1000 1001	off = event_regs[event_id].offset;1002 1003	if (event_regs[event_id].map_reg == part_ev_reg) {1004		if (index == SWITCHTEC_IOCTL_EVENT_LOCAL_PART_IDX)1005			index = stdev->partition;1006		else if (index < 0 || index >= stdev->partition_count)1007			return (u32 __iomem *)ERR_PTR(-EINVAL);1008	} else if (event_regs[event_id].map_reg == pff_ev_reg) {1009		if (index < 0 || index >= stdev->pff_csr_count)1010			return (u32 __iomem *)ERR_PTR(-EINVAL);1011	}1012 1013	return event_regs[event_id].map_reg(stdev, off, index);1014}1015 1016static int event_ctl(struct switchtec_dev *stdev,1017		     struct switchtec_ioctl_event_ctl *ctl)1018{1019	int i;1020	u32 __iomem *reg;1021	u32 hdr;1022 1023	reg = event_hdr_addr(stdev, ctl->event_id, ctl->index);1024	if (IS_ERR(reg))1025		return PTR_ERR(reg);1026 1027	hdr = ioread32(reg);1028	if (hdr & SWITCHTEC_EVENT_NOT_SUPP)1029		return -EOPNOTSUPP;1030 1031	for (i = 0; i < ARRAY_SIZE(ctl->data); i++)1032		ctl->data[i] = ioread32(&reg[i + 1]);1033 1034	ctl->occurred = hdr & SWITCHTEC_EVENT_OCCURRED;1035	ctl->count = (hdr >> 5) & 0xFF;1036 1037	if (!(ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_CLEAR))1038		hdr &= ~SWITCHTEC_EVENT_CLEAR;1039	if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_EN_POLL)1040		hdr |= SWITCHTEC_EVENT_EN_IRQ;1041	if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_DIS_POLL)1042		hdr &= ~SWITCHTEC_EVENT_EN_IRQ;1043	if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_EN_LOG)1044		hdr |= SWITCHTEC_EVENT_EN_LOG;1045	if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_DIS_LOG)1046		hdr &= ~SWITCHTEC_EVENT_EN_LOG;1047	if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_EN_CLI)1048		hdr |= SWITCHTEC_EVENT_EN_CLI;1049	if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_DIS_CLI)1050		hdr &= ~SWITCHTEC_EVENT_EN_CLI;1051	if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_EN_FATAL)1052		hdr |= SWITCHTEC_EVENT_FATAL;1053	if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_DIS_FATAL)1054		hdr &= ~SWITCHTEC_EVENT_FATAL;1055 1056	if (ctl->flags)1057		iowrite32(hdr, reg);1058 1059	ctl->flags = 0;1060	if (hdr & SWITCHTEC_EVENT_EN_IRQ)1061		ctl->flags |= SWITCHTEC_IOCTL_EVENT_FLAG_EN_POLL;1062	if (hdr & SWITCHTEC_EVENT_EN_LOG)1063		ctl->flags |= SWITCHTEC_IOCTL_EVENT_FLAG_EN_LOG;1064	if (hdr & SWITCHTEC_EVENT_EN_CLI)1065		ctl->flags |= SWITCHTEC_IOCTL_EVENT_FLAG_EN_CLI;1066	if (hdr & SWITCHTEC_EVENT_FATAL)1067		ctl->flags |= SWITCHTEC_IOCTL_EVENT_FLAG_EN_FATAL;1068 1069	return 0;1070}1071 1072static int ioctl_event_ctl(struct switchtec_dev *stdev,1073	struct switchtec_ioctl_event_ctl __user *uctl)1074{1075	int ret;1076	int nr_idxs;1077	unsigned int event_flags;1078	struct switchtec_ioctl_event_ctl ctl;1079 1080	if (copy_from_user(&ctl, uctl, sizeof(ctl)))1081		return -EFAULT;1082 1083	if (ctl.event_id >= SWITCHTEC_IOCTL_MAX_EVENTS)1084		return -EINVAL;1085 1086	if (ctl.flags & SWITCHTEC_IOCTL_EVENT_FLAG_UNUSED)1087		return -EINVAL;1088 1089	if (ctl.index == SWITCHTEC_IOCTL_EVENT_IDX_ALL) {1090		if (event_regs[ctl.event_id].map_reg == global_ev_reg)1091			nr_idxs = 1;1092		else if (event_regs[ctl.event_id].map_reg == part_ev_reg)1093			nr_idxs = stdev->partition_count;1094		else if (event_regs[ctl.event_id].map_reg == pff_ev_reg)1095			nr_idxs = stdev->pff_csr_count;1096		else1097			return -EINVAL;1098 1099		event_flags = ctl.flags;1100		for (ctl.index = 0; ctl.index < nr_idxs; ctl.index++) {1101			ctl.flags = event_flags;1102			ret = event_ctl(stdev, &ctl);1103			if (ret < 0 && ret != -EOPNOTSUPP)1104				return ret;1105		}1106	} else {1107		ret = event_ctl(stdev, &ctl);1108		if (ret < 0)1109			return ret;1110	}1111 1112	if (copy_to_user(uctl, &ctl, sizeof(ctl)))1113		return -EFAULT;1114 1115	return 0;1116}1117 1118static int ioctl_pff_to_port(struct switchtec_dev *stdev,1119			     struct switchtec_ioctl_pff_port __user *up)1120{1121	int i, part;1122	u32 reg;1123	struct part_cfg_regs __iomem *pcfg;1124	struct switchtec_ioctl_pff_port p;1125 1126	if (copy_from_user(&p, up, sizeof(p)))1127		return -EFAULT;1128 1129	p.port = -1;1130	for (part = 0; part < stdev->partition_count; part++) {1131		pcfg = &stdev->mmio_part_cfg_all[part];1132		p.partition = part;1133 1134		reg = ioread32(&pcfg->usp_pff_inst_id);1135		if (reg == p.pff) {1136			p.port = 0;1137			break;1138		}1139 1140		reg = ioread32(&pcfg->vep_pff_inst_id) & 0xFF;1141		if (reg == p.pff) {1142			p.port = SWITCHTEC_IOCTL_PFF_VEP;1143			break;1144		}1145 1146		for (i = 0; i < ARRAY_SIZE(pcfg->dsp_pff_inst_id); i++) {1147			reg = ioread32(&pcfg->dsp_pff_inst_id[i]);1148			if (reg != p.pff)1149				continue;1150 1151			p.port = i + 1;1152			break;1153		}1154 1155		if (p.port != -1)1156			break;1157	}1158 1159	if (copy_to_user(up, &p, sizeof(p)))1160		return -EFAULT;1161 1162	return 0;1163}1164 1165static int ioctl_port_to_pff(struct switchtec_dev *stdev,1166			     struct switchtec_ioctl_pff_port __user *up)1167{1168	struct switchtec_ioctl_pff_port p;1169	struct part_cfg_regs __iomem *pcfg;1170 1171	if (copy_from_user(&p, up, sizeof(p)))1172		return -EFAULT;1173 1174	if (p.partition == SWITCHTEC_IOCTL_EVENT_LOCAL_PART_IDX)1175		pcfg = stdev->mmio_part_cfg;1176	else if (p.partition < stdev->partition_count)1177		pcfg = &stdev->mmio_part_cfg_all[p.partition];1178	else1179		return -EINVAL;1180 1181	switch (p.port) {1182	case 0:1183		p.pff = ioread32(&pcfg->usp_pff_inst_id);1184		break;1185	case SWITCHTEC_IOCTL_PFF_VEP:1186		p.pff = ioread32(&pcfg->vep_pff_inst_id) & 0xFF;1187		break;1188	default:1189		if (p.port > ARRAY_SIZE(pcfg->dsp_pff_inst_id))1190			return -EINVAL;1191		p.port = array_index_nospec(p.port,1192					ARRAY_SIZE(pcfg->dsp_pff_inst_id) + 1);1193		p.pff = ioread32(&pcfg->dsp_pff_inst_id[p.port - 1]);1194		break;1195	}1196 1197	if (copy_to_user(up, &p, sizeof(p)))1198		return -EFAULT;1199 1200	return 0;1201}1202 1203static long switchtec_dev_ioctl(struct file *filp, unsigned int cmd,1204				unsigned long arg)1205{1206	struct switchtec_user *stuser = filp->private_data;1207	struct switchtec_dev *stdev = stuser->stdev;1208	int rc;1209	void __user *argp = (void __user *)arg;1210 1211	rc = lock_mutex_and_test_alive(stdev);1212	if (rc)1213		return rc;1214 1215	switch (cmd) {1216	case SWITCHTEC_IOCTL_FLASH_INFO:1217		rc = ioctl_flash_info(stdev, argp);1218		break;1219	case SWITCHTEC_IOCTL_FLASH_PART_INFO:1220		rc = ioctl_flash_part_info(stdev, argp);1221		break;1222	case SWITCHTEC_IOCTL_EVENT_SUMMARY_LEGACY:1223		rc = ioctl_event_summary(stdev, stuser, argp,1224					 sizeof(struct switchtec_ioctl_event_summary_legacy));1225		break;1226	case SWITCHTEC_IOCTL_EVENT_CTL:1227		rc = ioctl_event_ctl(stdev, argp);1228		break;1229	case SWITCHTEC_IOCTL_PFF_TO_PORT:1230		rc = ioctl_pff_to_port(stdev, argp);1231		break;1232	case SWITCHTEC_IOCTL_PORT_TO_PFF:1233		rc = ioctl_port_to_pff(stdev, argp);1234		break;1235	case SWITCHTEC_IOCTL_EVENT_SUMMARY:1236		rc = ioctl_event_summary(stdev, stuser, argp,1237					 sizeof(struct switchtec_ioctl_event_summary));1238		break;1239	default:1240		rc = -ENOTTY;1241		break;1242	}1243 1244	mutex_unlock(&stdev->mrpc_mutex);1245	return rc;1246}1247 1248static const struct file_operations switchtec_fops = {1249	.owner = THIS_MODULE,1250	.open = switchtec_dev_open,1251	.release = switchtec_dev_release,1252	.write = switchtec_dev_write,1253	.read = switchtec_dev_read,1254	.poll = switchtec_dev_poll,1255	.unlocked_ioctl = switchtec_dev_ioctl,1256	.compat_ioctl = compat_ptr_ioctl,1257};1258 1259static void link_event_work(struct work_struct *work)1260{1261	struct switchtec_dev *stdev;1262 1263	stdev = container_of(work, struct switchtec_dev, link_event_work);1264 1265	if (stdev->link_notifier)1266		stdev->link_notifier(stdev);1267}1268 1269static void check_link_state_events(struct switchtec_dev *stdev)1270{1271	int idx;1272	u32 reg;1273	int count;1274	int occurred = 0;1275 1276	for (idx = 0; idx < stdev->pff_csr_count; idx++) {1277		reg = ioread32(&stdev->mmio_pff_csr[idx].link_state_hdr);1278		dev_dbg(&stdev->dev, "link_state: %d->%08x\n", idx, reg);1279		count = (reg >> 5) & 0xFF;1280 1281		if (count != stdev->link_event_count[idx]) {1282			occurred = 1;1283			stdev->link_event_count[idx] = count;1284		}1285	}1286 1287	if (occurred)1288		schedule_work(&stdev->link_event_work);1289}1290 1291static void enable_link_state_events(struct switchtec_dev *stdev)1292{1293	int idx;1294 1295	for (idx = 0; idx < stdev->pff_csr_count; idx++) {1296		iowrite32(SWITCHTEC_EVENT_CLEAR |1297			  SWITCHTEC_EVENT_EN_IRQ,1298			  &stdev->mmio_pff_csr[idx].link_state_hdr);1299	}1300}1301 1302static void enable_dma_mrpc(struct switchtec_dev *stdev)1303{1304	writeq(stdev->dma_mrpc_dma_addr, &stdev->mmio_mrpc->dma_addr);1305	flush_wc_buf(stdev);1306	iowrite32(SWITCHTEC_DMA_MRPC_EN, &stdev->mmio_mrpc->dma_en);1307}1308 1309static void stdev_release(struct device *dev)1310{1311	struct switchtec_dev *stdev = to_stdev(dev);1312 1313	kfree(stdev);1314}1315 1316static void stdev_kill(struct switchtec_dev *stdev)1317{1318	struct switchtec_user *stuser, *tmpuser;1319 1320	pci_clear_master(stdev->pdev);1321 1322	cancel_delayed_work_sync(&stdev->mrpc_timeout);1323 1324	/* Mark the hardware as unavailable and complete all completions */1325	mutex_lock(&stdev->mrpc_mutex);1326	stdev->alive = false;1327 1328	/* Wake up and kill any users waiting on an MRPC request */1329	list_for_each_entry_safe(stuser, tmpuser, &stdev->mrpc_queue, list) {1330		stuser->cmd_done = true;1331		wake_up_interruptible(&stuser->cmd_comp);1332		list_del_init(&stuser->list);1333		stuser_put(stuser);1334	}1335 1336	mutex_unlock(&stdev->mrpc_mutex);1337 1338	/* Wake up any users waiting on event_wq */1339	wake_up_interruptible(&stdev->event_wq);1340}1341 1342static struct switchtec_dev *stdev_create(struct pci_dev *pdev)1343{1344	struct switchtec_dev *stdev;1345	int minor;1346	struct device *dev;1347	struct cdev *cdev;1348	int rc;1349 1350	stdev = kzalloc_node(sizeof(*stdev), GFP_KERNEL,1351			     dev_to_node(&pdev->dev));1352	if (!stdev)1353		return ERR_PTR(-ENOMEM);1354 1355	stdev->alive = true;1356	stdev->pdev = pci_dev_get(pdev);1357	INIT_LIST_HEAD(&stdev->mrpc_queue);1358	mutex_init(&stdev->mrpc_mutex);1359	stdev->mrpc_busy = 0;1360	INIT_WORK(&stdev->mrpc_work, mrpc_event_work);1361	INIT_DELAYED_WORK(&stdev->mrpc_timeout, mrpc_timeout_work);1362	INIT_WORK(&stdev->link_event_work, link_event_work);1363	init_waitqueue_head(&stdev->event_wq);1364	atomic_set(&stdev->event_cnt, 0);1365 1366	dev = &stdev->dev;1367	device_initialize(dev);1368	dev->class = &switchtec_class;1369	dev->parent = &pdev->dev;1370	dev->groups = switchtec_device_groups;1371	dev->release = stdev_release;1372 1373	minor = ida_alloc(&switchtec_minor_ida, GFP_KERNEL);1374	if (minor < 0) {1375		rc = minor;1376		goto err_put;1377	}1378 1379	dev->devt = MKDEV(MAJOR(switchtec_devt), minor);1380	dev_set_name(dev, "switchtec%d", minor);1381 1382	cdev = &stdev->cdev;1383	cdev_init(cdev, &switchtec_fops);1384	cdev->owner = THIS_MODULE;1385 1386	return stdev;1387 1388err_put:1389	pci_dev_put(stdev->pdev);1390	put_device(&stdev->dev);1391	return ERR_PTR(rc);1392}1393 1394static int mask_event(struct switchtec_dev *stdev, int eid, int idx)1395{1396	size_t off = event_regs[eid].offset;1397	u32 __iomem *hdr_reg;1398	u32 hdr;1399 1400	hdr_reg = event_regs[eid].map_reg(stdev, off, idx);1401	hdr = ioread32(hdr_reg);1402 1403	if (hdr & SWITCHTEC_EVENT_NOT_SUPP)1404		return 0;1405 1406	if (!(hdr & SWITCHTEC_EVENT_OCCURRED && hdr & SWITCHTEC_EVENT_EN_IRQ))1407		return 0;1408 1409	dev_dbg(&stdev->dev, "%s: %d %d %x\n", __func__, eid, idx, hdr);1410	hdr &= ~(SWITCHTEC_EVENT_EN_IRQ | SWITCHTEC_EVENT_OCCURRED);1411	iowrite32(hdr, hdr_reg);1412 1413	return 1;1414}1415 1416static int mask_all_events(struct switchtec_dev *stdev, int eid)1417{1418	int idx;1419	int count = 0;1420 1421	if (event_regs[eid].map_reg == part_ev_reg) {1422		for (idx = 0; idx < stdev->partition_count; idx++)1423			count += mask_event(stdev, eid, idx);1424	} else if (event_regs[eid].map_reg == pff_ev_reg) {1425		for (idx = 0; idx < stdev->pff_csr_count; idx++) {1426			if (!stdev->pff_local[idx])1427				continue;1428 1429			count += mask_event(stdev, eid, idx);1430		}1431	} else {1432		count += mask_event(stdev, eid, 0);1433	}1434 1435	return count;1436}1437 1438static irqreturn_t switchtec_event_isr(int irq, void *dev)1439{1440	struct switchtec_dev *stdev = dev;1441	u32 reg;1442	irqreturn_t ret = IRQ_NONE;1443	int eid, event_count = 0;1444 1445	reg = ioread32(&stdev->mmio_part_cfg->mrpc_comp_hdr);1446	if (reg & SWITCHTEC_EVENT_OCCURRED) {1447		dev_dbg(&stdev->dev, "%s: mrpc comp\n", __func__);1448		ret = IRQ_HANDLED;1449		schedule_work(&stdev->mrpc_work);1450		iowrite32(reg, &stdev->mmio_part_cfg->mrpc_comp_hdr);1451	}1452 1453	check_link_state_events(stdev);1454 1455	for (eid = 0; eid < SWITCHTEC_IOCTL_MAX_EVENTS; eid++) {1456		if (eid == SWITCHTEC_IOCTL_EVENT_LINK_STATE ||1457		    eid == SWITCHTEC_IOCTL_EVENT_MRPC_COMP)1458			continue;1459 1460		event_count += mask_all_events(stdev, eid);1461	}1462 1463	if (event_count) {1464		atomic_inc(&stdev->event_cnt);1465		wake_up_interruptible(&stdev->event_wq);1466		dev_dbg(&stdev->dev, "%s: %d events\n", __func__,1467			event_count);1468		return IRQ_HANDLED;1469	}1470 1471	return ret;1472}1473 1474 1475static irqreturn_t switchtec_dma_mrpc_isr(int irq, void *dev)1476{1477	struct switchtec_dev *stdev = dev;1478 1479	iowrite32(SWITCHTEC_EVENT_CLEAR |1480		  SWITCHTEC_EVENT_EN_IRQ,1481		  &stdev->mmio_part_cfg->mrpc_comp_hdr);1482	schedule_work(&stdev->mrpc_work);1483 1484	return IRQ_HANDLED;1485}1486 1487static int switchtec_init_isr(struct switchtec_dev *stdev)1488{1489	int nvecs;1490	int event_irq;1491	int dma_mrpc_irq;1492	int rc;1493 1494	if (nirqs < 4)1495		nirqs = 4;1496 1497	nvecs = pci_alloc_irq_vectors(stdev->pdev, 1, nirqs,1498				      PCI_IRQ_MSIX | PCI_IRQ_MSI |1499				      PCI_IRQ_VIRTUAL);1500	if (nvecs < 0)1501		return nvecs;1502 1503	event_irq = ioread16(&stdev->mmio_part_cfg->vep_vector_number);1504	if (event_irq < 0 || event_irq >= nvecs)1505		return -EFAULT;1506 1507	event_irq = pci_irq_vector(stdev->pdev, event_irq);1508	if (event_irq < 0)1509		return event_irq;1510 1511	rc = devm_request_irq(&stdev->pdev->dev, event_irq,1512				switchtec_event_isr, 0,1513				KBUILD_MODNAME, stdev);1514 1515	if (rc)1516		return rc;1517 1518	if (!stdev->dma_mrpc)1519		return rc;1520 1521	dma_mrpc_irq = ioread32(&stdev->mmio_mrpc->dma_vector);1522	if (dma_mrpc_irq < 0 || dma_mrpc_irq >= nvecs)1523		return -EFAULT;1524 1525	dma_mrpc_irq  = pci_irq_vector(stdev->pdev, dma_mrpc_irq);1526	if (dma_mrpc_irq < 0)1527		return dma_mrpc_irq;1528 1529	rc = devm_request_irq(&stdev->pdev->dev, dma_mrpc_irq,1530				switchtec_dma_mrpc_isr, 0,1531				KBUILD_MODNAME, stdev);1532 1533	return rc;1534}1535 1536static void init_pff(struct switchtec_dev *stdev)1537{1538	int i;1539	u32 reg;1540	struct part_cfg_regs __iomem *pcfg = stdev->mmio_part_cfg;1541 1542	for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++) {1543		reg = ioread16(&stdev->mmio_pff_csr[i].vendor_id);1544		if (reg != PCI_VENDOR_ID_MICROSEMI)1545			break;1546	}1547 1548	stdev->pff_csr_count = i;1549 1550	reg = ioread32(&pcfg->usp_pff_inst_id);1551	if (reg < stdev->pff_csr_count)1552		stdev->pff_local[reg] = 1;1553 1554	reg = ioread32(&pcfg->vep_pff_inst_id) & 0xFF;1555	if (reg < stdev->pff_csr_count)1556		stdev->pff_local[reg] = 1;1557 1558	for (i = 0; i < ARRAY_SIZE(pcfg->dsp_pff_inst_id); i++) {1559		reg = ioread32(&pcfg->dsp_pff_inst_id[i]);1560		if (reg < stdev->pff_csr_count)1561			stdev->pff_local[reg] = 1;1562	}1563}1564 1565static int switchtec_init_pci(struct switchtec_dev *stdev,1566			      struct pci_dev *pdev)1567{1568	int rc;1569	void __iomem *map;1570	unsigned long res_start, res_len;1571	u32 __iomem *part_id;1572 1573	rc = pcim_enable_device(pdev);1574	if (rc)1575		return rc;1576 1577	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));1578	if (rc)1579		return rc;1580 1581	pci_set_master(pdev);1582 1583	res_start = pci_resource_start(pdev, 0);1584	res_len = pci_resource_len(pdev, 0);1585 1586	if (!devm_request_mem_region(&pdev->dev, res_start,1587				     res_len, KBUILD_MODNAME))1588		return -EBUSY;1589 1590	stdev->mmio_mrpc = devm_ioremap_wc(&pdev->dev, res_start,1591					   SWITCHTEC_GAS_TOP_CFG_OFFSET);1592	if (!stdev->mmio_mrpc)1593		return -ENOMEM;1594 1595	map = devm_ioremap(&pdev->dev,1596			   res_start + SWITCHTEC_GAS_TOP_CFG_OFFSET,1597			   res_len - SWITCHTEC_GAS_TOP_CFG_OFFSET);1598	if (!map)1599		return -ENOMEM;1600 1601	stdev->mmio = map - SWITCHTEC_GAS_TOP_CFG_OFFSET;1602	stdev->mmio_sw_event = stdev->mmio + SWITCHTEC_GAS_SW_EVENT_OFFSET;1603	stdev->mmio_sys_info = stdev->mmio + SWITCHTEC_GAS_SYS_INFO_OFFSET;1604	stdev->mmio_flash_info = stdev->mmio + SWITCHTEC_GAS_FLASH_INFO_OFFSET;1605	stdev->mmio_ntb = stdev->mmio + SWITCHTEC_GAS_NTB_OFFSET;1606 1607	if (stdev->gen == SWITCHTEC_GEN3)1608		part_id = &stdev->mmio_sys_info->gen3.partition_id;1609	else if (stdev->gen >= SWITCHTEC_GEN4)1610		part_id = &stdev->mmio_sys_info->gen4.partition_id;1611	else1612		return -EOPNOTSUPP;1613 1614	stdev->partition = ioread8(part_id);1615	stdev->partition_count = ioread8(&stdev->mmio_ntb->partition_count);1616	stdev->mmio_part_cfg_all = stdev->mmio + SWITCHTEC_GAS_PART_CFG_OFFSET;1617	stdev->mmio_part_cfg = &stdev->mmio_part_cfg_all[stdev->partition];1618	stdev->mmio_pff_csr = stdev->mmio + SWITCHTEC_GAS_PFF_CSR_OFFSET;1619 1620	if (stdev->partition_count < 1)1621		stdev->partition_count = 1;1622 1623	init_pff(stdev);1624 1625	pci_set_drvdata(pdev, stdev);1626 1627	if (!use_dma_mrpc)1628		return 0;1629 1630	if (ioread32(&stdev->mmio_mrpc->dma_ver) == 0)1631		return 0;1632 1633	stdev->dma_mrpc = dma_alloc_coherent(&stdev->pdev->dev,1634					     sizeof(*stdev->dma_mrpc),1635					     &stdev->dma_mrpc_dma_addr,1636					     GFP_KERNEL);1637	if (stdev->dma_mrpc == NULL)1638		return -ENOMEM;1639 1640	return 0;1641}1642 1643static void switchtec_exit_pci(struct switchtec_dev *stdev)1644{1645	if (stdev->dma_mrpc) {1646		iowrite32(0, &stdev->mmio_mrpc->dma_en);1647		flush_wc_buf(stdev);1648		writeq(0, &stdev->mmio_mrpc->dma_addr);1649		dma_free_coherent(&stdev->pdev->dev, sizeof(*stdev->dma_mrpc),1650				  stdev->dma_mrpc, stdev->dma_mrpc_dma_addr);1651		stdev->dma_mrpc = NULL;1652	}1653}1654 1655static int switchtec_pci_probe(struct pci_dev *pdev,1656			       const struct pci_device_id *id)1657{1658	struct switchtec_dev *stdev;1659	int rc;1660 1661	if (pdev->class == (PCI_CLASS_BRIDGE_OTHER << 8))1662		request_module_nowait("ntb_hw_switchtec");1663 1664	stdev = stdev_create(pdev);1665	if (IS_ERR(stdev))1666		return PTR_ERR(stdev);1667 1668	stdev->gen = id->driver_data;1669 1670	rc = switchtec_init_pci(stdev, pdev);1671	if (rc)1672		goto err_put;1673 1674	rc = switchtec_init_isr(stdev);1675	if (rc) {1676		dev_err(&stdev->dev, "failed to init isr.\n");1677		goto err_exit_pci;1678	}1679 1680	iowrite32(SWITCHTEC_EVENT_CLEAR |1681		  SWITCHTEC_EVENT_EN_IRQ,1682		  &stdev->mmio_part_cfg->mrpc_comp_hdr);1683	enable_link_state_events(stdev);1684 1685	if (stdev->dma_mrpc)1686		enable_dma_mrpc(stdev);1687 1688	rc = cdev_device_add(&stdev->cdev, &stdev->dev);1689	if (rc)1690		goto err_devadd;1691 1692	dev_info(&stdev->dev, "Management device registered.\n");1693 1694	return 0;1695 1696err_devadd:1697	stdev_kill(stdev);1698err_exit_pci:1699	switchtec_exit_pci(stdev);1700err_put:1701	ida_free(&switchtec_minor_ida, MINOR(stdev->dev.devt));1702	put_device(&stdev->dev);1703	return rc;1704}1705 1706static void switchtec_pci_remove(struct pci_dev *pdev)1707{1708	struct switchtec_dev *stdev = pci_get_drvdata(pdev);1709 1710	pci_set_drvdata(pdev, NULL);1711 1712	cdev_device_del(&stdev->cdev, &stdev->dev);1713	ida_free(&switchtec_minor_ida, MINOR(stdev->dev.devt));1714	dev_info(&stdev->dev, "unregistered.\n");1715	stdev_kill(stdev);1716	switchtec_exit_pci(stdev);1717	pci_dev_put(stdev->pdev);1718	stdev->pdev = NULL;1719	put_device(&stdev->dev);1720}1721 1722#define SWITCHTEC_PCI_DEVICE(device_id, gen) \1723	{ \1724		.vendor     = PCI_VENDOR_ID_MICROSEMI, \1725		.device     = device_id, \1726		.subvendor  = PCI_ANY_ID, \1727		.subdevice  = PCI_ANY_ID, \1728		.class      = (PCI_CLASS_MEMORY_OTHER << 8), \1729		.class_mask = 0xFFFFFFFF, \1730		.driver_data = gen, \1731	}, \1732	{ \1733		.vendor     = PCI_VENDOR_ID_MICROSEMI, \1734		.device     = device_id, \1735		.subvendor  = PCI_ANY_ID, \1736		.subdevice  = PCI_ANY_ID, \1737		.class      = (PCI_CLASS_BRIDGE_OTHER << 8), \1738		.class_mask = 0xFFFFFFFF, \1739		.driver_data = gen, \1740	}1741 1742static const struct pci_device_id switchtec_pci_tbl[] = {1743	SWITCHTEC_PCI_DEVICE(0x8531, SWITCHTEC_GEN3),  /* PFX 24xG3 */1744	SWITCHTEC_PCI_DEVICE(0x8532, SWITCHTEC_GEN3),  /* PFX 32xG3 */1745	SWITCHTEC_PCI_DEVICE(0x8533, SWITCHTEC_GEN3),  /* PFX 48xG3 */1746	SWITCHTEC_PCI_DEVICE(0x8534, SWITCHTEC_GEN3),  /* PFX 64xG3 */1747	SWITCHTEC_PCI_DEVICE(0x8535, SWITCHTEC_GEN3),  /* PFX 80xG3 */1748	SWITCHTEC_PCI_DEVICE(0x8536, SWITCHTEC_GEN3),  /* PFX 96xG3 */1749	SWITCHTEC_PCI_DEVICE(0x8541, SWITCHTEC_GEN3),  /* PSX 24xG3 */1750	SWITCHTEC_PCI_DEVICE(0x8542, SWITCHTEC_GEN3),  /* PSX 32xG3 */1751	SWITCHTEC_PCI_DEVICE(0x8543, SWITCHTEC_GEN3),  /* PSX 48xG3 */1752	SWITCHTEC_PCI_DEVICE(0x8544, SWITCHTEC_GEN3),  /* PSX 64xG3 */1753	SWITCHTEC_PCI_DEVICE(0x8545, SWITCHTEC_GEN3),  /* PSX 80xG3 */1754	SWITCHTEC_PCI_DEVICE(0x8546, SWITCHTEC_GEN3),  /* PSX 96xG3 */1755	SWITCHTEC_PCI_DEVICE(0x8551, SWITCHTEC_GEN3),  /* PAX 24XG3 */1756	SWITCHTEC_PCI_DEVICE(0x8552, SWITCHTEC_GEN3),  /* PAX 32XG3 */1757	SWITCHTEC_PCI_DEVICE(0x8553, SWITCHTEC_GEN3),  /* PAX 48XG3 */1758	SWITCHTEC_PCI_DEVICE(0x8554, SWITCHTEC_GEN3),  /* PAX 64XG3 */1759	SWITCHTEC_PCI_DEVICE(0x8555, SWITCHTEC_GEN3),  /* PAX 80XG3 */1760	SWITCHTEC_PCI_DEVICE(0x8556, SWITCHTEC_GEN3),  /* PAX 96XG3 */1761	SWITCHTEC_PCI_DEVICE(0x8561, SWITCHTEC_GEN3),  /* PFXL 24XG3 */1762	SWITCHTEC_PCI_DEVICE(0x8562, SWITCHTEC_GEN3),  /* PFXL 32XG3 */1763	SWITCHTEC_PCI_DEVICE(0x8563, SWITCHTEC_GEN3),  /* PFXL 48XG3 */1764	SWITCHTEC_PCI_DEVICE(0x8564, SWITCHTEC_GEN3),  /* PFXL 64XG3 */1765	SWITCHTEC_PCI_DEVICE(0x8565, SWITCHTEC_GEN3),  /* PFXL 80XG3 */1766	SWITCHTEC_PCI_DEVICE(0x8566, SWITCHTEC_GEN3),  /* PFXL 96XG3 */1767	SWITCHTEC_PCI_DEVICE(0x8571, SWITCHTEC_GEN3),  /* PFXI 24XG3 */1768	SWITCHTEC_PCI_DEVICE(0x8572, SWITCHTEC_GEN3),  /* PFXI 32XG3 */1769	SWITCHTEC_PCI_DEVICE(0x8573, SWITCHTEC_GEN3),  /* PFXI 48XG3 */1770	SWITCHTEC_PCI_DEVICE(0x8574, SWITCHTEC_GEN3),  /* PFXI 64XG3 */1771	SWITCHTEC_PCI_DEVICE(0x8575, SWITCHTEC_GEN3),  /* PFXI 80XG3 */1772	SWITCHTEC_PCI_DEVICE(0x8576, SWITCHTEC_GEN3),  /* PFXI 96XG3 */1773	SWITCHTEC_PCI_DEVICE(0x4000, SWITCHTEC_GEN4),  /* PFX 100XG4 */1774	SWITCHTEC_PCI_DEVICE(0x4084, SWITCHTEC_GEN4),  /* PFX 84XG4 */1775	SWITCHTEC_PCI_DEVICE(0x4068, SWITCHTEC_GEN4),  /* PFX 68XG4 */1776	SWITCHTEC_PCI_DEVICE(0x4052, SWITCHTEC_GEN4),  /* PFX 52XG4 */1777	SWITCHTEC_PCI_DEVICE(0x4036, SWITCHTEC_GEN4),  /* PFX 36XG4 */1778	SWITCHTEC_PCI_DEVICE(0x4028, SWITCHTEC_GEN4),  /* PFX 28XG4 */1779	SWITCHTEC_PCI_DEVICE(0x4100, SWITCHTEC_GEN4),  /* PSX 100XG4 */1780	SWITCHTEC_PCI_DEVICE(0x4184, SWITCHTEC_GEN4),  /* PSX 84XG4 */1781	SWITCHTEC_PCI_DEVICE(0x4168, SWITCHTEC_GEN4),  /* PSX 68XG4 */1782	SWITCHTEC_PCI_DEVICE(0x4152, SWITCHTEC_GEN4),  /* PSX 52XG4 */1783	SWITCHTEC_PCI_DEVICE(0x4136, SWITCHTEC_GEN4),  /* PSX 36XG4 */1784	SWITCHTEC_PCI_DEVICE(0x4128, SWITCHTEC_GEN4),  /* PSX 28XG4 */1785	SWITCHTEC_PCI_DEVICE(0x4200, SWITCHTEC_GEN4),  /* PAX 100XG4 */1786	SWITCHTEC_PCI_DEVICE(0x4284, SWITCHTEC_GEN4),  /* PAX 84XG4 */1787	SWITCHTEC_PCI_DEVICE(0x4268, SWITCHTEC_GEN4),  /* PAX 68XG4 */1788	SWITCHTEC_PCI_DEVICE(0x4252, SWITCHTEC_GEN4),  /* PAX 52XG4 */1789	SWITCHTEC_PCI_DEVICE(0x4236, SWITCHTEC_GEN4),  /* PAX 36XG4 */1790	SWITCHTEC_PCI_DEVICE(0x4228, SWITCHTEC_GEN4),  /* PAX 28XG4 */1791	SWITCHTEC_PCI_DEVICE(0x4352, SWITCHTEC_GEN4),  /* PFXA 52XG4 */1792	SWITCHTEC_PCI_DEVICE(0x4336, SWITCHTEC_GEN4),  /* PFXA 36XG4 */1793	SWITCHTEC_PCI_DEVICE(0x4328, SWITCHTEC_GEN4),  /* PFXA 28XG4 */1794	SWITCHTEC_PCI_DEVICE(0x4452, SWITCHTEC_GEN4),  /* PSXA 52XG4 */1795	SWITCHTEC_PCI_DEVICE(0x4436, SWITCHTEC_GEN4),  /* PSXA 36XG4 */1796	SWITCHTEC_PCI_DEVICE(0x4428, SWITCHTEC_GEN4),  /* PSXA 28XG4 */1797	SWITCHTEC_PCI_DEVICE(0x4552, SWITCHTEC_GEN4),  /* PAXA 52XG4 */1798	SWITCHTEC_PCI_DEVICE(0x4536, SWITCHTEC_GEN4),  /* PAXA 36XG4 */1799	SWITCHTEC_PCI_DEVICE(0x4528, SWITCHTEC_GEN4),  /* PAXA 28XG4 */1800	SWITCHTEC_PCI_DEVICE(0x5000, SWITCHTEC_GEN5),  /* PFX 100XG5 */1801	SWITCHTEC_PCI_DEVICE(0x5084, SWITCHTEC_GEN5),  /* PFX 84XG5 */1802	SWITCHTEC_PCI_DEVICE(0x5068, SWITCHTEC_GEN5),  /* PFX 68XG5 */1803	SWITCHTEC_PCI_DEVICE(0x5052, SWITCHTEC_GEN5),  /* PFX 52XG5 */1804	SWITCHTEC_PCI_DEVICE(0x5036, SWITCHTEC_GEN5),  /* PFX 36XG5 */1805	SWITCHTEC_PCI_DEVICE(0x5028, SWITCHTEC_GEN5),  /* PFX 28XG5 */1806	SWITCHTEC_PCI_DEVICE(0x5100, SWITCHTEC_GEN5),  /* PSX 100XG5 */1807	SWITCHTEC_PCI_DEVICE(0x5184, SWITCHTEC_GEN5),  /* PSX 84XG5 */1808	SWITCHTEC_PCI_DEVICE(0x5168, SWITCHTEC_GEN5),  /* PSX 68XG5 */1809	SWITCHTEC_PCI_DEVICE(0x5152, SWITCHTEC_GEN5),  /* PSX 52XG5 */1810	SWITCHTEC_PCI_DEVICE(0x5136, SWITCHTEC_GEN5),  /* PSX 36XG5 */1811	SWITCHTEC_PCI_DEVICE(0x5128, SWITCHTEC_GEN5),  /* PSX 28XG5 */1812	SWITCHTEC_PCI_DEVICE(0x5200, SWITCHTEC_GEN5),  /* PAX 100XG5 */1813	SWITCHTEC_PCI_DEVICE(0x5284, SWITCHTEC_GEN5),  /* PAX 84XG5 */1814	SWITCHTEC_PCI_DEVICE(0x5268, SWITCHTEC_GEN5),  /* PAX 68XG5 */1815	SWITCHTEC_PCI_DEVICE(0x5252, SWITCHTEC_GEN5),  /* PAX 52XG5 */1816	SWITCHTEC_PCI_DEVICE(0x5236, SWITCHTEC_GEN5),  /* PAX 36XG5 */1817	SWITCHTEC_PCI_DEVICE(0x5228, SWITCHTEC_GEN5),  /* PAX 28XG5 */1818	SWITCHTEC_PCI_DEVICE(0x5300, SWITCHTEC_GEN5),  /* PFXA 100XG5 */1819	SWITCHTEC_PCI_DEVICE(0x5384, SWITCHTEC_GEN5),  /* PFXA 84XG5 */1820	SWITCHTEC_PCI_DEVICE(0x5368, SWITCHTEC_GEN5),  /* PFXA 68XG5 */1821	SWITCHTEC_PCI_DEVICE(0x5352, SWITCHTEC_GEN5),  /* PFXA 52XG5 */1822	SWITCHTEC_PCI_DEVICE(0x5336, SWITCHTEC_GEN5),  /* PFXA 36XG5 */1823	SWITCHTEC_PCI_DEVICE(0x5328, SWITCHTEC_GEN5),  /* PFXA 28XG5 */1824	SWITCHTEC_PCI_DEVICE(0x5400, SWITCHTEC_GEN5),  /* PSXA 100XG5 */1825	SWITCHTEC_PCI_DEVICE(0x5484, SWITCHTEC_GEN5),  /* PSXA 84XG5 */1826	SWITCHTEC_PCI_DEVICE(0x5468, SWITCHTEC_GEN5),  /* PSXA 68XG5 */1827	SWITCHTEC_PCI_DEVICE(0x5452, SWITCHTEC_GEN5),  /* PSXA 52XG5 */1828	SWITCHTEC_PCI_DEVICE(0x5436, SWITCHTEC_GEN5),  /* PSXA 36XG5 */1829	SWITCHTEC_PCI_DEVICE(0x5428, SWITCHTEC_GEN5),  /* PSXA 28XG5 */1830	SWITCHTEC_PCI_DEVICE(0x5500, SWITCHTEC_GEN5),  /* PAXA 100XG5 */1831	SWITCHTEC_PCI_DEVICE(0x5584, SWITCHTEC_GEN5),  /* PAXA 84XG5 */1832	SWITCHTEC_PCI_DEVICE(0x5568, SWITCHTEC_GEN5),  /* PAXA 68XG5 */1833	SWITCHTEC_PCI_DEVICE(0x5552, SWITCHTEC_GEN5),  /* PAXA 52XG5 */1834	SWITCHTEC_PCI_DEVICE(0x5536, SWITCHTEC_GEN5),  /* PAXA 36XG5 */1835	SWITCHTEC_PCI_DEVICE(0x5528, SWITCHTEC_GEN5),  /* PAXA 28XG5 */1836	{0}1837};1838MODULE_DEVICE_TABLE(pci, switchtec_pci_tbl);1839 1840static struct pci_driver switchtec_pci_driver = {1841	.name		= KBUILD_MODNAME,1842	.id_table	= switchtec_pci_tbl,1843	.probe		= switchtec_pci_probe,1844	.remove		= switchtec_pci_remove,1845};1846 1847static int __init switchtec_init(void)1848{1849	int rc;1850 1851	rc = alloc_chrdev_region(&switchtec_devt, 0, max_devices,1852				 "switchtec");1853	if (rc)1854		return rc;1855 1856	rc = class_register(&switchtec_class);1857	if (rc)1858		goto err_create_class;1859 1860	rc = pci_register_driver(&switchtec_pci_driver);1861	if (rc)1862		goto err_pci_register;1863 1864	pr_info(KBUILD_MODNAME ": loaded.\n");1865 1866	return 0;1867 1868err_pci_register:1869	class_unregister(&switchtec_class);1870 1871err_create_class:1872	unregister_chrdev_region(switchtec_devt, max_devices);1873 1874	return rc;1875}1876module_init(switchtec_init);1877 1878static void __exit switchtec_exit(void)1879{1880	pci_unregister_driver(&switchtec_pci_driver);1881	class_unregister(&switchtec_class);1882	unregister_chrdev_region(switchtec_devt, max_devices);1883	ida_destroy(&switchtec_minor_ida);1884 1885	pr_info(KBUILD_MODNAME ": unloaded.\n");1886}1887module_exit(switchtec_exit);1888