diff options
-rw-r--r-- | drivers/rapidio/rio-scan.c | 59 | ||||
-rw-r--r-- | drivers/rapidio/rio-sysfs.c | 4 | ||||
-rw-r--r-- | include/linux/rio.h | 82 |
3 files changed, 75 insertions, 70 deletions
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 51f0af241eb7..45d14cd6b356 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c | |||
@@ -378,12 +378,30 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
378 | struct rio_dev *rdev; | 378 | struct rio_dev *rdev; |
379 | struct rio_switch *rswitch = NULL; | 379 | struct rio_switch *rswitch = NULL; |
380 | int result, rdid; | 380 | int result, rdid; |
381 | size_t size; | ||
382 | u32 swpinfo = 0; | ||
381 | 383 | ||
382 | rdev = kzalloc(sizeof(struct rio_dev), GFP_KERNEL); | 384 | size = sizeof(struct rio_dev); |
385 | if (rio_mport_read_config_32(port, destid, hopcount, | ||
386 | RIO_PEF_CAR, &result)) | ||
387 | return NULL; | ||
388 | |||
389 | if (result & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) { | ||
390 | rio_mport_read_config_32(port, destid, hopcount, | ||
391 | RIO_SWP_INFO_CAR, &swpinfo); | ||
392 | if (result & RIO_PEF_SWITCH) { | ||
393 | size += (RIO_GET_TOTAL_PORTS(swpinfo) * | ||
394 | sizeof(rswitch->nextdev[0])) + sizeof(*rswitch); | ||
395 | } | ||
396 | } | ||
397 | |||
398 | rdev = kzalloc(size, GFP_KERNEL); | ||
383 | if (!rdev) | 399 | if (!rdev) |
384 | return NULL; | 400 | return NULL; |
385 | 401 | ||
386 | rdev->net = net; | 402 | rdev->net = net; |
403 | rdev->pef = result; | ||
404 | rdev->swpinfo = swpinfo; | ||
387 | rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR, | 405 | rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR, |
388 | &result); | 406 | &result); |
389 | rdev->did = result >> 16; | 407 | rdev->did = result >> 16; |
@@ -397,8 +415,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
397 | rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR, | 415 | rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR, |
398 | &result); | 416 | &result); |
399 | rdev->asm_rev = result >> 16; | 417 | rdev->asm_rev = result >> 16; |
400 | rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR, | ||
401 | &rdev->pef); | ||
402 | if (rdev->pef & RIO_PEF_EXT_FEATURES) { | 418 | if (rdev->pef & RIO_PEF_EXT_FEATURES) { |
403 | rdev->efptr = result & 0xffff; | 419 | rdev->efptr = result & 0xffff; |
404 | rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid, | 420 | rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid, |
@@ -408,11 +424,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
408 | hopcount, RIO_EFB_ERR_MGMNT); | 424 | hopcount, RIO_EFB_ERR_MGMNT); |
409 | } | 425 | } |
410 | 426 | ||
411 | if (rdev->pef & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) { | ||
412 | rio_mport_read_config_32(port, destid, hopcount, | ||
413 | RIO_SWP_INFO_CAR, &rdev->swpinfo); | ||
414 | } | ||
415 | |||
416 | rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, | 427 | rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, |
417 | &rdev->src_ops); | 428 | &rdev->src_ops); |
418 | rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, | 429 | rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, |
@@ -449,12 +460,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
449 | 460 | ||
450 | /* If a PE has both switch and other functions, show it as a switch */ | 461 | /* If a PE has both switch and other functions, show it as a switch */ |
451 | if (rio_is_switch(rdev)) { | 462 | if (rio_is_switch(rdev)) { |
452 | rswitch = kzalloc(sizeof(*rswitch) + | 463 | rswitch = rdev->rswitch; |
453 | RIO_GET_TOTAL_PORTS(rdev->swpinfo) * | ||
454 | sizeof(rswitch->nextdev[0]), | ||
455 | GFP_KERNEL); | ||
456 | if (!rswitch) | ||
457 | goto cleanup; | ||
458 | rswitch->switchid = next_switchid; | 464 | rswitch->switchid = next_switchid; |
459 | rswitch->port_ok = 0; | 465 | rswitch->port_ok = 0; |
460 | rswitch->route_table = kzalloc(sizeof(u8)* | 466 | rswitch->route_table = kzalloc(sizeof(u8)* |
@@ -466,15 +472,13 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
466 | for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size); | 472 | for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size); |
467 | rdid++) | 473 | rdid++) |
468 | rswitch->route_table[rdid] = RIO_INVALID_ROUTE; | 474 | rswitch->route_table[rdid] = RIO_INVALID_ROUTE; |
469 | rdev->rswitch = rswitch; | ||
470 | rswitch->rdev = rdev; | ||
471 | dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, | 475 | dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, |
472 | rdev->rswitch->switchid); | 476 | rswitch->switchid); |
473 | rio_switch_init(rdev, do_enum); | 477 | rio_switch_init(rdev, do_enum); |
474 | 478 | ||
475 | if (do_enum && rdev->rswitch->clr_table) | 479 | if (do_enum && rswitch->clr_table) |
476 | rdev->rswitch->clr_table(port, destid, hopcount, | 480 | rswitch->clr_table(port, destid, hopcount, |
477 | RIO_GLOBAL_TABLE); | 481 | RIO_GLOBAL_TABLE); |
478 | 482 | ||
479 | list_add_tail(&rswitch->node, &rio_switches); | 483 | list_add_tail(&rswitch->node, &rio_switches); |
480 | 484 | ||
@@ -510,10 +514,9 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
510 | return rdev; | 514 | return rdev; |
511 | 515 | ||
512 | cleanup: | 516 | cleanup: |
513 | if (rswitch) { | 517 | if (rswitch->route_table) |
514 | kfree(rswitch->route_table); | 518 | kfree(rswitch->route_table); |
515 | kfree(rswitch); | 519 | |
516 | } | ||
517 | kfree(rdev); | 520 | kfree(rdev); |
518 | return NULL; | 521 | return NULL; |
519 | } | 522 | } |
@@ -1072,7 +1075,7 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port) | |||
1072 | */ | 1075 | */ |
1073 | static void rio_update_route_tables(struct rio_mport *port) | 1076 | static void rio_update_route_tables(struct rio_mport *port) |
1074 | { | 1077 | { |
1075 | struct rio_dev *rdev; | 1078 | struct rio_dev *rdev, *swrdev; |
1076 | struct rio_switch *rswitch; | 1079 | struct rio_switch *rswitch; |
1077 | u8 sport; | 1080 | u8 sport; |
1078 | u16 destid; | 1081 | u16 destid; |
@@ -1087,14 +1090,16 @@ static void rio_update_route_tables(struct rio_mport *port) | |||
1087 | continue; | 1090 | continue; |
1088 | 1091 | ||
1089 | if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { | 1092 | if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { |
1093 | swrdev = sw_to_rio_dev(rswitch); | ||
1094 | |||
1090 | /* Skip if destid ends in empty switch*/ | 1095 | /* Skip if destid ends in empty switch*/ |
1091 | if (rswitch->rdev->destid == destid) | 1096 | if (swrdev->destid == destid) |
1092 | continue; | 1097 | continue; |
1093 | 1098 | ||
1094 | sport = RIO_GET_PORT_NUM(rswitch->rdev->swpinfo); | 1099 | sport = RIO_GET_PORT_NUM(swrdev->swpinfo); |
1095 | 1100 | ||
1096 | if (rswitch->add_entry) { | 1101 | if (rswitch->add_entry) { |
1097 | rio_route_add_entry(rswitch->rdev, | 1102 | rio_route_add_entry(swrdev, |
1098 | RIO_GLOBAL_TABLE, destid, | 1103 | RIO_GLOBAL_TABLE, destid, |
1099 | sport, 0); | 1104 | sport, 0); |
1100 | rswitch->route_table[destid] = sport; | 1105 | rswitch->route_table[destid] = sport; |
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 137ed93ee33f..76b41853a877 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c | |||
@@ -217,7 +217,7 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev) | |||
217 | 217 | ||
218 | err = device_create_bin_file(&rdev->dev, &rio_config_attr); | 218 | err = device_create_bin_file(&rdev->dev, &rio_config_attr); |
219 | 219 | ||
220 | if (!err && rdev->rswitch) { | 220 | if (!err && (rdev->pef & RIO_PEF_SWITCH)) { |
221 | err = device_create_file(&rdev->dev, &dev_attr_routes); | 221 | err = device_create_file(&rdev->dev, &dev_attr_routes); |
222 | if (!err && rdev->rswitch->sw_sysfs) | 222 | if (!err && rdev->rswitch->sw_sysfs) |
223 | err = rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_CREATE); | 223 | err = rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_CREATE); |
@@ -239,7 +239,7 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev) | |||
239 | void rio_remove_sysfs_dev_files(struct rio_dev *rdev) | 239 | void rio_remove_sysfs_dev_files(struct rio_dev *rdev) |
240 | { | 240 | { |
241 | device_remove_bin_file(&rdev->dev, &rio_config_attr); | 241 | device_remove_bin_file(&rdev->dev, &rio_config_attr); |
242 | if (rdev->rswitch) { | 242 | if (rdev->pef & RIO_PEF_SWITCH) { |
243 | device_remove_file(&rdev->dev, &dev_attr_routes); | 243 | device_remove_file(&rdev->dev, &dev_attr_routes); |
244 | if (rdev->rswitch->sw_sysfs) | 244 | if (rdev->rswitch->sw_sysfs) |
245 | rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE); | 245 | rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE); |
diff --git a/include/linux/rio.h b/include/linux/rio.h index f6e25b3a6967..9b558856a8b6 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h | |||
@@ -71,9 +71,47 @@ extern struct device rio_bus; | |||
71 | extern struct list_head rio_devices; /* list of all devices */ | 71 | extern struct list_head rio_devices; /* list of all devices */ |
72 | 72 | ||
73 | struct rio_mport; | 73 | struct rio_mport; |
74 | struct rio_dev; | ||
74 | union rio_pw_msg; | 75 | union rio_pw_msg; |
75 | 76 | ||
76 | /** | 77 | /** |
78 | * struct rio_switch - RIO switch info | ||
79 | * @node: Node in global list of switches | ||
80 | * @switchid: Switch ID that is unique across a network | ||
81 | * @route_table: Copy of switch routing table | ||
82 | * @port_ok: Status of each port (one bit per port) - OK=1 or UNINIT=0 | ||
83 | * @add_entry: Callback for switch-specific route add function | ||
84 | * @get_entry: Callback for switch-specific route get function | ||
85 | * @clr_table: Callback for switch-specific clear route table function | ||
86 | * @set_domain: Callback for switch-specific domain setting function | ||
87 | * @get_domain: Callback for switch-specific domain get function | ||
88 | * @em_init: Callback for switch-specific error management init function | ||
89 | * @em_handle: Callback for switch-specific error management handler function | ||
90 | * @sw_sysfs: Callback that initializes switch-specific sysfs attributes | ||
91 | * @nextdev: Array of per-port pointers to the next attached device | ||
92 | */ | ||
93 | struct rio_switch { | ||
94 | struct list_head node; | ||
95 | u16 switchid; | ||
96 | u8 *route_table; | ||
97 | u32 port_ok; | ||
98 | int (*add_entry) (struct rio_mport *mport, u16 destid, u8 hopcount, | ||
99 | u16 table, u16 route_destid, u8 route_port); | ||
100 | int (*get_entry) (struct rio_mport *mport, u16 destid, u8 hopcount, | ||
101 | u16 table, u16 route_destid, u8 *route_port); | ||
102 | int (*clr_table) (struct rio_mport *mport, u16 destid, u8 hopcount, | ||
103 | u16 table); | ||
104 | int (*set_domain) (struct rio_mport *mport, u16 destid, u8 hopcount, | ||
105 | u8 sw_domain); | ||
106 | int (*get_domain) (struct rio_mport *mport, u16 destid, u8 hopcount, | ||
107 | u8 *sw_domain); | ||
108 | int (*em_init) (struct rio_dev *dev); | ||
109 | int (*em_handle) (struct rio_dev *dev, u8 swport); | ||
110 | int (*sw_sysfs) (struct rio_dev *dev, int create); | ||
111 | struct rio_dev *nextdev[0]; | ||
112 | }; | ||
113 | |||
114 | /** | ||
77 | * struct rio_dev - RIO device info | 115 | * struct rio_dev - RIO device info |
78 | * @global_list: Node in list of all RIO devices | 116 | * @global_list: Node in list of all RIO devices |
79 | * @net_list: Node in list of RIO devices in a network | 117 | * @net_list: Node in list of RIO devices in a network |
@@ -93,7 +131,6 @@ union rio_pw_msg; | |||
93 | * @phys_efptr: RIO device extended features pointer | 131 | * @phys_efptr: RIO device extended features pointer |
94 | * @em_efptr: RIO Error Management features pointer | 132 | * @em_efptr: RIO Error Management features pointer |
95 | * @dma_mask: Mask of bits of RIO address this device implements | 133 | * @dma_mask: Mask of bits of RIO address this device implements |
96 | * @rswitch: Pointer to &struct rio_switch if valid for this device | ||
97 | * @driver: Driver claiming this device | 134 | * @driver: Driver claiming this device |
98 | * @dev: Device model device | 135 | * @dev: Device model device |
99 | * @riores: RIO resources this device owns | 136 | * @riores: RIO resources this device owns |
@@ -101,6 +138,7 @@ union rio_pw_msg; | |||
101 | * @destid: Network destination ID (or associated destid for switch) | 138 | * @destid: Network destination ID (or associated destid for switch) |
102 | * @hopcount: Hopcount to this device | 139 | * @hopcount: Hopcount to this device |
103 | * @prev: Previous RIO device connected to the current one | 140 | * @prev: Previous RIO device connected to the current one |
141 | * @rswitch: struct rio_switch (if valid for this device) | ||
104 | */ | 142 | */ |
105 | struct rio_dev { | 143 | struct rio_dev { |
106 | struct list_head global_list; /* node in list of all RIO devices */ | 144 | struct list_head global_list; /* node in list of all RIO devices */ |
@@ -121,7 +159,6 @@ struct rio_dev { | |||
121 | u32 phys_efptr; | 159 | u32 phys_efptr; |
122 | u32 em_efptr; | 160 | u32 em_efptr; |
123 | u64 dma_mask; | 161 | u64 dma_mask; |
124 | struct rio_switch *rswitch; /* RIO switch info */ | ||
125 | struct rio_driver *driver; /* RIO driver claiming this device */ | 162 | struct rio_driver *driver; /* RIO driver claiming this device */ |
126 | struct device dev; /* LDM device structure */ | 163 | struct device dev; /* LDM device structure */ |
127 | struct resource riores[RIO_MAX_DEV_RESOURCES]; | 164 | struct resource riores[RIO_MAX_DEV_RESOURCES]; |
@@ -129,11 +166,13 @@ struct rio_dev { | |||
129 | u16 destid; | 166 | u16 destid; |
130 | u8 hopcount; | 167 | u8 hopcount; |
131 | struct rio_dev *prev; | 168 | struct rio_dev *prev; |
169 | struct rio_switch rswitch[0]; /* RIO switch info */ | ||
132 | }; | 170 | }; |
133 | 171 | ||
134 | #define rio_dev_g(n) list_entry(n, struct rio_dev, global_list) | 172 | #define rio_dev_g(n) list_entry(n, struct rio_dev, global_list) |
135 | #define rio_dev_f(n) list_entry(n, struct rio_dev, net_list) | 173 | #define rio_dev_f(n) list_entry(n, struct rio_dev, net_list) |
136 | #define to_rio_dev(n) container_of(n, struct rio_dev, dev) | 174 | #define to_rio_dev(n) container_of(n, struct rio_dev, dev) |
175 | #define sw_to_rio_dev(n) container_of(n, struct rio_dev, rswitch[0]) | ||
137 | 176 | ||
138 | /** | 177 | /** |
139 | * struct rio_msg - RIO message event | 178 | * struct rio_msg - RIO message event |
@@ -226,45 +265,6 @@ struct rio_net { | |||
226 | #define RIO_SW_SYSFS_CREATE 1 /* Create switch attributes */ | 265 | #define RIO_SW_SYSFS_CREATE 1 /* Create switch attributes */ |
227 | #define RIO_SW_SYSFS_REMOVE 0 /* Remove switch attributes */ | 266 | #define RIO_SW_SYSFS_REMOVE 0 /* Remove switch attributes */ |
228 | 267 | ||
229 | /** | ||
230 | * struct rio_switch - RIO switch info | ||
231 | * @node: Node in global list of switches | ||
232 | * @rdev: Associated RIO device structure | ||
233 | * @switchid: Switch ID that is unique across a network | ||
234 | * @route_table: Copy of switch routing table | ||
235 | * @port_ok: Status of each port (one bit per port) - OK=1 or UNINIT=0 | ||
236 | * @add_entry: Callback for switch-specific route add function | ||
237 | * @get_entry: Callback for switch-specific route get function | ||
238 | * @clr_table: Callback for switch-specific clear route table function | ||
239 | * @set_domain: Callback for switch-specific domain setting function | ||
240 | * @get_domain: Callback for switch-specific domain get function | ||
241 | * @em_init: Callback for switch-specific error management initialization function | ||
242 | * @em_handle: Callback for switch-specific error management handler function | ||
243 | * @sw_sysfs: Callback that initializes switch-specific sysfs attributes | ||
244 | * @nextdev: Array of per-port pointers to the next attached device | ||
245 | */ | ||
246 | struct rio_switch { | ||
247 | struct list_head node; | ||
248 | struct rio_dev *rdev; | ||
249 | u16 switchid; | ||
250 | u8 *route_table; | ||
251 | u32 port_ok; | ||
252 | int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount, | ||
253 | u16 table, u16 route_destid, u8 route_port); | ||
254 | int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount, | ||
255 | u16 table, u16 route_destid, u8 * route_port); | ||
256 | int (*clr_table) (struct rio_mport *mport, u16 destid, u8 hopcount, | ||
257 | u16 table); | ||
258 | int (*set_domain) (struct rio_mport *mport, u16 destid, u8 hopcount, | ||
259 | u8 sw_domain); | ||
260 | int (*get_domain) (struct rio_mport *mport, u16 destid, u8 hopcount, | ||
261 | u8 *sw_domain); | ||
262 | int (*em_init) (struct rio_dev *dev); | ||
263 | int (*em_handle) (struct rio_dev *dev, u8 swport); | ||
264 | int (*sw_sysfs) (struct rio_dev *dev, int create); | ||
265 | struct rio_dev *nextdev[0]; | ||
266 | }; | ||
267 | |||
268 | /* Low-level architecture-dependent routines */ | 268 | /* Low-level architecture-dependent routines */ |
269 | 269 | ||
270 | /** | 270 | /** |