diff options
Diffstat (limited to 'drivers/rapidio/rio.c')
-rw-r--r-- | drivers/rapidio/rio.c | 84 |
1 files changed, 57 insertions, 27 deletions
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index cc2a3b74d0f0..c29719cacbca 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "rio.h" | 32 | #include "rio.h" |
33 | 33 | ||
34 | static LIST_HEAD(rio_mports); | 34 | static LIST_HEAD(rio_mports); |
35 | static unsigned char next_portid; | ||
35 | 36 | ||
36 | /** | 37 | /** |
37 | * rio_local_get_device_id - Get the base/extended device id for a port | 38 | * rio_local_get_device_id - Get the base/extended device id for a port |
@@ -68,9 +69,13 @@ int rio_request_inb_mbox(struct rio_mport *mport, | |||
68 | void (*minb) (struct rio_mport * mport, void *dev_id, int mbox, | 69 | void (*minb) (struct rio_mport * mport, void *dev_id, int mbox, |
69 | int slot)) | 70 | int slot)) |
70 | { | 71 | { |
71 | int rc = 0; | 72 | int rc = -ENOSYS; |
73 | struct resource *res; | ||
72 | 74 | ||
73 | struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); | 75 | if (mport->ops->open_inb_mbox == NULL) |
76 | goto out; | ||
77 | |||
78 | res = kmalloc(sizeof(struct resource), GFP_KERNEL); | ||
74 | 79 | ||
75 | if (res) { | 80 | if (res) { |
76 | rio_init_mbox_res(res, mbox, mbox); | 81 | rio_init_mbox_res(res, mbox, mbox); |
@@ -88,7 +93,7 @@ int rio_request_inb_mbox(struct rio_mport *mport, | |||
88 | /* Hook the inbound message callback */ | 93 | /* Hook the inbound message callback */ |
89 | mport->inb_msg[mbox].mcback = minb; | 94 | mport->inb_msg[mbox].mcback = minb; |
90 | 95 | ||
91 | rc = rio_open_inb_mbox(mport, dev_id, mbox, entries); | 96 | rc = mport->ops->open_inb_mbox(mport, dev_id, mbox, entries); |
92 | } else | 97 | } else |
93 | rc = -ENOMEM; | 98 | rc = -ENOMEM; |
94 | 99 | ||
@@ -106,10 +111,13 @@ int rio_request_inb_mbox(struct rio_mport *mport, | |||
106 | */ | 111 | */ |
107 | int rio_release_inb_mbox(struct rio_mport *mport, int mbox) | 112 | int rio_release_inb_mbox(struct rio_mport *mport, int mbox) |
108 | { | 113 | { |
109 | rio_close_inb_mbox(mport, mbox); | 114 | if (mport->ops->close_inb_mbox) { |
115 | mport->ops->close_inb_mbox(mport, mbox); | ||
110 | 116 | ||
111 | /* Release the mailbox resource */ | 117 | /* Release the mailbox resource */ |
112 | return release_resource(mport->inb_msg[mbox].res); | 118 | return release_resource(mport->inb_msg[mbox].res); |
119 | } else | ||
120 | return -ENOSYS; | ||
113 | } | 121 | } |
114 | 122 | ||
115 | /** | 123 | /** |
@@ -129,9 +137,13 @@ int rio_request_outb_mbox(struct rio_mport *mport, | |||
129 | int entries, | 137 | int entries, |
130 | void (*moutb) (struct rio_mport * mport, void *dev_id, int mbox, int slot)) | 138 | void (*moutb) (struct rio_mport * mport, void *dev_id, int mbox, int slot)) |
131 | { | 139 | { |
132 | int rc = 0; | 140 | int rc = -ENOSYS; |
141 | struct resource *res; | ||
133 | 142 | ||
134 | struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); | 143 | if (mport->ops->open_outb_mbox == NULL) |
144 | goto out; | ||
145 | |||
146 | res = kmalloc(sizeof(struct resource), GFP_KERNEL); | ||
135 | 147 | ||
136 | if (res) { | 148 | if (res) { |
137 | rio_init_mbox_res(res, mbox, mbox); | 149 | rio_init_mbox_res(res, mbox, mbox); |
@@ -149,7 +161,7 @@ int rio_request_outb_mbox(struct rio_mport *mport, | |||
149 | /* Hook the inbound message callback */ | 161 | /* Hook the inbound message callback */ |
150 | mport->outb_msg[mbox].mcback = moutb; | 162 | mport->outb_msg[mbox].mcback = moutb; |
151 | 163 | ||
152 | rc = rio_open_outb_mbox(mport, dev_id, mbox, entries); | 164 | rc = mport->ops->open_outb_mbox(mport, dev_id, mbox, entries); |
153 | } else | 165 | } else |
154 | rc = -ENOMEM; | 166 | rc = -ENOMEM; |
155 | 167 | ||
@@ -167,10 +179,13 @@ int rio_request_outb_mbox(struct rio_mport *mport, | |||
167 | */ | 179 | */ |
168 | int rio_release_outb_mbox(struct rio_mport *mport, int mbox) | 180 | int rio_release_outb_mbox(struct rio_mport *mport, int mbox) |
169 | { | 181 | { |
170 | rio_close_outb_mbox(mport, mbox); | 182 | if (mport->ops->close_outb_mbox) { |
183 | mport->ops->close_outb_mbox(mport, mbox); | ||
171 | 184 | ||
172 | /* Release the mailbox resource */ | 185 | /* Release the mailbox resource */ |
173 | return release_resource(mport->outb_msg[mbox].res); | 186 | return release_resource(mport->outb_msg[mbox].res); |
187 | } else | ||
188 | return -ENOSYS; | ||
174 | } | 189 | } |
175 | 190 | ||
176 | /** | 191 | /** |
@@ -1120,36 +1135,51 @@ static int __devinit rio_init(void) | |||
1120 | return 0; | 1135 | return 0; |
1121 | } | 1136 | } |
1122 | 1137 | ||
1123 | device_initcall(rio_init); | ||
1124 | |||
1125 | int __devinit rio_init_mports(void) | 1138 | int __devinit rio_init_mports(void) |
1126 | { | 1139 | { |
1127 | int rc = 0; | ||
1128 | struct rio_mport *port; | 1140 | struct rio_mport *port; |
1129 | 1141 | ||
1130 | list_for_each_entry(port, &rio_mports, node) { | 1142 | list_for_each_entry(port, &rio_mports, node) { |
1131 | if (!request_mem_region(port->iores.start, | ||
1132 | resource_size(&port->iores), | ||
1133 | port->name)) { | ||
1134 | printk(KERN_ERR | ||
1135 | "RIO: Error requesting master port region 0x%016llx-0x%016llx\n", | ||
1136 | (u64)port->iores.start, (u64)port->iores.end); | ||
1137 | rc = -ENOMEM; | ||
1138 | goto out; | ||
1139 | } | ||
1140 | |||
1141 | if (port->host_deviceid >= 0) | 1143 | if (port->host_deviceid >= 0) |
1142 | rio_enum_mport(port); | 1144 | rio_enum_mport(port); |
1143 | else | 1145 | else |
1144 | rio_disc_mport(port); | 1146 | rio_disc_mport(port); |
1145 | } | 1147 | } |
1146 | 1148 | ||
1147 | out: | 1149 | rio_init(); |
1148 | return rc; | 1150 | |
1151 | return 0; | ||
1149 | } | 1152 | } |
1150 | 1153 | ||
1154 | device_initcall_sync(rio_init_mports); | ||
1155 | |||
1156 | static int hdids[RIO_MAX_MPORTS + 1]; | ||
1157 | |||
1158 | static int rio_get_hdid(int index) | ||
1159 | { | ||
1160 | if (!hdids[0] || hdids[0] <= index || index >= RIO_MAX_MPORTS) | ||
1161 | return -1; | ||
1162 | |||
1163 | return hdids[index + 1]; | ||
1164 | } | ||
1165 | |||
1166 | static int rio_hdid_setup(char *str) | ||
1167 | { | ||
1168 | (void)get_options(str, ARRAY_SIZE(hdids), hdids); | ||
1169 | return 1; | ||
1170 | } | ||
1171 | |||
1172 | __setup("riohdid=", rio_hdid_setup); | ||
1173 | |||
1151 | void rio_register_mport(struct rio_mport *port) | 1174 | void rio_register_mport(struct rio_mport *port) |
1152 | { | 1175 | { |
1176 | if (next_portid >= RIO_MAX_MPORTS) { | ||
1177 | pr_err("RIO: reached specified max number of mports\n"); | ||
1178 | return; | ||
1179 | } | ||
1180 | |||
1181 | port->id = next_portid++; | ||
1182 | port->host_deviceid = rio_get_hdid(port->id); | ||
1153 | list_add_tail(&port->node, &rio_mports); | 1183 | list_add_tail(&port->node, &rio_mports); |
1154 | } | 1184 | } |
1155 | 1185 | ||