aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorey Minyard <cminyard@mvista.com>2017-09-13 00:24:30 -0400
committerCorey Minyard <cminyard@mvista.com>2017-09-28 13:26:00 -0400
commit58e2763553cb837b879d4a2934094e152e7daf27 (patch)
treec7cfd0c210528fcb22cca63bdc1ce7a68b5c3559
parentd1a6791323b810ce9136a58d95c6e0e455313388 (diff)
ipmi_si: Move port and mem I/O handling to their own files
Signed-off-by: Corey Minyard <cminyard@mvista.com>
-rw-r--r--drivers/char/ipmi/Makefile3
-rw-r--r--drivers/char/ipmi/ipmi_si.h3
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c256
-rw-r--r--drivers/char/ipmi/ipmi_si_mem_io.c144
-rw-r--r--drivers/char/ipmi/ipmi_si_port_io.c112
5 files changed, 263 insertions, 255 deletions
diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile
index 3c01149e7d36..312396c1a8e5 100644
--- a/drivers/char/ipmi/Makefile
+++ b/drivers/char/ipmi/Makefile
@@ -3,7 +3,8 @@
3# 3#
4 4
5ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o \ 5ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o \
6 ipmi_si_hotmod.o ipmi_si_hardcode.o ipmi_si_platform.o 6 ipmi_si_hotmod.o ipmi_si_hardcode.o ipmi_si_platform.o \
7 ipmi_si_port_io.o ipmi_si_mem_io.o
7ifdef CONFIG_PCI 8ifdef CONFIG_PCI
8ipmi_si-y += ipmi_si_pci.o 9ipmi_si-y += ipmi_si_pci.o
9endif 10endif
diff --git a/drivers/char/ipmi/ipmi_si.h b/drivers/char/ipmi/ipmi_si.h
index f3530d60db05..17ce5f7b89ab 100644
--- a/drivers/char/ipmi/ipmi_si.h
+++ b/drivers/char/ipmi/ipmi_si.h
@@ -44,3 +44,6 @@ void ipmi_si_parisc_shutdown(void);
44static inline void ipmi_si_parisc_init(void) { } 44static inline void ipmi_si_parisc_init(void) { }
45static inline void ipmi_si_parisc_shutdown(void) { } 45static inline void ipmi_si_parisc_shutdown(void) { }
46#endif 46#endif
47
48int ipmi_si_port_setup(struct si_sm_io *io);
49int ipmi_si_mem_setup(struct si_sm_io *io);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 801ca241b34c..d24cd5de09d0 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -49,7 +49,6 @@
49#include <linux/slab.h> 49#include <linux/slab.h>
50#include <linux/delay.h> 50#include <linux/delay.h>
51#include <linux/list.h> 51#include <linux/list.h>
52#include <linux/ioport.h>
53#include <linux/notifier.h> 52#include <linux/notifier.h>
54#include <linux/mutex.h> 53#include <linux/mutex.h>
55#include <linux/kthread.h> 54#include <linux/kthread.h>
@@ -58,7 +57,6 @@
58#include <linux/rcupdate.h> 57#include <linux/rcupdate.h>
59#include <linux/ipmi.h> 58#include <linux/ipmi.h>
60#include <linux/ipmi_smi.h> 59#include <linux/ipmi_smi.h>
61#include <asm/io.h>
62#include "ipmi_si.h" 60#include "ipmi_si.h"
63#include <linux/string.h> 61#include <linux/string.h>
64#include <linux/ctype.h> 62#include <linux/ctype.h>
@@ -1304,256 +1302,6 @@ int ipmi_std_irq_setup(struct si_sm_io *io)
1304 return rv; 1302 return rv;
1305} 1303}
1306 1304
1307static unsigned char port_inb(const struct si_sm_io *io, unsigned int offset)
1308{
1309 unsigned int addr = io->addr_data;
1310
1311 return inb(addr + (offset * io->regspacing));
1312}
1313
1314static void port_outb(const struct si_sm_io *io, unsigned int offset,
1315 unsigned char b)
1316{
1317 unsigned int addr = io->addr_data;
1318
1319 outb(b, addr + (offset * io->regspacing));
1320}
1321
1322static unsigned char port_inw(const struct si_sm_io *io, unsigned int offset)
1323{
1324 unsigned int addr = io->addr_data;
1325
1326 return (inw(addr + (offset * io->regspacing)) >> io->regshift) & 0xff;
1327}
1328
1329static void port_outw(const struct si_sm_io *io, unsigned int offset,
1330 unsigned char b)
1331{
1332 unsigned int addr = io->addr_data;
1333
1334 outw(b << io->regshift, addr + (offset * io->regspacing));
1335}
1336
1337static unsigned char port_inl(const struct si_sm_io *io, unsigned int offset)
1338{
1339 unsigned int addr = io->addr_data;
1340
1341 return (inl(addr + (offset * io->regspacing)) >> io->regshift) & 0xff;
1342}
1343
1344static void port_outl(const struct si_sm_io *io, unsigned int offset,
1345 unsigned char b)
1346{
1347 unsigned int addr = io->addr_data;
1348
1349 outl(b << io->regshift, addr+(offset * io->regspacing));
1350}
1351
1352static void port_cleanup(struct si_sm_io *io)
1353{
1354 unsigned int addr = io->addr_data;
1355 int idx;
1356
1357 if (addr) {
1358 for (idx = 0; idx < io->io_size; idx++)
1359 release_region(addr + idx * io->regspacing,
1360 io->regsize);
1361 }
1362}
1363
1364static int port_setup(struct si_sm_io *io)
1365{
1366 unsigned int addr = io->addr_data;
1367 int idx;
1368
1369 if (!addr)
1370 return -ENODEV;
1371
1372 io->io_cleanup = port_cleanup;
1373
1374 /*
1375 * Figure out the actual inb/inw/inl/etc routine to use based
1376 * upon the register size.
1377 */
1378 switch (io->regsize) {
1379 case 1:
1380 io->inputb = port_inb;
1381 io->outputb = port_outb;
1382 break;
1383 case 2:
1384 io->inputb = port_inw;
1385 io->outputb = port_outw;
1386 break;
1387 case 4:
1388 io->inputb = port_inl;
1389 io->outputb = port_outl;
1390 break;
1391 default:
1392 dev_warn(io->dev, "Invalid register size: %d\n",
1393 io->regsize);
1394 return -EINVAL;
1395 }
1396
1397 /*
1398 * Some BIOSes reserve disjoint I/O regions in their ACPI
1399 * tables. This causes problems when trying to register the
1400 * entire I/O region. Therefore we must register each I/O
1401 * port separately.
1402 */
1403 for (idx = 0; idx < io->io_size; idx++) {
1404 if (request_region(addr + idx * io->regspacing,
1405 io->regsize, DEVICE_NAME) == NULL) {
1406 /* Undo allocations */
1407 while (idx--)
1408 release_region(addr + idx * io->regspacing,
1409 io->regsize);
1410 return -EIO;
1411 }
1412 }
1413 return 0;
1414}
1415
1416static unsigned char intf_mem_inb(const struct si_sm_io *io,
1417 unsigned int offset)
1418{
1419 return readb((io->addr)+(offset * io->regspacing));
1420}
1421
1422static void intf_mem_outb(const struct si_sm_io *io, unsigned int offset,
1423 unsigned char b)
1424{
1425 writeb(b, (io->addr)+(offset * io->regspacing));
1426}
1427
1428static unsigned char intf_mem_inw(const struct si_sm_io *io,
1429 unsigned int offset)
1430{
1431 return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift)
1432 & 0xff;
1433}
1434
1435static void intf_mem_outw(const struct si_sm_io *io, unsigned int offset,
1436 unsigned char b)
1437{
1438 writeb(b << io->regshift, (io->addr)+(offset * io->regspacing));
1439}
1440
1441static unsigned char intf_mem_inl(const struct si_sm_io *io,
1442 unsigned int offset)
1443{
1444 return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift)
1445 & 0xff;
1446}
1447
1448static void intf_mem_outl(const struct si_sm_io *io, unsigned int offset,
1449 unsigned char b)
1450{
1451 writel(b << io->regshift, (io->addr)+(offset * io->regspacing));
1452}
1453
1454#ifdef readq
1455static unsigned char mem_inq(const struct si_sm_io *io, unsigned int offset)
1456{
1457 return (readq((io->addr)+(offset * io->regspacing)) >> io->regshift)
1458 & 0xff;
1459}
1460
1461static void mem_outq(const struct si_sm_io *io, unsigned int offset,
1462 unsigned char b)
1463{
1464 writeq(b << io->regshift, (io->addr)+(offset * io->regspacing));
1465}
1466#endif
1467
1468static void mem_region_cleanup(struct si_sm_io *io, int num)
1469{
1470 unsigned long addr = io->addr_data;
1471 int idx;
1472
1473 for (idx = 0; idx < num; idx++)
1474 release_mem_region(addr + idx * io->regspacing,
1475 io->regsize);
1476}
1477
1478static void mem_cleanup(struct si_sm_io *io)
1479{
1480 if (io->addr) {
1481 iounmap(io->addr);
1482 mem_region_cleanup(io, io->io_size);
1483 }
1484}
1485
1486static int mem_setup(struct si_sm_io *io)
1487{
1488 unsigned long addr = io->addr_data;
1489 int mapsize, idx;
1490
1491 if (!addr)
1492 return -ENODEV;
1493
1494 io->io_cleanup = mem_cleanup;
1495
1496 /*
1497 * Figure out the actual readb/readw/readl/etc routine to use based
1498 * upon the register size.
1499 */
1500 switch (io->regsize) {
1501 case 1:
1502 io->inputb = intf_mem_inb;
1503 io->outputb = intf_mem_outb;
1504 break;
1505 case 2:
1506 io->inputb = intf_mem_inw;
1507 io->outputb = intf_mem_outw;
1508 break;
1509 case 4:
1510 io->inputb = intf_mem_inl;
1511 io->outputb = intf_mem_outl;
1512 break;
1513#ifdef readq
1514 case 8:
1515 io->inputb = mem_inq;
1516 io->outputb = mem_outq;
1517 break;
1518#endif
1519 default:
1520 dev_warn(io->dev, "Invalid register size: %d\n",
1521 io->regsize);
1522 return -EINVAL;
1523 }
1524
1525 /*
1526 * Some BIOSes reserve disjoint memory regions in their ACPI
1527 * tables. This causes problems when trying to request the
1528 * entire region. Therefore we must request each register
1529 * separately.
1530 */
1531 for (idx = 0; idx < io->io_size; idx++) {
1532 if (request_mem_region(addr + idx * io->regspacing,
1533 io->regsize, DEVICE_NAME) == NULL) {
1534 /* Undo allocations */
1535 mem_region_cleanup(io, idx);
1536 return -EIO;
1537 }
1538 }
1539
1540 /*
1541 * Calculate the total amount of memory to claim. This is an
1542 * unusual looking calculation, but it avoids claiming any
1543 * more memory than it has to. It will claim everything
1544 * between the first address to the end of the last full
1545 * register.
1546 */
1547 mapsize = ((io->io_size * io->regspacing)
1548 - (io->regspacing - io->regsize));
1549 io->addr = ioremap(addr, mapsize);
1550 if (io->addr == NULL) {
1551 mem_region_cleanup(io, io->io_size);
1552 return -EIO;
1553 }
1554 return 0;
1555}
1556
1557static struct smi_info *smi_info_alloc(void) 1305static struct smi_info *smi_info_alloc(void)
1558{ 1306{
1559 struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL); 1307 struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -2146,9 +1894,9 @@ int ipmi_si_add_smi(struct si_sm_io *io)
2146 1894
2147 if (!io->io_setup) { 1895 if (!io->io_setup) {
2148 if (io->addr_type == IPMI_IO_ADDR_SPACE) { 1896 if (io->addr_type == IPMI_IO_ADDR_SPACE) {
2149 io->io_setup = port_setup; 1897 io->io_setup = ipmi_si_port_setup;
2150 } else if (io->addr_type == IPMI_MEM_ADDR_SPACE) { 1898 } else if (io->addr_type == IPMI_MEM_ADDR_SPACE) {
2151 io->io_setup = mem_setup; 1899 io->io_setup = ipmi_si_mem_setup;
2152 } else { 1900 } else {
2153 return -EINVAL; 1901 return -EINVAL;
2154 } 1902 }
diff --git a/drivers/char/ipmi/ipmi_si_mem_io.c b/drivers/char/ipmi/ipmi_si_mem_io.c
new file mode 100644
index 000000000000..8796396ecd0f
--- /dev/null
+++ b/drivers/char/ipmi/ipmi_si_mem_io.c
@@ -0,0 +1,144 @@
1
2#include <linux/io.h>
3#include "ipmi_si.h"
4
5static unsigned char intf_mem_inb(const struct si_sm_io *io,
6 unsigned int offset)
7{
8 return readb((io->addr)+(offset * io->regspacing));
9}
10
11static void intf_mem_outb(const struct si_sm_io *io, unsigned int offset,
12 unsigned char b)
13{
14 writeb(b, (io->addr)+(offset * io->regspacing));
15}
16
17static unsigned char intf_mem_inw(const struct si_sm_io *io,
18 unsigned int offset)
19{
20 return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift)
21 & 0xff;
22}
23
24static void intf_mem_outw(const struct si_sm_io *io, unsigned int offset,
25 unsigned char b)
26{
27 writeb(b << io->regshift, (io->addr)+(offset * io->regspacing));
28}
29
30static unsigned char intf_mem_inl(const struct si_sm_io *io,
31 unsigned int offset)
32{
33 return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift)
34 & 0xff;
35}
36
37static void intf_mem_outl(const struct si_sm_io *io, unsigned int offset,
38 unsigned char b)
39{
40 writel(b << io->regshift, (io->addr)+(offset * io->regspacing));
41}
42
43#ifdef readq
44static unsigned char mem_inq(const struct si_sm_io *io, unsigned int offset)
45{
46 return (readq((io->addr)+(offset * io->regspacing)) >> io->regshift)
47 & 0xff;
48}
49
50static void mem_outq(const struct si_sm_io *io, unsigned int offset,
51 unsigned char b)
52{
53 writeq(b << io->regshift, (io->addr)+(offset * io->regspacing));
54}
55#endif
56
57static void mem_region_cleanup(struct si_sm_io *io, int num)
58{
59 unsigned long addr = io->addr_data;
60 int idx;
61
62 for (idx = 0; idx < num; idx++)
63 release_mem_region(addr + idx * io->regspacing,
64 io->regsize);
65}
66
67static void mem_cleanup(struct si_sm_io *io)
68{
69 if (io->addr) {
70 iounmap(io->addr);
71 mem_region_cleanup(io, io->io_size);
72 }
73}
74
75int ipmi_si_mem_setup(struct si_sm_io *io)
76{
77 unsigned long addr = io->addr_data;
78 int mapsize, idx;
79
80 if (!addr)
81 return -ENODEV;
82
83 io->io_cleanup = mem_cleanup;
84
85 /*
86 * Figure out the actual readb/readw/readl/etc routine to use based
87 * upon the register size.
88 */
89 switch (io->regsize) {
90 case 1:
91 io->inputb = intf_mem_inb;
92 io->outputb = intf_mem_outb;
93 break;
94 case 2:
95 io->inputb = intf_mem_inw;
96 io->outputb = intf_mem_outw;
97 break;
98 case 4:
99 io->inputb = intf_mem_inl;
100 io->outputb = intf_mem_outl;
101 break;
102#ifdef readq
103 case 8:
104 io->inputb = mem_inq;
105 io->outputb = mem_outq;
106 break;
107#endif
108 default:
109 dev_warn(io->dev, "Invalid register size: %d\n",
110 io->regsize);
111 return -EINVAL;
112 }
113
114 /*
115 * Some BIOSes reserve disjoint memory regions in their ACPI
116 * tables. This causes problems when trying to request the
117 * entire region. Therefore we must request each register
118 * separately.
119 */
120 for (idx = 0; idx < io->io_size; idx++) {
121 if (request_mem_region(addr + idx * io->regspacing,
122 io->regsize, DEVICE_NAME) == NULL) {
123 /* Undo allocations */
124 mem_region_cleanup(io, idx);
125 return -EIO;
126 }
127 }
128
129 /*
130 * Calculate the total amount of memory to claim. This is an
131 * unusual looking calculation, but it avoids claiming any
132 * more memory than it has to. It will claim everything
133 * between the first address to the end of the last full
134 * register.
135 */
136 mapsize = ((io->io_size * io->regspacing)
137 - (io->regspacing - io->regsize));
138 io->addr = ioremap(addr, mapsize);
139 if (io->addr == NULL) {
140 mem_region_cleanup(io, io->io_size);
141 return -EIO;
142 }
143 return 0;
144}
diff --git a/drivers/char/ipmi/ipmi_si_port_io.c b/drivers/char/ipmi/ipmi_si_port_io.c
new file mode 100644
index 000000000000..e5ce174fbeeb
--- /dev/null
+++ b/drivers/char/ipmi/ipmi_si_port_io.c
@@ -0,0 +1,112 @@
1
2#include <linux/io.h>
3#include "ipmi_si.h"
4
5static unsigned char port_inb(const struct si_sm_io *io, unsigned int offset)
6{
7 unsigned int addr = io->addr_data;
8
9 return inb(addr + (offset * io->regspacing));
10}
11
12static void port_outb(const struct si_sm_io *io, unsigned int offset,
13 unsigned char b)
14{
15 unsigned int addr = io->addr_data;
16
17 outb(b, addr + (offset * io->regspacing));
18}
19
20static unsigned char port_inw(const struct si_sm_io *io, unsigned int offset)
21{
22 unsigned int addr = io->addr_data;
23
24 return (inw(addr + (offset * io->regspacing)) >> io->regshift) & 0xff;
25}
26
27static void port_outw(const struct si_sm_io *io, unsigned int offset,
28 unsigned char b)
29{
30 unsigned int addr = io->addr_data;
31
32 outw(b << io->regshift, addr + (offset * io->regspacing));
33}
34
35static unsigned char port_inl(const struct si_sm_io *io, unsigned int offset)
36{
37 unsigned int addr = io->addr_data;
38
39 return (inl(addr + (offset * io->regspacing)) >> io->regshift) & 0xff;
40}
41
42static void port_outl(const struct si_sm_io *io, unsigned int offset,
43 unsigned char b)
44{
45 unsigned int addr = io->addr_data;
46
47 outl(b << io->regshift, addr+(offset * io->regspacing));
48}
49
50static void port_cleanup(struct si_sm_io *io)
51{
52 unsigned int addr = io->addr_data;
53 int idx;
54
55 if (addr) {
56 for (idx = 0; idx < io->io_size; idx++)
57 release_region(addr + idx * io->regspacing,
58 io->regsize);
59 }
60}
61
62int ipmi_si_port_setup(struct si_sm_io *io)
63{
64 unsigned int addr = io->addr_data;
65 int idx;
66
67 if (!addr)
68 return -ENODEV;
69
70 io->io_cleanup = port_cleanup;
71
72 /*
73 * Figure out the actual inb/inw/inl/etc routine to use based
74 * upon the register size.
75 */
76 switch (io->regsize) {
77 case 1:
78 io->inputb = port_inb;
79 io->outputb = port_outb;
80 break;
81 case 2:
82 io->inputb = port_inw;
83 io->outputb = port_outw;
84 break;
85 case 4:
86 io->inputb = port_inl;
87 io->outputb = port_outl;
88 break;
89 default:
90 dev_warn(io->dev, "Invalid register size: %d\n",
91 io->regsize);
92 return -EINVAL;
93 }
94
95 /*
96 * Some BIOSes reserve disjoint I/O regions in their ACPI
97 * tables. This causes problems when trying to register the
98 * entire I/O region. Therefore we must register each I/O
99 * port separately.
100 */
101 for (idx = 0; idx < io->io_size; idx++) {
102 if (request_region(addr + idx * io->regspacing,
103 io->regsize, DEVICE_NAME) == NULL) {
104 /* Undo allocations */
105 while (idx--)
106 release_region(addr + idx * io->regspacing,
107 io->regsize);
108 return -EIO;
109 }
110 }
111 return 0;
112}