Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d578966 authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky
Browse files

s390/pci: split lpf



List pci functions is used to query and iterate over pci functions.
This function currently has 2 users - initial device discovery and
rescan after a machine check. Instead of having a multipurpose
function pass a callback which gets called for each pci function.

Signed-off-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 77e844b9
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -135,7 +135,8 @@ int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64);
int zpci_unregister_ioat(struct zpci_dev *, u8);

/* CLP */
int clp_find_pci_devices(void);
int clp_scan_pci_devices(void);
int clp_rescan_pci_devices(void);
int clp_add_pci_device(u32, u32, int);
int clp_enable_fh(struct zpci_dev *, u8);
int clp_disable_fh(struct zpci_dev *);
@@ -163,7 +164,6 @@ static inline void zpci_exit_slot(struct zpci_dev *zdev) {}
/* Helpers */
struct zpci_dev *get_zdev(struct pci_dev *);
struct zpci_dev *get_zdev_by_fid(u32);
bool zpci_fid_present(u32);

/* sysfs */
int zpci_sysfs_add_device(struct device *);
+1 −6
Original line number Diff line number Diff line
@@ -99,11 +99,6 @@ struct zpci_dev *get_zdev_by_fid(u32 fid)
	return zdev;
}

bool zpci_fid_present(u32 fid)
{
	return (get_zdev_by_fid(fid) != NULL) ? true : false;
}

static struct zpci_dev *get_zdev_by_bus(struct pci_bus *bus)
{
	return (bus && bus->sysdata) ? (struct zpci_dev *) bus->sysdata : NULL;
@@ -926,7 +921,7 @@ static int __init pci_base_init(void)
	if (rc)
		goto out_dma;

	rc = clp_find_pci_devices();
	rc = clp_scan_pci_devices();
	if (rc)
		goto out_find;

+68 −45
Original line number Diff line number Diff line
@@ -36,9 +36,9 @@ static inline u8 clp_instr(void *data)
	return cc;
}

static void *clp_alloc_block(void)
static void *clp_alloc_block(gfp_t gfp_mask)
{
	return (void *) __get_free_pages(GFP_KERNEL, get_order(CLP_BLK_SIZE));
	return (void *) __get_free_pages(gfp_mask, get_order(CLP_BLK_SIZE));
}

static void clp_free_block(void *ptr)
@@ -70,7 +70,7 @@ static int clp_query_pci_fngrp(struct zpci_dev *zdev, u8 pfgid)
	struct clp_req_rsp_query_pci_grp *rrb;
	int rc;

	rrb = clp_alloc_block();
	rrb = clp_alloc_block(GFP_KERNEL);
	if (!rrb)
		return -ENOMEM;

@@ -113,7 +113,7 @@ static int clp_query_pci_fn(struct zpci_dev *zdev, u32 fh)
	struct clp_req_rsp_query_pci *rrb;
	int rc;

	rrb = clp_alloc_block();
	rrb = clp_alloc_block(GFP_KERNEL);
	if (!rrb)
		return -ENOMEM;

@@ -181,7 +181,7 @@ static int clp_set_pci_fn(u32 *fh, u8 nr_dma_as, u8 command)
	struct clp_req_rsp_set_pci *rrb;
	int rc, retries = 1000;

	rrb = clp_alloc_block();
	rrb = clp_alloc_block(GFP_KERNEL);
	if (!rrb)
		return -ENOMEM;

@@ -245,49 +245,12 @@ int clp_disable_fh(struct zpci_dev *zdev)
	return rc;
}

static void clp_check_pcifn_entry(struct clp_fh_list_entry *entry)
static int clp_list_pci(struct clp_req_rsp_list_pci *rrb,
			void (*cb)(struct clp_fh_list_entry *entry))
{
	int present, rc;

	if (!entry->vendor_id)
		return;

	/* TODO: be a little bit more scalable */
	present = zpci_fid_present(entry->fid);

	if (present)
		pr_debug("%s: device %x already present\n", __func__, entry->fid);

	/* skip already used functions */
	if (present && entry->config_state)
		return;

	/* aev 306: function moved to stand-by state */
	if (present && !entry->config_state) {
		/*
		 * The handle is already disabled, that means no iota/irq freeing via
		 * the firmware interfaces anymore. Need to free resources manually
		 * (DMA memory, debug, sysfs)...
		 */
		zpci_stop_device(get_zdev_by_fid(entry->fid));
		return;
	}

	rc = clp_add_pci_device(entry->fid, entry->fh, entry->config_state);
	if (rc)
		pr_err("Failed to add fid: 0x%x\n", entry->fid);
}

int clp_find_pci_devices(void)
{
	struct clp_req_rsp_list_pci *rrb;
	u64 resume_token = 0;
	int entries, i, rc;

	rrb = clp_alloc_block();
	if (!rrb)
		return -ENOMEM;

	do {
		memset(rrb, 0, sizeof(*rrb));
		rrb->request.hdr.len = sizeof(rrb->request);
@@ -316,12 +279,72 @@ int clp_find_pci_devices(void)
		resume_token = rrb->response.resume_token;

		for (i = 0; i < entries; i++)
			clp_check_pcifn_entry(&rrb->response.fh_list[i]);
			cb(&rrb->response.fh_list[i]);
	} while (resume_token);

	pr_debug("Maximum number of supported PCI functions: %u\n",
		rrb->response.max_fn);
out:
	return rc;
}

static void __clp_add(struct clp_fh_list_entry *entry)
{
	if (!entry->vendor_id)
		return;

	clp_add_pci_device(entry->fid, entry->fh, entry->config_state);
}

static void __clp_rescan(struct clp_fh_list_entry *entry)
{
	struct zpci_dev *zdev;

	if (!entry->vendor_id)
		return;

	zdev = get_zdev_by_fid(entry->fid);
	if (!zdev) {
		clp_add_pci_device(entry->fid, entry->fh, entry->config_state);
		return;
	}

	if (!entry->config_state) {
		/*
		 * The handle is already disabled, that means no iota/irq freeing via
		 * the firmware interfaces anymore. Need to free resources manually
		 * (DMA memory, debug, sysfs)...
		 */
		zpci_stop_device(zdev);
	}
}

int clp_scan_pci_devices(void)
{
	struct clp_req_rsp_list_pci *rrb;
	int rc;

	rrb = clp_alloc_block(GFP_KERNEL);
	if (!rrb)
		return -ENOMEM;

	rc = clp_list_pci(rrb, __clp_add);

	clp_free_block(rrb);
	return rc;
}

int clp_rescan_pci_devices(void)
{
	struct clp_req_rsp_list_pci *rrb;
	int rc;

	rrb = clp_alloc_block(GFP_KERNEL);
	if (!rrb)
		return -ENOMEM;

	rc = clp_list_pci(rrb, __clp_rescan);

	clp_free_block(rrb);
	return rc;
}
+1 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ static void zpci_event_log_avail(struct zpci_ccdf_avail *ccdf)
		clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
		break;
	case 0x0306:
		clp_find_pci_devices();
		clp_rescan_pci_devices();
		break;
	default:
		break;