@@ -196,6 +196,17 @@ struct ism_sba {
u16 dmbe_mask[ISM_NR_DMBS];
};
+struct ismvp_dev {
+ struct ism_dev ism;
+ struct ism_sba *sba;
+ dma_addr_t sba_dma_addr;
+ DECLARE_BITMAP(sba_bitmap, ISM_NR_DMBS);
+
+ struct ism_eq *ieq;
+ dma_addr_t ieq_dma_addr;
+ int ieq_idx;
+};
+
#define ISM_CREATE_REQ(dmb, idx, sf, offset) \
((dmb) | (idx) << 24 | (sf) << 23 | (offset))
@@ -84,6 +84,7 @@ static int query_info(struct ism_dev *ism)
static int register_sba(struct ism_dev *ism)
{
+ struct ismvp_dev *ismvp;
union ism_reg_sba cmd;
dma_addr_t dma_handle;
struct ism_sba *sba;
@@ -103,14 +104,16 @@ static int register_sba(struct ism_dev *ism)
return -EIO;
}
- ism->sba = sba;
- ism->sba_dma_addr = dma_handle;
+ ismvp = container_of(ism, struct ismvp_dev, ism);
+ ismvp->sba = sba;
+ ismvp->sba_dma_addr = dma_handle;
return 0;
}
static int register_ieq(struct ism_dev *ism)
{
+ struct ismvp_dev *ismvp = container_of(ism, struct ismvp_dev, ism);
union ism_reg_ieq cmd;
dma_addr_t dma_handle;
struct ism_eq *ieq;
@@ -131,18 +134,19 @@ static int register_ieq(struct ism_dev *ism)
return -EIO;
}
- ism->ieq = ieq;
- ism->ieq_idx = -1;
- ism->ieq_dma_addr = dma_handle;
+ ismvp->ieq = ieq;
+ ismvp->ieq_idx = -1;
+ ismvp->ieq_dma_addr = dma_handle;
return 0;
}
static int unregister_sba(struct ism_dev *ism)
{
+ struct ismvp_dev *ismvp = container_of(ism, struct ismvp_dev, ism);
int ret;
- if (!ism->sba)
+ if (!ismvp->sba)
return 0;
ret = ism_cmd_simple(ism, ISM_UNREG_SBA);
@@ -150,19 +154,20 @@ static int unregister_sba(struct ism_dev *ism)
return -EIO;
dma_free_coherent(ism->dev.parent, PAGE_SIZE,
- ism->sba, ism->sba_dma_addr);
+ ismvp->sba, ismvp->sba_dma_addr);
- ism->sba = NULL;
- ism->sba_dma_addr = 0;
+ ismvp->sba = NULL;
+ ismvp->sba_dma_addr = 0;
return 0;
}
static int unregister_ieq(struct ism_dev *ism)
{
+ struct ismvp_dev *ismvp = container_of(ism, struct ismvp_dev, ism);
int ret;
- if (!ism->ieq)
+ if (!ismvp->ieq)
return 0;
ret = ism_cmd_simple(ism, ISM_UNREG_IEQ);
@@ -170,10 +175,10 @@ static int unregister_ieq(struct ism_dev *ism)
return -EIO;
dma_free_coherent(ism->dev.parent, PAGE_SIZE,
- ism->ieq, ism->ieq_dma_addr);
+ ismvp->ieq, ismvp->ieq_dma_addr);
- ism->ieq = NULL;
- ism->ieq_dma_addr = 0;
+ ismvp->ieq = NULL;
+ ismvp->ieq_dma_addr = 0;
return 0;
}
@@ -215,7 +220,9 @@ static int ism_query_rgid(struct ism_dev *ism, uuid_t *rgid, u32 vid_valid,
static void ism_free_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
{
- clear_bit(dmb->sba_idx, ism->sba_bitmap);
+ struct ismvp_dev *ismvp = container_of(ism, struct ismvp_dev, ism);
+
+ clear_bit(dmb->sba_idx, ismvp->sba_bitmap);
dma_unmap_page(ism->dev.parent, dmb->dma_addr, dmb->dmb_len,
DMA_FROM_DEVICE);
folio_put(virt_to_folio(dmb->cpu_addr));
@@ -223,6 +230,7 @@ static void ism_free_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
{
+ struct ismvp_dev *ismvp = container_of(ism, struct ismvp_dev, ism);
struct folio *folio;
unsigned long bit;
int rc;
@@ -231,7 +239,7 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
return -EINVAL;
if (!dmb->sba_idx) {
- bit = find_next_zero_bit(ism->sba_bitmap, ISM_NR_DMBS,
+ bit = find_next_zero_bit(ismvp->sba_bitmap, ISM_NR_DMBS,
ISM_DMB_BIT_OFFSET);
if (bit == ISM_NR_DMBS)
return -ENOSPC;
@@ -239,7 +247,7 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
dmb->sba_idx = bit;
}
if (dmb->sba_idx < ISM_DMB_BIT_OFFSET ||
- test_and_set_bit(dmb->sba_idx, ism->sba_bitmap))
+ test_and_set_bit(dmb->sba_idx, ismvp->sba_bitmap))
return -EINVAL;
folio = folio_alloc(GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC |
@@ -264,7 +272,7 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
out_free:
kfree(dmb->cpu_addr);
out_bit:
- clear_bit(dmb->sba_idx, ism->sba_bitmap);
+ clear_bit(dmb->sba_idx, ismvp->sba_bitmap);
return rc;
}
@@ -424,15 +432,16 @@ static u16 ism_get_chid(struct ism_dev *ism)
static void ism_handle_event(struct ism_dev *ism)
{
+ struct ismvp_dev *ismvp = container_of(ism, struct ismvp_dev, ism);
struct ism_event *entry;
struct ism_client *clt;
int i;
- while ((ism->ieq_idx + 1) != READ_ONCE(ism->ieq->header.idx)) {
- if (++(ism->ieq_idx) == ARRAY_SIZE(ism->ieq->entry))
- ism->ieq_idx = 0;
+ while ((ismvp->ieq_idx + 1) != READ_ONCE(ismvp->ieq->header.idx)) {
+ if (++ismvp->ieq_idx == ARRAY_SIZE(ismvp->ieq->entry))
+ ismvp->ieq_idx = 0;
- entry = &ism->ieq->entry[ism->ieq_idx];
+ entry = &ismvp->ieq->entry[ismvp->ieq_idx];
debug_event(ism_debug_info, 2, entry, sizeof(*entry));
for (i = 0; i < MAX_CLIENTS; ++i) {
clt = ism->subs[i];
@@ -445,16 +454,19 @@ static void ism_handle_event(struct ism_dev *ism)
static irqreturn_t ism_handle_irq(int irq, void *data)
{
struct ism_dev *ism = data;
+ struct ismvp_dev *ismvp;
unsigned long bit, end;
unsigned long *bv;
u16 dmbemask;
u8 client_id;
- bv = (void *) &ism->sba->dmb_bits[ISM_DMB_WORD_OFFSET];
- end = sizeof(ism->sba->dmb_bits) * BITS_PER_BYTE - ISM_DMB_BIT_OFFSET;
+ ismvp = container_of(ism, struct ismvp_dev, ism);
+
+ bv = (void *)&ismvp->sba->dmb_bits[ISM_DMB_WORD_OFFSET];
+ end = sizeof(ismvp->sba->dmb_bits) * BITS_PER_BYTE - ISM_DMB_BIT_OFFSET;
spin_lock(&ism->lock);
- ism->sba->s = 0;
+ ismvp->sba->s = 0;
barrier();
for (bit = 0;;) {
bit = find_next_bit_inv(bv, end, bit);
@@ -462,8 +474,8 @@ static irqreturn_t ism_handle_irq(int irq, void *data)
break;
clear_bit_inv(bit, bv);
- dmbemask = ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET];
- ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET] = 0;
+ dmbemask = ismvp->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET];
+ ismvp->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET] = 0;
barrier();
client_id = ism->sba_client_arr[bit];
if (unlikely(client_id == NO_CLIENT || !ism->subs[client_id]))
@@ -471,8 +483,8 @@ static irqreturn_t ism_handle_irq(int irq, void *data)
ism->subs[client_id]->handle_irq(ism, bit + ISM_DMB_BIT_OFFSET, dmbemask);
}
- if (ism->sba->e) {
- ism->sba->e = 0;
+ if (ismvp->sba->e) {
+ ismvp->sba->e = 0;
barrier();
ism_handle_event(ism);
}
@@ -480,7 +492,7 @@ static irqreturn_t ism_handle_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static const struct ism_ops ism_vp_ops = {
+static const struct ism_ops ismvp_ops = {
.query_remote_gid = ism_query_rgid,
.register_dmb = ism_register_dmb,
.unregister_dmb = ism_unregister_dmb,
@@ -531,7 +543,7 @@ static int ism_dev_init(struct ism_dev *ism)
else
ism_v2_capable = false;
- ism->ops = &ism_vp_ops;
+ ism->ops = &ismvp_ops;
ism_dev_register(ism);
query_info(ism);
@@ -553,12 +565,14 @@ static int ism_dev_init(struct ism_dev *ism)
static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ struct ismvp_dev *ismvp;
struct ism_dev *ism;
int ret;
- ism = kzalloc(sizeof(*ism), GFP_KERNEL);
- if (!ism)
+ ismvp = kzalloc(sizeof(*ismvp), GFP_KERNEL);
+ if (!ismvp)
return -ENOMEM;
+ ism = &ismvp->ism;
spin_lock_init(&ism->lock);
dev_set_drvdata(&pdev->dev, ism);
@@ -599,6 +613,7 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id)
device_del(&ism->dev);
err_dev:
dev_set_drvdata(&pdev->dev, NULL);
+ kfree(ismvp);
return ret;
}
@@ -627,7 +642,11 @@ static void ism_dev_exit(struct ism_dev *ism)
static void ism_remove(struct pci_dev *pdev)
{
- struct ism_dev *ism = dev_get_drvdata(&pdev->dev);
+ struct ismvp_dev *ismvp;
+ struct ism_dev *ism;
+
+ ism = dev_get_drvdata(&pdev->dev);
+ ismvp = container_of(ism, struct ismvp_dev, ism);
ism_dev_exit(ism);
@@ -635,7 +654,7 @@ static void ism_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
device_del(&ism->dev);
dev_set_drvdata(&pdev->dev, NULL);
- kfree(ism);
+ kfree(ismvp);
}
static struct pci_driver ism_driver = {
@@ -281,24 +281,18 @@ struct ism_ops {
struct ism_dev {
const struct ism_ops *ops;
- spinlock_t lock; /* protects the ism device */
struct list_head list;
- struct pci_dev *pdev;
-
- struct ism_sba *sba;
- dma_addr_t sba_dma_addr;
- DECLARE_BITMAP(sba_bitmap, ISM_NR_DMBS);
- u8 *sba_client_arr; /* entries are indices into 'clients' array */
- void *priv[MAX_CLIENTS];
-
- struct ism_eq *ieq;
- dma_addr_t ieq_dma_addr;
-
struct device dev;
uuid_t gid;
- int ieq_idx;
+ /* get this lock before accessing any of the fields below */
+ spinlock_t lock;
+ /* indexed by dmb idx; entries are indices into priv and subs arrays: */
+ u8 *sba_client_arr;
+ /* Sparse array of all ISM clients */
struct ism_client *subs[MAX_CLIENTS];
+ /* priv pointer per client; for client usage only */
+ void *priv[MAX_CLIENTS];
};
int ism_dev_register(struct ism_dev *ism);
Move the fields that are specific to the s390 ism_vpci driver out of the generic ism_dev into a local ismvp_dev structure. Signed-off-by: Alexandra Winter <wintera@linux.ibm.com> --- drivers/s390/net/ism.h | 11 +++++ drivers/s390/net/ism_drv.c | 87 +++++++++++++++++++++++--------------- include/linux/ism.h | 20 +++------ 3 files changed, 71 insertions(+), 47 deletions(-)